Skip to content

Sceat/agent-pool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

agent-pool banner

πŸ”„ agent-pool

A workaround for Claude Code's memory leak issues. Spawn agents once, reuse indefinitely.

claude mcp add agent-pool -- npx -y github:Sceat/agent-pool


⚠️ Security Warning

SPAWNED AGENTS RUN WITH ALL PERMISSIONS BYPASSED

Agents are spawned with --dangerously-skip-permissions, meaning they can:

  • Execute any shell command without approval
  • Read/write any file on your system
  • Access network resources freely
  • Inherit your full environment (env vars, credentials, SSH keys)

This is intentionalβ€”orchestration requires agents to work autonomously. However:

  • βœ… Only use trusted agent definitions from sources you control
  • βœ… Review agent prompts in agents/*.md before running
  • ❌ Never run untrusted agents or agent definitions from unknown sources

You are responsible for what your agents do.


Why This Exists

Claude Code's native Task tool has critical memory leak issues that cause processes to grow from hundreds of MB to tens of GB, eventually crashing:

Issue Description
#7020 Sub-agent orchestration: 450MB β†’ 30GB, then crashes
#4953 Process grows to 120GB+ RAM, OOM killed
#11315 129GB virtual memory consumption
#11155 Bash output stored in memory forever, 90GB+ usage
#8382 v2.0.0: 26GB per process

The root cause: Every Task tool call spawns a fresh subprocess. The memory accumulates and is never released.

agent-pool's solution: Keep Claude CLI subprocesses alive and use /clear to reset context while preserving the warm prompt cache. No new processes = no memory leak.


How It Works

Native Task Tool (leaky):              agent-pool (stable):
──────────────────────────             ──────────────────────
Task 1 β†’ spawn β†’ 450MB                 Warmup β†’ spawn β†’ 450MB
Task 2 β†’ spawn β†’ 900MB ↑               Task 1 β†’ /clear β†’ 450MB (cached)
Task 3 β†’ spawn β†’ 1.3GB ↑               Task 2 β†’ /clear β†’ 450MB (cached)
Task 4 β†’ spawn β†’ 1.7GB ↑               Task 3 β†’ /clear β†’ 450MB (cached)
...                                    ...
Task N β†’ OOM KILLED πŸ’€                  Task N β†’ still 450MB βœ“

Bonus: Same process = same system prompt = prompt cache hits = ~90% token savings.


Quick Start

claude mcp add agent-pool -- npx -y github:Sceat/agent-pool
// Warm up agent (optional, creates prompt cache)
mcp__agent-pool__warmup({ agent: "code-reviewer" })

// Send tasks - all reuse the same process
mcp__agent-pool__invoke({ agent: "code-reviewer", task: "Review src/auth.js" })
mcp__agent-pool__invoke({ agent: "code-reviewer", task: "Review src/api.ts" })
mcp__agent-pool__invoke({ agent: "code-reviewer", task: "Review src/db.js" })

// Check active agents
mcp__agent-pool__list()

API Reference

Tool Description
invoke(agent, task) Send task to agent, get result, auto-reset context with /clear
warmup(agent) Pre-spawn agent to warm up prompt cache (optional)
list() Show active agents with PIDs
reset(agent) Kill agent process (respawns on next invoke)

Token Savings

Tasks Native Task agent-pool Savings
1 2,000 2,000 0%
3 6,000 2,600 57%
5 10,000 3,200 68%
10 20,000 4,700 76%

System prompt (~1,500 tokens) is cached after first call. Subsequent calls only pay for task content.


Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Claude Code                              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           β”‚ MCP Protocol
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              agent-pool MCP Server (Node.js)                 β”‚
β”‚  invoke() β”‚ warmup() β”‚ list() β”‚ reset()                     β”‚
β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
      β”‚           β”‚           β”‚           β”‚
   β”Œβ”€β”€β”΄β”€β”€β”     β”Œβ”€β”€β”΄β”€β”€β”     β”Œβ”€β”€β”΄β”€β”€β”     β”Œβ”€β”€β”΄β”€β”€β”
   β”‚Agentβ”‚     β”‚Agentβ”‚     β”‚Agentβ”‚     β”‚Agentβ”‚  ← Persistent processes
   β”‚ PID β”‚     β”‚ PID β”‚     β”‚ PID β”‚     β”‚ PID β”‚    (not respawned)
   β””β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”˜     β””β”€β”€β”€β”€β”€β”˜
      ↑           ↑           ↑           ↑
   /clear      /clear      /clear      /clear   ← Context reset
   (cache)     (cache)     (cache)     (cache)    (cache preserved)

Creating Custom Agents

Create agents/my-agent.md with YAML frontmatter:

---
name: my-agent
description: What this agent does
skills:
  - skill-name
expertise:
  - expertise-name
---

Frontmatter Headers

Header Description
name Agent identifier (used in invoke({ agent: "name" }))
description What the agent does (shown in list() output)
skills List of skill modules to inject (loaded from SKILLS_DIR)
expertise List of expertise modules to inject (loaded from EXPERTISE_DIR)

Skills & Expertise Injection: Content from referenced skill/expertise files gets injected into the agent's system prompt at spawn time. This allows modular composition of agent capabilities.

Then invoke: mcp__agent-pool__invoke({ agent: "my-agent", task: "..." })


πŸ’‘ Pro Tips

Disable MCP servers for main orchestrator, enable only for subagents

When using an orchestrator pattern, the main Claude instance doesn't need direct tool accessβ€”it should only delegate to specialized agents.

Why this matters:

  • Reduces context pollution - Main instance focuses on orchestration, not tool outputs
  • Enforces the pattern - Prevents accidental direct tool use
  • Cleaner separation - Orchestrator thinks, subagents act

Tool access pattern:

Instance Tools
Main orchestrator mcp__agent-pool__invoke, Task, AskUserQuestion, TodoWrite
Subagents Full MCP access (Bash, Read, Write, Grep, etc.)

How to configure:

  1. CLAUDE.md approach - Forbid direct tool use in your orchestrator's instructions:

    # Orchestrator Rules
    - NEVER use Bash, Read, Write, Edit, or Grep directly
    - ALWAYS delegate work to specialized agents via mcp__agent-pool__invoke
    - Only use AskUserQuestion for user clarification
  2. Selective MCP registration - Only register agent-pool for the main instance, not file/shell MCPs

  3. Hooks - Use Claude Code hooks to block certain tools for the main instance

This pattern keeps your orchestrator clean and forces proper delegation.


Troubleshooting

Issue Solution
Agent not found Check agents/name.md exists and name: in frontmatter matches
Task timeout Run reset({ agent: "name" }) to kill stuck process
Plugin not loading Verify plugin.json exists, restart Claude Code completely
High memory usage Check you're using agent-pool, not native Task tool

Full guide: docs/TROUBLESHOOTING.md


Documentation


Requirements

  • Claude CLI 2.0+ with --input-format stream-json support
  • Node.js 18+

License

MIT


Made for Claude Code developers tired of OOM kills

Report Bug Β· Request Feature

About

Persistent multi-agent orchestration MCP plugin for Claude Code. Spawns agents once, reuses with /clear for maximum token efficiency.

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors