ruvnet/ruflo · error

Maximum agents (${this.config.maxAgents}) reached

Error message

Maximum agents (${this.config.maxAgents}) reached

What it means

registerAgent() enforces the coordinator-level maxAgents ceiling: once state.agents.size reaches config.maxAgents, further registrations throw before an agent id is minted. This limit is independent of the TopologyManager maxAgents, so in a unified setup both limits apply and the lower one wins.

Source

Thrown at v3/@claude-flow/swarm/src/unified-coordinator.ts:305

    if (this.state.status !== 'paused') {
      return;
    }

    this.startBackgroundProcesses();
    this.state.status = 'running';

    this.emitEvent('swarm.resumed', { swarmId: this.state.id.id });
  }

  // ===== AGENT MANAGEMENT =====

  async registerAgent(
    agentData: Omit<AgentState, 'id'>
  ): Promise<string> {
    const startTime = performance.now();

    if (this.state.agents.size >= this.config.maxAgents) {
      throw new Error(`Maximum agents (${this.config.maxAgents}) reached`);
    }

    this.agentCounter++;
    const agentId: AgentId = {
      id: `agent_${this.state.id.id}_${this.agentCounter}`,
      swarmId: this.state.id.id,
      type: agentData.type,
      instance: this.agentCounter,
    };

    const agent: AgentState = {
      ...agentData,
      id: agentId,
      lastHeartbeat: new Date(),
      connections: [],
    };

    // Add to state

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Raise maxAgents in the UnifiedSwarmCoordinator config to cover the whole fleet
  2. Terminate or deregister idle/terminated agents before registering new ones
  3. Pre-check with getAllAgents().length against config.maxAgents and shed load instead of throwing

Example fix

// before
const coordinator = new UnifiedSwarmCoordinator({ ...baseConfig, maxAgents: 8 });
await Promise.all(agents.map(a => coordinator.registerAgent(a))); // throws at the 9th

// after
const coordinator = new UnifiedSwarmCoordinator({ ...baseConfig, maxAgents: agents.length + 4 });
await Promise.all(agents.map(a => coordinator.registerAgent(a)));
Defensive patterns

Strategy: validation

Validate before calling

const current = coordinator.getAllAgents();
if (current.length >= config.maxAgents) {
  const idle = current.filter(a => a.status === 'idle');
  await terminateIdleAgents(idle); // free slots before scaling up
}
const agentId = await coordinator.registerAgent(agentData);

Type guard

function hasAgentCapacity(coordinator: UnifiedSwarmCoordinator, maxAgents: number): boolean {
  return coordinator.getAllAgents().length < maxAgents;
}

Try / catch

try {
  await coordinator.registerAgent(agentData);
} catch (err) {
  if (err instanceof Error && err.message.includes('Maximum agents')) {
    await terminateIdleAgents(coordinator.getAllAgents().filter(a => a.status === 'idle'));
    return coordinator.registerAgent(agentData);
  }
  throw err;
}

Prevention

When it happens

Trigger: registerAgent() calls exceeding config.maxAgents; autoscaling that registers without tracking the current count; agent entries that were never deregistered accumulating in state.agents.

Common situations: Raising only the topology maxAgents but not the coordinator config; long-lived swarms retaining terminated agents in state.agents; test suites sharing one coordinator instance.

Related errors


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