cc-haha/docs/en/internals/agent-framework.md
程序员阿江(Relakkes) c2cd615824 docs: rebuild the documentation site around two readers
The site had drifted from the product. Every screenshot predated the
v0.5.0 UI redesign, the reading experience shipped no search and no
syntax highlighting, and a third of the pages were internal process
artefacts — migration task lists addressed to agentic workers, a
release runbook, a proposal marked "historical".

Reorganise around the only two people who read this: someone getting
the desktop app running for the first time, and someone reading the
source. Five sections replace nine — start / desktop / im / cli /
internals — and the pages that served neither reader are gone.

Site rewrite:

- Palette lifted from the desktop app's 「纸·墨·印」 themes, so the
  site and the product read as one thing. Light mirrors 纯白, dark
  mirrors 墨夜, and dark mode exists at all now.
- Fonts are self-hosted. The old @import from Google Fonts is
  unreachable from mainland China, which left every heading in a
  fallback serif; it also only requested weight 600 while the CSS
  asked for 900, so Latin and CJK in the same heading disagreed.
- Docs were shipped as one 968KB manifest downloaded on every page
  view. Split into a 32KB index plus one lazily imported chunk per
  page; the entry bundle is now 101KB gzipped.
- Add search, syntax highlighting, per-route meta with canonical and
  hreflang, a sitemap, and an error boundary. Replace the 44vh
  mobile sidebar with a drawer.
- Image dimensions are read at build time and written into the tag,
  so lazy images reserve their space instead of collapsing.

Screenshots are recaptured from a real v0.5.0 build against a clean
demo project, with tokens, QR codes and paired accounts redacted.
The previous set is deleted rather than kept alongside.

Routes follow file paths, so the restructure would have broken every
inbound link; 37 old paths redirect, in both languages. The PR policy
gate and CODEOWNERS also hardcoded docs/guide/contributing.md.

Verified: check:docs 78 pages / 323 links / 0 problems, check:policy
127 pass. Walked every route at 1440 and 390 in both themes for
overflow, contrast, keyboard reachability and focus management.
2026-07-27 17:32:41 +08:00

31 KiB

title nav_title description order
Agent Framework Deep Dive Agent Framework The core agent loop, prompt engineering, tool system, and context compression, read from source. 6

Agent Framework Deep Dive

Deconstructing the architecture behind the world's most popular AI code editor — from source code to design philosophy.

Agent Framework Architecture Overview

What This Framework Solves

Watch Claude Code closely and a few behaviors need explaining:

  • It can modify dozens of files in a single conversation with extremely few errors
  • It automatically recovers from edge cases (token overflow, API timeouts, tool failures)
  • It can simultaneously manage multiple subagents collaborating on complex tasks
  • Long conversations don't degrade — they actually become more precise over time

None of that comes from the model alone; it is designed into the framework. The rest of this page walks the source in order.

The Core Agent Loop

Not ReAct — An Async Generator State Machine

Most agent frameworks (including LangChain) adopt the classic ReAct pattern:

Thought → Action → Observation → Thought → ...

Claude Code does not use this pattern. Its core is an async generator-driven state machine, defined in src/query.ts (~1730 lines):

// src/query.ts:219
export async function* query(params: QueryParams): AsyncGenerator<...>

This function is the heart of the entire agent. It's not a simple "think-act-observe" loop but a streaming state machine that yields messages in real-time and drives iteration through state assignment (not recursive calls).

The State Structure

// src/query.ts:204-217
type State = {
  messages: Message[]                    // Full conversation history
  toolUseContext: ToolUseContext          // Tool execution context
  autoCompactTracking: AutoCompactTracking  // Auto-compaction tracking
  maxOutputTokensRecoveryCount: number   // Output recovery counter
  hasAttemptedReactiveCompact: boolean   // Whether reactive compact was tried
  maxOutputTokensOverride: number        // Output token override
  pendingToolUseSummary: Promise<...>    // Pending tool summary
  stopHookActive: boolean               // Stop hook state
  turnCount: number                      // Conversation turn count
  transition: Continue | undefined       // Transition reason
}

