Multi-Agent Orchestration
\nOpenCrabs supports spawning specialized sub-agents that run autonomously in isolated sessions. Each child agent gets its own context, tool registry, and cancel token. Introduced in v0.2.97 with a typed agent system and team orchestration.
\nAgent Types
\nWhen spawning an agent, an agent_type parameter selects a specialized role with a curated tool set:
| Type | Role | Tools |
|---|---|---|
general | Full-capability agent (default) | All parent tools minus recursive/dangerous |
explore | Fast codebase navigation (read-only) | read_file, glob, grep, ls |
plan | Architecture planning (read + analysis) | read_file, glob, grep, ls, bash |
code | Implementation (full write access) | All parent tools minus recursive/dangerous |
research | Web search + documentation lookup | read_file, glob, grep, ls, web_search, http_request |
Each type receives a role-specific system prompt that shapes its behavior. Explore agents are fast and lightweight – they only read files. Code agents can modify anything. Research agents can search the web but not touch your filesystem.
\nSafety: ALWAYS_EXCLUDED Tools
\nNo agent type has access to these tools, preventing dangerous or recursive operations:
\n- \n
spawn_agent– no spawning agents from agents \nresume_agent,wait_agent,send_input,close_agent– no managing siblings \nrebuild– no building from source \nevolve– no self-updating \n
Five Orchestration Tools
\n| Tool | Description |
|---|---|
spawn_agent | Create a typed child agent to handle a sub-task autonomously in the background |
wait_agent | Wait for a spawned agent to complete and return its output (configurable timeout) |
send_input | Send follow-up instructions to a running agent (multi-turn conversation) |
close_agent | Terminate a running agent and clean up its resources |
resume_agent | Resume a completed or failed agent with a new prompt (preserves prior context) |
Spawn an Agent
\nspawn_agent(\n label: \"refactor-auth\", # Human-readable label\n agent_type: \"code\", # general | explore | plan | code | research\n prompt: \"Refactor auth...\" # Task instruction\n)\n\nThe agent runs in its own session with auto-approved tools. No blocking – it executes in the background while the parent continues.
\nWait for Completion
\nwait_agent(\n agent_id: \"abc-123\",\n timeout_secs: 300 # Max wait time (default: 300s)\n)\n\nMulti-Turn with send_input
\nAfter spawning, you can send additional instructions without restarting:
\nsend_input(\n agent_id: \"abc-123\",\n text: \"Also add unit tests for the new module\"\n)\n\nThe child agent processes the input on its next iteration. This enables iterative workflows – review the agent’s output, then ask it to refine or continue.
\nResume a Completed Agent
\nresume_agent(\n agent_id: \"abc-123\",\n prompt: \"Now port the same changes to the other two files\"\n)\n\nThe agent continues in its original session, preserving all prior context. No need to re-explain the codebase.
\nTeam Orchestration
\nThe TeamManager coordinates named groups of agents for parallel execution. Three team-specific tools:
Create a Team
\nteam_create(\n team_name: \"backend-refactor\",\n agents: [\n { label: \"auth\", agent_type: \"code\", prompt: \"Refactor auth module\" },\n { label: \"tests\", agent_type: \"code\", prompt: \"Write tests for auth\" },\n { label: \"docs\", agent_type: \"general\", prompt: \"Update documentation\" }\n ]\n)\n\nAll agents spawn simultaneously and run in parallel. Returns the team name and all agent IDs.
\nBroadcast to a Team
\nteam_broadcast(\n team_name: \"backend-refactor\",\n message: \"Use the new AuthError enum instead of plain strings\"\n)\n\nSends a message to all running agents in the team. Non-running agents are skipped. Useful for sharing context or direction changes.
\nDelete a Team
\nteam_delete(team_name: \"backend-refactor\")\n\nCancels all running agents and cleans up resources. Completed agents are left in the subagent manager for reference.
\nSubagent Provider/Model Config
\nBy default, every spawned agent inherits the parent session’s provider and model. You can override this globally in config.toml so child agents route to a different (usually cheaper or faster) backend:
[agent]\nsubagent_provider = \"openrouter\" # Provider for child agents\nsubagent_model = \"qwen/qwen3-235b\" # Model override\n\n# Omit both keys and child agents inherit the parent session's provider\n# and run on that provider's default model.\n\nThe override applies to spawn_agent, resume_agent, and every member of a team_create team. Changes take effect on next session start; running sessions keep their existing provider.
Per-Call Overrides (v0.3.35)
\nspawn_agent, resume_agent, and team_create now accept optional provider and model fields that override config defaults for a single call. This enables mixed-model teams:
team_create(\n team_name: \"mixed-stack\",\n agents: [\n { label: \"planner\", provider: \"zhipu\", model: \"glm-5\", prompt: \"Architect the feature\" },\n { label: \"coder\", provider: \"deepseek\", model: \"deepseek-coder\", prompt: \"Implement it\" },\n { label: \"reviewer\", provider: \"kimi\", model: \"kimi-k2.5\", prompt: \"Review the code\" }\n ]\n)\n\nPrecedence order (highest first): per-call provider/model > [agent] subagent_provider/subagent_model in config > parent session’s provider.
Why It Matters
\nThe common pattern is premium parent, cheap children. Your main conversation stays on a reasoning-capable model (Opus, GPT-5, Gemini 2.5 Pro) while subtasks — file exploration, test writing, web research, bulk refactors — run on a faster, cheaper model. With a 4-agent team running 10 minutes each, the cost delta between Opus and Qwen on the children is roughly 50x.
\nConcrete Examples
\nOpenRouter parent, Qwen children — best bang-for-buck on mixed workloads:
\n[providers.openrouter]\nenabled = true\napi_key = \"sk-or-...\"\nmodel = \"anthropic/claude-opus-4\"\n\n[agent]\nsubagent_provider = \"openrouter\"\nsubagent_model = \"qwen/qwen3-235b-a22b-instruct\"\n\nKimi on custom OpenCode provider — fast code generation for code and explore agents:
[providers.opencode-kimi]\nenabled = true\nbase_url = \"https://api.kimi.com/v1\"\napi_key = \"...\"\nmodel = \"kimi-k2.5\"\n\n[agent]\nsubagent_provider = \"opencode-kimi\"\nsubagent_model = \"kimi-k2.6\"\n\nLocal Ollama children — zero cost, fully offline, good for explore agents that just read files:
[providers.ollama]\nenabled = true\nmodel = \"qwen3:14b\"\n\n[agent]\nsubagent_provider = \"ollama\"\nsubagent_model = \"qwen3:14b\"\n\nGemini parent, Gemini Flash children — single billing account, reasoning on main, flash on team:
\n[providers.gemini]\nenabled = true\nmodel = \"gemini-2.5-pro\"\n\n[agent]\nsubagent_provider = \"gemini\"\nsubagent_model = \"gemini-2.5-flash\"\n\nGotchas
\n- \n
- The subagent provider must be enabled and have a valid API key (or be a CLI/none-auth provider). Missing keys cause the spawn to fail with a provider resolution error. \n
subagent_modelmust be a model the provider actually serves.qwen/qwen3-235bworks on OpenRouter, not on Anthropic. Check/modelson the target provider to confirm. \nteam_createmembers all share the same subagent config. If you need heterogeneous routing (e.g. a research agent on web-search model, a code agent on code-specialized model), spawn them individually withspawn_agentunder different config profiles. \n- The CLI model override is surfaced in the
spawn_agent,resume_agent, andteam_createtool descriptions themselves, so the LLM knows to mention these keys to you instead of inventing per-call overrides. \n
If subagent_provider or subagent_model is not set, the spawned agent loads from the parent session’s provider and runs on that provider’s default model.
Workflow Patterns
\nParallel Research + Implementation
\nteam_create(\"feature-research\", [\n { label: \"research\", agent_type: \"research\", prompt: \"Find best practices for rate limiting in Rust\" },\n { label: \"explore\", agent_type: \"explore\", prompt: \"Find all middleware files in the codebase\" }\n])\n\nWait for results, then spawn a code agent with the combined context.
\nIterative Code Review
\n# 1. Spawn a code agent\nspawn_agent(label: \"impl\", agent_type: \"code\", prompt: \"Implement rate limiting middleware\")\n\n# 2. Wait for completion\nwait_agent(agent_id: \"impl-id\")\n\n# 3. Resume with refinements\nresume_agent(agent_id: \"impl-id\", prompt: \"Add tests for the edge cases we discussed\")\n\nLarge-Scale Refactoring
\nteam_create(\"refactor-team\", [\n { label: \"module-a\", agent_type: \"code\", prompt: \"Refactor module A to use the new trait\" },\n { label: \"module-b\", agent_type: \"code\", prompt: \"Refactor module B to use the new trait\" },\n { label: \"module-c\", agent_type: \"code\", prompt: \"Refactor module C to use the new trait\" },\n { label: \"tests\", agent_type: \"code\", prompt: \"Update all tests for the new trait signature\" }\n])\n\nTesting
\n84 tests cover the entire multi-agent system:
\n- \n
- Manager state machine (spawn, wait, close lifecycle) \n
SendInputwiring and input loop \nCloseAgentcleanup \nWaitAgenttimeout behavior \nAgentTypetool filtering \nTeamManager,TeamDelete,TeamBroadcast\n- Registry exclusion (ALWAYS_EXCLUDED enforcement) \n