This article dissects the hidden multi-agent architecture of Anthropic's Claude Code, revealing how LLMs are orchestrated to perform complex tasks. It highlights the use of a recursive `AgentTool` for spawning sub-agents, explicit model selection for cost-quality tradeoffs, and a surprisingly simple filesystem-based mailbox for inter-agent communication. The architecture prioritizes simplicity and debuggability for local multi-agent systems.
Read original on Dev.to #architectureClaude Code's core orchestration mechanism involves a single `AgentTool` that allows a parent agent to spawn sub-agents. This recursive capability enables complex task decomposition and parallel execution. A key architectural decision is the explicit selection of the model tier (Haiku, Sonnet, Opus) by the parent agent for each child agent. This approach ensures a deliberate cost-quality trade-off per task, avoiding automatic routing which might lead to suboptimal resource utilization or performance for specific sub-tasks.
const baseInputSchema = z.object({
description: z.string().describe('A short (3-5 word) description'),
prompt: z.string().describe('The task for the agent to perform'),
subagent_type: z.string().optional(),
model: z.enum(['sonnet', 'opus', 'haiku']).optional(),
run_in_background: z.boolean().optional(),
})Perhaps the most counter-intuitive yet effective architectural choice is the use of a filesystem-based mailbox for communication between agents. Instead of complex message brokers, WebSockets, or shared memory, agents communicate by writing and reading JSON files to and from a designated directory (`~/.claude/teams/{team}/mailbox/{agent}.json`). Each agent runs in its own `tmux` pane as a separate process, ensuring isolation. This simple approach reduces operational overhead, enhances debuggability (messages can be inspected directly), and proves reliable for agents co-located on the same machine.
Design Principle: Simplicity for Co-located Systems
For systems where components are co-located on a single machine or within a tightly coupled environment, simpler communication mechanisms like filesystem-based messaging or shared memory can often outperform distributed message brokers. They reduce latency, complexity, and external dependencies, making the system easier to build, debug, and maintain. The trade-off is reduced scalability across multiple machines, but for specific use cases like local multi-agent orchestration, it's a valid and often superior choice.
The entire Claude Code system is heavily reliant on feature flags (44 identified). These flags dynamically control the inclusion of code, schemas, and even entire tool definitions. This allows for conditional functionality, A/B testing, and progressive rollout of features. Crucially, dead code elimination ensures that disabled features are not even seen by the underlying language model, simplifying its context and preventing unintended tool invocations. This is a robust pattern for managing complexity and enabling agile development in large, evolving systems, especially those leveraging LLMs where context window management is vital.