Five Phases of the Core Loop

The entire while (true) loop (src/query.ts:307-1728) consists of five phases:

Agent Core Loop

Phase 1: Message Preparation & Smart Compression (lines 365-543)

Before calling the API, conversation history goes through four layers of compression:

Compression Strategy Mechanism Trigger
Snip Compression Smart deletion of redundant tokens in old messages Every turn
Micro Compression In-place modification of cached message content Every turn
Context Collapse Staged summarization of historical messages When context nears limit
Auto Compact Full summary generation via Claude When context is critically low

This is the key to Claude Code handling extremely long conversations without degradation — it doesn't simply truncate history, but intelligently compresses while preserving critical information.

Phase 2: Streaming API Call (lines 652-954)

// src/query.ts:659-708
for await (const message of deps.callModel({
  messages: prependUserContext(messagesForQuery, userContext),
  systemPrompt: fullSystemPrompt,
  thinkingConfig,
  tools: toolUseContext.options.tools,
  signal: abortController.signal,
}))

Key design: tools begin executing during streaming, not after the model generates a complete response. This is achieved through StreamingToolExecutor — when the model generates tool_use blocks, tools start running immediately.

Phase 3: Decision Point (lines 1062-1358)

Model response complete
  │
  ├─ Has tool calls? ──→ Continue loop (Phase 4)
  │
  └─ No tool calls?  ──→ Run stop hooks → Check token budget → Return result

Phase 4: Tool Orchestration (lines 1363-1409)

Tool execution isn't simple sequential invocation — it uses a carefully designed orchestration strategy (src/services/tools/toolOrchestration.ts):

Tool call list
  │
  ├─ Partition: read-only vs. write
  │
  ├─ Read-only tools ──→ Parallel execution (up to 10 concurrent)
  │
  └─ Write tools ──→ Serial execution (prevent race conditions)

Phase 5: State Update & Loop (lines 1704-1728)

This is the most elegant part of the design — driving the loop through state assignment rather than recursive calls:

// src/query.ts:1715-1728
const next: State = {
  messages: [...messagesForQuery, ...assistantMessages, ...toolResults],
  toolUseContext: toolUseContextWithQueryTracking,
  autoCompactTracking: tracking,
  turnCount: nextTurnCount,
  transition: { reason: 'next_turn' },
}
state = next
// Back to top of while(true) loop

No recursion, no callback hell — just simple state = next followed by continue. This guarantees:

  • Memory stability: No stack overflow from deep recursion
  • State traceability: Every transition reason is recorded
  • Controllable recovery: Errors at any phase can be recovered by modifying state

System Prompt Engineering

Layered Construction Architecture

The system prompt isn't a static string — it's dynamically assembled through a layered pipeline (src/constants/prompts.ts:444-577):

System Prompt Pipeline

┌─────────────────────────────────────────────────────────────┐
│                    Static Cacheable Zone                      │
│  ┌───────────────────────────────────────────────────────┐  │
│  │ Role Def │ System Rules │ Task Guide │ Tool Desc │ Style│  │
│  └───────────────────────────────────────────────────────┘  │
├─────────────────────── Cache Boundary ──────────────────────┤
│                    Dynamic Variable Zone                      │
│  ┌───────────────────────────────────────────────────────┐  │
│  │ Session Guide │ Memory │ Env Info │ MCP Instr │ Budget │  │
│  └───────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

The cache boundary (SYSTEM_PROMPT_DYNAMIC_BOUNDARY) is a critical design element:

  • Above the boundary: Content universal across users and organizations, cached with scope: 'global'
  • Below the boundary: User/session-specific content, cached with scope: 'ephemeral'

This means Claude Code's system prompt doesn't need to be reprocessed every time — the static portion is shared globally, dramatically reducing latency and cost.

Two Section Types

// src/constants/systemPromptSections.ts

