ruvnet/ruflo · error
Maximum agent limit (${this.config.maxConcurrentAgents}) rea
Error message
Maximum agent limit (${this.config.maxConcurrentAgents}) reached What it means
spawnAgent() caps concurrent agents at config.maxConcurrentAgents (default 15), counting every entry in the agents map. Importantly, terminateAgent() only flips status to 'terminated' and keeps the entry in the map, so terminated agents still consume slots — the limit is reached on total registered agents, not live ones.
Source
Thrown at v3/@claude-flow/plugins/src/integrations/agentic-flow.ts:221
this.swarmInitialized = false;
this.swarmTopology = undefined;
this.config.logger?.info('Swarm shutdown complete');
}
// =========================================================================
// Agent Management
// =========================================================================
/**
* Spawn a new agent.
*/
async spawnAgent(options: AgentSpawnOptions): Promise<SpawnedAgent> {
if (!this.swarmInitialized) {
throw new Error('Swarm not initialized');
}
if (this.agents.size >= (this.config.maxConcurrentAgents ?? 15)) {
throw new Error(`Maximum agent limit (${this.config.maxConcurrentAgents}) reached`);
}
const id = options.id ?? `agent-${this.nextAgentId++}`;
if (this.agents.has(id)) {
throw new Error(`Agent ${id} already exists`);
}
const agent: SpawnedAgent = {
id,
type: options.type,
status: 'active',
capabilities: options.capabilities ?? [],
parentId: options.parentId,
spawnedAt: new Date(),
};
this.agents.set(id, agent);View on GitHub (pinned to fa13ee4ad6)
Solutions
- Set config.maxConcurrentAgents to your intended pool size when constructing the integration
- Reuse existing active/idle agents (orchestrateTask without agentId auto-picks one) instead of spawning per task
- Size spawn counts against the cap you configured, accounting for terminated-but-present entries
Example fix
// before
const flow = new AgenticFlowIntegration({ logger }); // default cap 15
for (let i = 0; i < 30; i++) await flow.spawnAgent({ type: 'coder' }); // throws at #16
// after
const flow = new AgenticFlowIntegration({ logger, maxConcurrentAgents: 30 });
for (let i = 0; i < 30; i++) await flow.spawnAgent({ type: 'coder' }); Defensive patterns
Strategy: validation
Validate before calling
const MAX = 30;
const spawned = new Set<string>();
async function safeSpawn(opts: AgentSpawnOptions): Promise<SpawnedAgent> {
if (spawned.size >= MAX) {
throw new Error(`agent budget exhausted (${MAX}); terminate or raise maxConcurrentAgents`);
}
const agent = await flow.spawnAgent(opts);
spawned.add(agent.id);
return agent;
}
// construct with matching cap: new AgenticFlowIntegration({ maxConcurrentAgents: MAX }) Prevention
- Set maxConcurrentAgents to your real pool size at construction
- Remember terminated agents still occupy slots in this implementation
- Prefer reusing active/idle agents over spawning per task
When it happens
Trigger: Spawning the 16th agent with the default cap; bulk-spawning a worker pool larger than maxConcurrentAgents; repeatedly spawn/terminate cycles that never free slots because terminated entries remain in the map.
Common situations: Workloads sized above the default 15 agents; forgetting to raise maxConcurrentAgents in the integration config; assuming termination frees capacity when it does not.
Related errors
- Max sessions (${this.config.maxSessions}) reached
- Swarm not initialized
- Agent ${id} already exists
- Agent ${agentId} not found
- No available agents
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/78e41ef760f6e721.
Report an issue: GitHub.