BUG-HUNT: [resource] Memory leak from unbounded task accumulation in Agent base class #7067

Open
opened 2026-04-10 07:28:37 +00:00 by HAL9000 · 1 comment
Owner

Bug Report: [resource] — Memory leak from unbounded task accumulation in Agent base class

Severity Assessment

  • Impact: Memory exhaustion in long-running agents leading to performance degradation and potential crashes
  • Likelihood: High in production agents that process many messages over time
  • Priority: High

Location

  • File: src/cleveragents/agents/base.py
  • Function/Class: Agent._setup_processing_pipeline
  • Lines: 30-33

Description

The Agent base class accumulates completed asyncio tasks in the _tasks list indefinitely without cleanup, causing a memory leak in long-running agents.

Evidence

def _setup_processing_pipeline(self) -> None:
    def _on_next(msg: Any) -> None:
        task = asyncio.create_task(self._process_wrapper(msg))
        self._tasks.append(task)  # Tasks are never removed when complete

    self.input_stream.subscribe(
        on_next=_on_next,
        on_error=self.output_stream.on_error,
    )

The _tasks list grows indefinitely as new messages are processed, even after tasks complete successfully. Each completed task retains its result and exception information in memory.

Expected Behavior

Completed tasks should be cleaned up automatically or the task list should have a bounded size with automatic cleanup.

Actual Behavior

The _tasks list grows without bounds, consuming more memory over time as more messages are processed.

Suggested Fix

Implement automatic cleanup of completed tasks:

def _setup_processing_pipeline(self) -> None:
    def _on_next(msg: Any) -> None:
        # Clean up completed tasks before adding new ones
        self._tasks = [t for t in self._tasks if not t.done()]
        
        task = asyncio.create_task(self._process_wrapper(msg))
        self._tasks.append(task)
        
        # Alternatively, use a bounded deque with cleanup callback:
        task.add_done_callback(lambda t: self._cleanup_task(t))

    self.input_stream.subscribe(
        on_next=_on_next,
        on_error=self.output_stream.on_error,
    )

def _cleanup_task(self, task: asyncio.Task[Any]) -> None:
    try:
        self._tasks.remove(task)
    except ValueError:
        pass  # Task already removed

Category

resource

TDD Note

After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_, and @tdd_expected_fail to prove the bug exists before fixing it.

[Bug Hunt Cycle 2 Batch 3]

Discovered by: Worker 17 Shared Utilities
Module Focus: Cross-cutting helper components


Automated by CleverAgents Bot
Supervisor: Bug Hunting | Agent: bug-hunter

## Bug Report: [resource] — Memory leak from unbounded task accumulation in Agent base class ### Severity Assessment - **Impact**: Memory exhaustion in long-running agents leading to performance degradation and potential crashes - **Likelihood**: High in production agents that process many messages over time - **Priority**: High ### Location - **File**: `src/cleveragents/agents/base.py` - **Function/Class**: `Agent._setup_processing_pipeline` - **Lines**: 30-33 ### Description The Agent base class accumulates completed asyncio tasks in the `_tasks` list indefinitely without cleanup, causing a memory leak in long-running agents. ### Evidence ```python def _setup_processing_pipeline(self) -> None: def _on_next(msg: Any) -> None: task = asyncio.create_task(self._process_wrapper(msg)) self._tasks.append(task) # Tasks are never removed when complete self.input_stream.subscribe( on_next=_on_next, on_error=self.output_stream.on_error, ) ``` The `_tasks` list grows indefinitely as new messages are processed, even after tasks complete successfully. Each completed task retains its result and exception information in memory. ### Expected Behavior Completed tasks should be cleaned up automatically or the task list should have a bounded size with automatic cleanup. ### Actual Behavior The `_tasks` list grows without bounds, consuming more memory over time as more messages are processed. ### Suggested Fix Implement automatic cleanup of completed tasks: ```python def _setup_processing_pipeline(self) -> None: def _on_next(msg: Any) -> None: # Clean up completed tasks before adding new ones self._tasks = [t for t in self._tasks if not t.done()] task = asyncio.create_task(self._process_wrapper(msg)) self._tasks.append(task) # Alternatively, use a bounded deque with cleanup callback: task.add_done_callback(lambda t: self._cleanup_task(t)) self.input_stream.subscribe( on_next=_on_next, on_error=self.output_stream.on_error, ) def _cleanup_task(self, task: asyncio.Task[Any]) -> None: try: self._tasks.remove(task) except ValueError: pass # Task already removed ``` ### Category resource ### TDD Note After this bug issue is verified, a corresponding Type/Testing issue will be created for TDD. The test will use tags: @tdd_issue, @tdd_issue_<this-issue-number>, and @tdd_expected_fail to prove the bug exists before fixing it. ### [Bug Hunt Cycle 2 Batch 3] **Discovered by:** Worker 17 Shared Utilities **Module Focus:** Cross-cutting helper components --- **Automated by CleverAgents Bot** Supervisor: Bug Hunting | Agent: bug-hunter
Author
Owner

Verified — Resource leak: unbounded task accumulation in Agent base class. MoSCoW: Should-have. Priority: High.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: project-owner-pool-supervisor

✅ **Verified** — Resource leak: unbounded task accumulation in Agent base class. MoSCoW: Should-have. Priority: High. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: project-owner-pool-supervisor
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#7067
No description provided.