// Type 1: Cached Section (computed once, reused for entire session)
systemPromptSection('memory', async () => {
  return buildMemoryLines()  // Load CLAUDE.md, memory files, etc.
})

// Type 2: Cache-Breaking Section (recomputed every turn)
DANGEROUS_uncachedSystemPromptSection('mcp_instructions', async () => {
  return getMcpInstructions()  // MCP servers may connect/disconnect mid-session
}, 'MCP servers can connect/disconnect mid-session')

CLAUDE.md Loading Mechanism

CLAUDE.md is the custom instruction system, loaded by priority from low to high (src/utils/claudemd.ts):

/etc/claude-code/CLAUDE.md          ← Global managed config (lowest priority)
  ↓
~/.claude/CLAUDE.md                 ← User-level global instructions
  ↓
project-root/CLAUDE.md              ← Project-level instructions
project-root/.claude/CLAUDE.md
project-root/.claude/rules/*.md
  ↓
project-root/CLAUDE.local.md        ← Local private instructions (highest priority)

Supports @path syntax for recursive file inclusion, with automatic circular reference prevention.

System Prompt Priority Resolution

The final system prompt is determined through buildEffectiveSystemPrompt() (src/utils/systemPrompt.ts:41-123):

  1. Override prompt — Complete replacement (used in loop mode)
  2. Coordinator prompt — Coordinator mode
  3. Agent prompt — Custom agent definition
  4. Custom prompt--system-prompt CLI flag
  5. Default prompt — Standard system prompt
  6. Append prompt — Always appended at the end

Tool System Design

Tools: More Than Function Calls

Claude Code's tools aren't simple "name + params + execute". Each tool is a complete lifecycle management unit (src/Tool.ts:362-695):

type Tool<Input, Output> = {
  // Identity
  name: string
  aliases?: string[]        // Backward-compatible old names
  searchHint?: string       // ToolSearch keyword matching

  // Capability declarations
  isEnabled(): boolean
  isConcurrencySafe(input): boolean   // Can run in parallel?
  isReadOnly(input): boolean          // Read-only operation?
  isDestructive(input): boolean       // Destructive operation?

  // Lifecycle
  validateInput(input, context)       // Input validation
  checkPermissions(input, context)    // Permission check
  call(input, context, ...)           // Actual execution

  // Output & rendering
  renderToolUseMessage(input)         // Render invocation info
  renderToolResultMessage(content)    // Render result info
  renderToolUseProgressMessage(...)   // Render progress
  mapToolResultToToolResultBlockParam()  // Map to API format

  // Smart features
  inputSchema: Zod schema             // Zod type validation
  maxResultSizeChars: number           // Result size threshold
  toAutoClassifierInput(input)         // Security classifier input
  getToolUseSummary?(input): string    // Tool usage summary
}

This design makes every tool self-describing, self-validating, and self-rendering — the framework doesn't need to understand tool internals, just call standard interfaces.

Tool Registration: Three-Stage Pipeline

Tool discovery and registration happens in three stages (src/tools.ts):

Stage 1: Base Tool Pool (getAllBaseTools)
  │  ~48 built-in tools
  │  + Feature-flag-gated conditional tools
  │
Stage 2: Filtering (getTools)
  │  Filter by permission mode
  │  Filter by REPL mode
  │  Filter by isEnabled()
  │
Stage 3: MCP Merge (assembleToolPool)
     + Dynamic tools from MCP servers
     Deduplication (built-in takes precedence)
     Sorting (cache stability)

Tool Execution Pipeline

Each tool invocation passes through a 7-step pipeline (src/services/tools/toolExecution.ts):

1. Tool Lookup → 2. Input Parsing (Zod) → 3. Custom Validation
       │
4. Pre-Tool Hooks → 5. Permission Check → 6. Actual Execution → 7. Post-Tool Hooks

Each step can interrupt, modify, or enhance the execution flow. This isn't a simple try { tool.call(input) } catch — it's a full middleware pipeline.

Deferred Tool Loading

Claude Code has 48+ built-in tools. Sending all tool definitions to the model on every API call would waste massive tokens. The solution:

// Tools can be marked for deferred loading
{
  shouldDefer: true,       // Only list name in ToolSearch
  alwaysLoad: false,       // Don't include full schema in initial prompt
  searchHint: "notebook"   // Search keywords
}

The model dynamically retrieves full definitions via the ToolSearch tool when needed. This dramatically reduces system prompt size.

Context Management & Compression

The Secret Behind Unlimited Conversations

Claude Code claims "conversations have no context limit." Behind this is a four-level compression system:

Context Compression Strategy

Level 1: Snip Compression

Smart trimming of processed messages — removes duplicate file content, overly long tool outputs, etc.

Level 2: Micro Compression

Modifies cached message content without changing the cache key. An "in-place optimization" strategy.

Level 3: Context Collapse

Staged summarization of historical messages. Not all-at-once summarization, but progressive folding — summarize the oldest messages first, keeping recent details intact.

Level 4: Auto Compact

When all local optimizations are insufficient, Claude itself generates a complete conversation summary that replaces all historical messages.

System Context Injection

Before every API call, two types of context are automatically injected (src/context.ts):

// System context (memoized, cached for entire session)
getSystemContext()  {
  gitStatus,           // Current branch, recent commits, file status
  cacheBreakerInjection  // System-level injection
}

// User context (memoized, cleared when CLAUDE.md changes)
getUserContext()  {
  claudeMdContent,     // Merged content from all CLAUDE.md files
  currentDate,         // Current date
  mcpInstructions      // MCP server instructions
}

System Reminders

System reminders are special attachment messages injected into tool results or user messages (src/utils/attachments.ts):

<system-reminder>
  System-level context information, unrelated to specific tool results.
</system-reminder>

Use cases include:

  • Security warnings during file reads
  • Memory staleness notifications
  • Accompanying information for side questions
  • Availability notices for deferred tools

Skills & Plugin Ecosystem

Skills System

Skills are one of Claude Code's most powerful extension mechanisms. They're not simple "command aliases" but complete AI behavior definitions.

Skill Definition Structure

type BundledSkillDefinition = {
  name: string
  description: string
  whenToUse?: string           // Model auto-determines when to use
  allowedTools?: string[]      // Restrict tool pool
  model?: string               // Specify model
  hooks?: HooksSettings        // Lifecycle hooks
  context?: 'inline' | 'fork'  // Inline or independent context
  agent?: string               // Associated agent type
  getPromptForCommand: (args, context) => Promise<ContentBlockParam[]>
}

Two Execution Contexts

Context Behavior Use Case
inline Skill content expands directly into current conversation Simple instructions, format templates
fork Skill runs as a subagent in an independent context Complex workflows, independent token budget

Skill Discovery Sources

Bundled skills (bundled)          ← Compiled into CLI, 15+
  ↓
Plugin skills (plugin)            ← Plugin-registered
  ↓
User skills (~/.claude/skills/)   ← User-global
  ↓
Project skills (.claude/skills/)  ← Project-level
  ↓
Policy skills (policy)            ← Organization-managed

Plugin System

Plugins are higher-level extension units that can contain skills, hooks, MCP servers, and LSP servers:

type BuiltinPluginDefinition = {
  name: string
  description: string
  skills?: BundledSkillDefinition[]     // Skill collection
  hooks?: HooksSettings                  // Lifecycle hooks
  mcpServers?: Record<string, McpServerConfig>  // MCP servers
  lspServers?: Record<string, LspServerConfig>  // LSP servers
  isAvailable?: () => boolean            // Availability check
  defaultEnabled?: boolean               // Default enabled state
}

The key plugin design: users can toggle enable/disable, unlike directly registered skills.

Hooks System

Hooks are programmable interception points across the entire lifecycle:

SessionStart → UserPromptSubmit → PreToolUse → [Tool Execution]
       │                                              │
       │                                          PostToolUse
       │                                              │
       └── SubagentStart ←── Stop ←── TaskCompleted ←─┘
              │
          SubagentStop → SessionEnd

Hooks execute as shell commands, with exit codes controlling behavior:

  • 0: Success, stdout content processed per event type
  • 2: stderr content shown to model or user
  • Other: Shown to user only

MCP: Model Context Protocol

MCP is the standard protocol for Claude Code's interaction with the external world. Tool naming convention:

mcp__{normalized_server_name}__{tool_name}
e.g.: mcp__chrome_devtools__take_screenshot

Supported transports: stdio, sse, http, websocket, sdk

MCP tools are discovered at runtime and seamlessly merged into the unified tool pool alongside built-in tools.

Permission & Security Model

Layered Permission Model

┌─────────────────────────────────────┐
│         Permission Rules             │
│  Sources: userSettings, project,     │
│           flagSettings, policy       │
├─────────────────────────────────────┤
│         Permission Modes             │
│  default | plan | acceptEdits       │
│  bypassPermissions | auto | bubble  │
├─────────────────────────────────────┤
│              Hooks                   │
│  PreToolUse can intercept/modify    │
├─────────────────────────────────────┤
│      Security Classifier             │
│  ML model evaluates tool call safety│
└─────────────────────────────────────┘

Permission Decision Flow

Permission check for every tool invocation:

type PermissionResult =
  | { behavior: 'allow', updatedInput?, decisionReason }
  | { behavior: 'ask',  message, suggestions }
  | { behavior: 'deny', message, decisionReason }
  | { behavior: 'passthrough', message }

Decision reason traceability:

  • type: 'rule' — Matched a permission rule
  • type: 'mode' — Determined by permission mode
  • type: 'hook' — Hook interception
  • type: 'classifier' — ML classifier decision

Permission Rule Pattern Matching

// Exact match
{ tool: 'Bash', behavior: 'deny' }

// Parameter pattern matching
{ tool: 'Bash(git *)', behavior: 'allow' }     // Allow all git commands
{ tool: 'Bash(rm -rf *)', behavior: 'deny' }   // Block rm -rf

// Wildcard
{ tool: 'File*', behavior: 'allow' }            // Allow all File* tools

Fault Recovery Mechanisms

This is one of Claude Code's most sophisticated designs. The core loop in src/query.ts has 6 built-in recovery strategies:

Recovery Strategy Trigger Recovery Method
collapse_drain_retry Prompt too long Drain staged context collapses, retry
reactive_compact_retry Still too long Generate summary via Claude, retry
max_output_tokens_escalate Hit 8k default limit Escalate to 64k limit, retry
max_output_tokens_recovery Hit any limit Inject "continue" nudge, retry (up to 3x)
stop_hook_blocking Stop hook blocked Inject blocking errors into context, retry
token_budget_continuation Budget remaining Inject budget nudge, continue

Each recovery works by modifying state:

// Example: prompt-too-long recovery
if (error.type === 'prompt_too_long') {
  // Drain all staged collapses
  const compacted = drainStagedCollapses(state.messages)
  state = { ...state, messages: compacted, transition: { reason: 'collapse_drain_retry' } }
  continue  // Back to loop top to retry
}

Model Fallback

When the primary model's stream fails, the system:

  1. Cleans up orphaned incomplete messages
  2. Switches to a fallback model
  3. Retries with the new model

Media Size Recovery

When images or other media cause token overflow:

  • Triggers reactive compaction
  • Automatically strips image content
  • Retains text information and retries

How It Differs from LangChain/ReAct

Architecture Paradigm Comparison

Dimension LangChain Claude Code
Core Pattern ReAct (Think→Act→Observe) Async Generator State Machine
Execution Model Synchronous blocking Streaming non-blocking
Tool Execution After complete model response During streaming
State Management External Memory objects Built-in state assignment + loop
Error Recovery Manual orchestration required 6 built-in recovery strategies
Context Compression Simple truncation or summary Four-level progressive compression
Multi-Agent Chain/Graph explicit orchestration Unified tool interface + state machine
Extension Mechanisms Python class inheritance Skills + Plugins + Hooks + MCP
Caching Strategy None Global / session / per-turn three-level cache

Why Not ReAct?

The ReAct pattern has several inherent limitations:

  1. Serial bottleneck: Each step must wait for the complete "think→act→observe" cycle
  2. No streaming capability: Tools can't execute until the model completes its full response
  3. Recovery difficulty: No unified state representation makes automatic recovery hard
  4. Cache-unfriendly: Prompt structure changes significantly each cycle, making caching difficult

Claude Code's Async Generator pattern solves all these problems:

  • Streaming execution: Tools run while the model generates
  • Controllable state: The State object contains all needed info; recovery means just modifying state
  • Cache optimization: Static prompts cached globally, dynamic parts minimized
  • Parallel capability: Read-only tools auto-parallelize, write tools serialize for ordering

Specific Differences from LangChain Agents

LangChain Agent:
  agent = initialize_agent(tools, llm, agent="zero-shot-react-description")
  result = agent.run("do something")
  # Internal: LLM → parse → tool → LLM → parse → tool → ... → final answer
  # Each step is an independent LLM call

Claude Code Agent:
  for await (const msg of query({ messages, tools, systemPrompt })) {
    yield msg  // Real-time message output
    // Internal: streaming LLM → streaming tool execution → state update → continue
    // A single API call can trigger multiple tools, which execute during streaming
  }

Key differences:

  • Each LangChain "step" is a complete LLM call
  • Each Claude Code "turn" can include multiple tool calls, with tools executing during streaming
  • LangChain requires an OutputParser to parse tool calls from model output
  • Claude Code directly uses Anthropic API's native tool_use capability — no parsing needed

Comparison with LangGraph

LangGraph is LangChain's evolution, introducing graph structures:

Dimension LangGraph Claude Code
State Flow Explicit graph nodes + edges Implicit state machine (while + continue)
Visualization Exportable as graph Transition reasons are traceable
Persistence Checkpoint + State File system + message history
Human-in-Loop interrupt_before/after Permission system + hooks
Multi-Agent Requires explicit orchestration Unified AgentTool interface

Claude Code's advantage is simplicity — no need to define graph structures; a single while loop handles everything.

Why Claude Code Is So Good

From source code analysis, we can distill these core design principles:

Streaming First

The entire architecture is designed around AsyncGenerator — everything is streamed:

  • Model responses are streamed
  • Tools execute during streaming
  • Progress updates in real-time
  • Compression strategies are progressive

Users never have to wait — they see the model thinking, tools executing, and results emerging.

Intelligent Caching

Three-level prompt caching system (src/services/api/claude.ts:3213-3237):

Global Cache (cross-org)      ← Static system prompt
  ↓
Ephemeral Cache (session)     ← Dynamic system prompt
  ↓
Section Cache (per-turn)      ← systemPromptSection memoization

This dramatically reduces latency and cost for every API call.

Graceful Degradation

Six recovery strategies ensure Claude Code almost never interrupts the user's workflow due to technical issues:

  • Token overflow? Auto-compress
  • API timeout? Auto-retry
  • Model failure? Fall back to alternate model
  • Tool failure? Log error, continue conversation

Minimal Abstraction Principle

Unlike LangChain's "abstract everything" philosophy, Claude Code's core has only:

  • One loop (while (true) in query())
  • One state (State object)
  • One interface (Tool type)

No Agent → AgentExecutor → Chain → Memory → Callback nesting layers. This makes the code easy to understand, debug, and extend.

Native API Integration

Claude Code directly leverages Anthropic API's native capabilities:

  • Native tool calling: No OutputParser needed, directly uses tool_use blocks
  • Native streaming: No wrapper layers, directly consumes SSE streams
  • Native caching: Leverages API's prompt caching feature
  • Native chain-of-thought: Directly uses extended thinking

This avoids the "framework tax" — the abstraction layer that frameworks like LangChain add between the LLM and the developer.

Tool-Driven Agent

Claude Code's philosophy: an agent's capability equals the capability of its tools.

  • Spawn a subagent? That's a tool (AgentTool)
  • Manage a team? That's a tool (TeamCreate/SendMessage)
  • Edit a file? That's a tool (FileEdit)
  • Execute a skill? That's a tool (SkillTool)

All capabilities are exposed through the unified tool interface, and the model uses natural language reasoning to decide which tool to use. No explicit orchestration logic needed — the model itself is the orchestrator.

Deep Developer Experience Integration

Claude Code isn't "generic agent + code plugin" — it's deeply optimized for coding scenarios from the ground up:

  • Git-aware: Automatically injects git status, understands branches, commits, diffs
  • Filesystem-aware: Understands project structure, intelligently searches files
  • Worktree isolation: Safe experimental modification environments
  • LSP integration: Language Server Protocol provides type information and diagnostics
  • MCP ecosystem: Connects to various external tools via standard protocol

Core Component Relationships

User Input
  │
  ▼
QueryEngine (src/QueryEngine.ts)
  │
  ├─ Build system prompt (prompts.ts + context.ts + claudemd.ts)
  ├─ Assemble tool pool (tools.ts + MCP)
  │
  ▼
query() async generator loop (src/query.ts)
  │
  ├─ Phase 1: Message compression (snip → micro → collapse → compact)
  ├─ Phase 2: Streaming API call (callModel + StreamingToolExecutor)
  ├─ Phase 3: Decision point (continue or complete)
  ├─ Phase 4: Tool orchestration (parallel read-only + serial write)
  └─ Phase 5: State update (state = next → continue)
       │
       ├─ Recovery strategies (6 types)
       ├─ Hook system (PreToolUse / PostToolUse / Stop / ...)
       └─ Subagent spawning (AgentTool → runAgent → new query() instance)
            │
            ├─ Synchronous foreground
            ├─ Async background (LocalAgentTask)
            ├─ Fork (inherit context)
            └─ Teammate (mailbox communication)

Key Source File Index

Component File Path Description
Core Loop src/query.ts Main agent loop (~1730 lines)
Query Engine src/QueryEngine.ts High-level wrapper
Tool Definition src/Tool.ts Tool type system (~792 lines)
Tool Registry src/tools.ts Tool discovery and registration (~389 lines)
Tool Execution src/services/tools/toolExecution.ts Execution pipeline
Tool Orchestration src/services/tools/toolOrchestration.ts Parallel/serial strategy
System Prompt src/constants/prompts.ts Prompt assembly
Prompt Sections src/constants/systemPromptSections.ts Section caching
Context Management src/context.ts System/user context
CLAUDE.md src/utils/claudemd.ts User instruction loading
Memory System src/memdir/memdir.ts Persistent memory
Agent Spawning src/tools/AgentTool/AgentTool.tsx Agent tool entry point
Agent Execution src/tools/AgentTool/runAgent.ts Agent execution logic
Fork Agent src/tools/AgentTool/forkSubagent.ts Fork cache optimization
Team Management src/utils/swarm/teamHelpers.ts Teams infrastructure
Mailbox Communication src/utils/teammateMailbox.ts Async message queue
Skills System src/skills/bundledSkills.ts Skill registration and management
Plugin System src/plugins/builtinPlugins.ts Plugin framework
Hook System src/utils/hooks/hooksConfigManager.ts Hook management
Permission System src/utils/permissions/permissions.ts Permission checking
State Management src/state/AppStateStore.ts Global state
Cost Tracking src/cost-tracker.ts API cost calculation
API Client src/services/api/claude.ts Anthropic API wrapper
MCP Client src/services/mcp/client.ts MCP protocol implementation
Coordinator Mode src/coordinator/coordinatorMode.ts Multi-agent orchestration
Remote Sessions src/remote/RemoteSessionManager.ts CCR connection management
Bridge src/bridge/bridgeMain.ts Remote bridge

Further Reading