ruvnet/ruflo · error

Agent ${this.id} has reached max concurrent tasks

Error message

Agent ${this.id} has reached max concurrent tasks

What it means

Thrown by AgenticFlowAgent#executeTask (v3/@claude-flow/integration/src/agentic-flow-agent.ts:495) when currentTaskCount >= config.maxConcurrentTasks. The agent enforces its own concurrency budget before accepting work; note the counter is incremented synchronously on accept, so it reflects in-flight tasks.

Source

Thrown at v3/@claude-flow/integration/src/agentic-flow-agent.ts:495

   * to agentic-flow's Agent.execute() which leverages:
   * - Flash Attention for 2.49x-7.47x faster processing
   * - SONA learning for real-time adaptation
   * - AgentDB for 150x-12,500x faster memory retrieval
   *
   * @param task - Task to execute
   * @returns Task result with output or error
   */
  async executeTask(task: Task): Promise<TaskResult> {
    this.ensureInitialized();

    // Validate agent is available
    if (this.status === 'terminated' || this.status === 'error') {
      throw new Error(`Agent ${this.id} is not available (status: ${this.status})`);
    }

    // Check concurrent task limit
    if (this.currentTaskCount >= this.config.maxConcurrentTasks) {
      throw new Error(`Agent ${this.id} has reached max concurrent tasks`);
    }

    this.currentTask = task;
    this.currentTaskCount++;
    this.status = 'busy';
    this.taskStartTime = Date.now();
    this.lastActivity = new Date();

    this.emit('task-started', {
      agentId: this.id,
      taskId: task.id,
      taskType: task.type,
    });

    try {
      let output: unknown;

      // ADR-001: Delegate to agentic-flow when available for optimized execution

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Raise maxConcurrentTasks in the AgentConfig when the agent is expected to handle more parallel work.
  2. Track in-flight promises per agent and only dispatch when below the limit (simple semaphore around executeTask).
  3. Use a worker pool that respects agent capacity instead of round-robin dispatch.
  4. If counts look stuck, verify every code path decrements currentTaskCount (a never-settling task leaks slots) and add timeouts to task execution.

Example fix

// before
await Promise.all(tasks.map((t) => agent.executeTask(t))); // maxConcurrentTasks = 1

// after
const sem = new Semaphore(agent.config.maxConcurrentTasks);
await Promise.all(tasks.map((t) => sem.withLock(() => agent.executeTask(t))));
// or: new AgenticFlowAgent({ ...cfg, maxConcurrentTasks: 10 })
Defensive patterns

Strategy: validation

Validate before calling

class Semaphore {
  private active = 0; private queue: (() => void)[] = [];
  constructor(private n: number) {}
  async withLock<T>(fn: () => Promise<T>): Promise<T> {
    if (this.active >= this.n) await new Promise<void>((r) => this.queue.push(r));
    this.active++;
    try { return await fn(); } finally { this.active--; this.queue.shift()?.(); }
  }
}
// usage: sem.withLock(() => agent.executeTask(task))

Type guard

function canAccept(agent: { currentTaskCount: number; config: { maxConcurrentTasks: number } }): boolean {
  return agent.currentTaskCount < agent.config.maxConcurrentTasks;
}

Try / catch

try {
  return await agent.executeTask(task);
} catch (e) {
  if (/max concurrent tasks/.test((e as Error).message)) {
    await waitForSlot(agent); // poll currentTaskCount or subscribe to completion events
    return agent.executeTask(task);
  }
  throw e;
}

Prevention

When it happens

Trigger: Dispatching more parallel tasks than the agent's maxConcurrentTasks (default is small, often 1); fire-and-forget executeTask calls that stack up; a worker pool that keeps assigning to the same agent instead of load-balancing; an agent stuck 'busy' because a prior task never resolved and the count never decremented.

Common situations: Raising parallelism (Promise.all over many tasks) without raising maxConcurrentTasks in the agent config; a hung external call inside a task leaking a slot; tests that await nothing and over-submit.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/209868c755fc6b73. Report an issue: GitHub.