Subagents (src/agents/)
This page is generated from
docs/lld/agents.mdin the repository.
1. Overview & Architecture
Section titled “1. Overview & Architecture”Subagents in Garuda keep the primary orchestrator agent’s context window lean, focused, and token-efficient. Instead of loading instruction sets, file dumps, and broad search outputs into the main conversation, the orchestrator delegates sub-tasks to child agent sessions that execute in isolation and return concise, actionable reports.
Garuda implements a three-tier subagent architecture:
- Explore Subagent (
explore.ts, 0.3): A read-only reconnaissance agent that executes broad search queries across the repository usingglob,grep,read_file, and code index tools. - Mixture-of-Experts (MoE) Language Specialists (
moe.ts, 0.17): Autonomous specialist subagents for Go, Rust, Python, Java, and TypeScript equipped with the code index tools (approximate outside JS/TS), test runners (cargo test,go test ./..., etc.), and idiomatic prompt guidelines. - Custom Agents (
custom.ts,agentTool.ts, 0.5): User and project Markdown agents configured in Claude Code subagent format (.garuda/agents/*.md,.claude/agents/*.md).
All subagent types share a common child execution engine (child.ts) that enforces security boundaries, session journaling, token budgets, and step limits.
flowchart TD
subgraph Main[Primary Agent Session]
Orchestrator[Primary Agent Loop]
MainTools[Tool Registry]
end
subgraph Dispatch[Subagent Dispatch Layer]
ExTool[explore tool]
MoeTool[delegate_expert tool]
CustomTool[agent tool]
Router[inferLanguage Router]
end
subgraph Engine[Child Execution Engine: runChild]
ChildSession[Isolated Child Session<br/>.garuda/sessions/parent/child.jsonl]
WrapUp[Step Limit Wrap-Up Guard]
ReportGen[SubagentReport Generator]
end
subgraph SpecialistTargets[Active Subagents]
ExploreAgent[Explore Subagent<br/>Read-only tools]
MoeGo[Go Specialist<br/>go test, AST, idioms]
MoeRust[Rust Specialist<br/>cargo test, AST, idioms]
MoePython[Python Specialist<br/>pytest, AST, idioms]
MoeJava[Java Specialist<br/>mvn/gradle test, idioms]
MoeTS[TypeScript Specialist<br/>pnpm/npm test, AST, idioms]
CustomAgent[Custom Markdown Agent<br/>Configured tools]
end
subgraph Governance[Governance & Safety]
Policy[Team Policy: managed file + ~/.garuda/policy.json]
Perms[Permission Engine & Sandbox]
Audit[Audit Logger: ~/.garuda/audit/]
end
Orchestrator --> MainTools
MainTools --> ExTool
MainTools --> MoeTool
MainTools --> CustomTool
MoeTool --> Router
Router --> MoeGo & MoeRust & MoePython & MoeJava & MoeTS
ExTool --> ExploreAgent
CustomTool --> CustomAgent
ExploreAgent & MoeGo & MoeRust & MoePython & MoeJava & MoeTS & CustomAgent --> ChildSession
ChildSession --> Perms
Perms --> Policy
Perms --> Audit
ChildSession --> WrapUp
WrapUp --> ReportGen
ReportGen -->|Synthesized Report & Usage| Orchestrator
Module Breakdown
Section titled “Module Breakdown”| File | Purpose |
|---|---|
child.ts |
Shared child session runner (runChild): isolated session initialization, step and token budgeting, wrap-up call when the budget has room (G06), SubagentReport generation, and call logging. |
moe.ts |
Mixture-of-Experts language specialist architecture: SPECIALIST_SPECS for 5 languages, inferLanguage routing, buildSpecialistSystem, and createMoeDispatchTool (delegate_expert). |
explore.ts |
The explore subagent tool (0.3): read-only code exploration that answers open questions without polluting the main context with file contents. |
custom.ts |
Custom agent loader: discovers and parses Markdown agent definitions from 4 folders, tool mapping, and hash-pinned consent (agentConsent). |
agentTool.ts |
The agent tool (0.5): validates agent invocations, passes custom toolsets, enforces single-agent write execution (runsAlone), and synthesizes reports. |
2. Mixture-of-Experts (MoE) Language Specialists (moe.ts, 0.17)
Section titled “2. Mixture-of-Experts (MoE) Language Specialists (moe.ts, 0.17)”Motivation & Concept
Section titled “Motivation & Concept”In polyglot codebases, loading rules, test patterns, and syntax constraints for all languages into the primary system prompt wastes tokens and increases instruction-following drift. The MoE subagent system delegates language-specific tasks to dedicated specialist child agents that operate with tailored instructions, scoped tools, and test harnesses.
sequenceDiagram
participant O as Primary Orchestrator
participant D as delegate_expert Tool
participant R as inferLanguage Router
participant C as runChild (moe-lang-id)
participant P as Permissions & Policy
participant S as Language Tools & Tests
participant A as Audit Logger
O->>D: delegate_expert(language: "auto", task: "Fix borrow error", files: ["src/lib.rs"])
D->>R: inferLanguage(task, files)
R-->>D: "rust"
D->>C: Spawn child session with Rust Specialist prompt
loop Specialist Reasoning & Tool Execution (up to maxSteps)
C->>P: Tool check (e.g. read_file, bash: cargo test)
P->>A: Log check (~/.garuda/audit/)
P-->>C: Allowed
C->>S: Execute tool in OS sandbox
S-->>C: Tool result
end
C-->>D: Child Result + SubagentReport
D->>A: Log tool execution duration & risk
D-->>O: [Rust Specialist Report] + concise findings & call summary
O->>O: Synthesize final response to user
Specialist Profiles (SPECIALIST_SPECS)
Section titled “Specialist Profiles (SPECIALIST_SPECS)”Garuda registers 5 built-in language specialist profiles:
Language (id) |
Specialist Name | File Extensions | Default Test Runner | Key Idiomatic Guidelines |
|---|---|---|---|---|
go |
Go Specialist | .go |
go test ./... |
Structs & interfaces, explicit error handling (errors.Is/As), goroutines/channels/sync, exported visibility, table-driven tests. |
rust |
Rust Specialist | .rs |
cargo test |
Ownership, borrowing, lifetimes, Result<T, E> / Option<T> with ?, traits, Cargo workspace layouts, unit (#[test]) & integration tests. |
python |
Python Specialist | .py |
pytest |
Type annotations (PEP 484/585/604), dataclasses & Pydantic, generators, async/await, context managers, pytest fixtures. |
java |
Java Specialist | .java |
./mvnw test || gradle test |
Records, sealed interfaces, pattern matching, Streams, Optionals, Maven/Gradle lifecycles, JUnit 5 & Mockito. |
typescript |
TypeScript/JS Specialist | .ts, .tsx, .js, .jsx, .mts, .cts |
pnpm test || npm test |
Strict null checking, discriminated unions, generics, modern ESM, Node.js/browser APIs, Vitest/Jest conventions. |
Automatic Language Inference (inferLanguage)
Section titled “Automatic Language Inference (inferLanguage)”When language: "auto" is passed, inferLanguage(task, files) inspects the relevant file extensions first (.go → go, .rs → rust, etc.). If no files are given, keyword pattern matching inspects the task string (e.g. cargo, lifetime, goroutine, pytest, pom.xml, vitest). If ambiguous, it defaults to typescript.
Scoped Toolset (ALLOWED_TOOLS)
Section titled “Scoped Toolset (ALLOWED_TOOLS)”Specialists receive only tools relevant to code inspection, AST queries, edits, and builds:
- Read tools:
read_file,glob,grep. - AST & Index tools:
find_symbol,find_references,find_callers,impact_analysis,ast_query,repo_map. - Write & build tools:
edit_file,write_file,bash. - Excluded: Recursive subagents (
delegate_expert,explore,agent) are strictly prohibited to prevent nesting loops.
Configuration
Section titled “Configuration”Turned on via project settings (.garuda/settings.json):
{ "moe": { "enabled": true, "maxSteps": 20, "tokenBudget": 150000 }}Off by default; only moe.enabled: true turns it on (subagents alone does not, merge gate). delegate_expert
has runsAlone: true: two specialist calls never run at the same time, because a specialist can
write files (G05).
3. The explore Subagent (explore.ts, 0.3)
Section titled “3. The explore Subagent (explore.ts, 0.3)”createExploreTool(options) creates a read-only child agent for broad code reconnaissance.
sequenceDiagram
participant Main as Primary Agent
participant Reg as ToolRegistry
participant Ex as explore Tool
participant Child as Child Loop (runChild)
participant RO as Read-Only Tools
Main->>Reg: explore(question: "Where is token budget enforced?")
Reg->>Ex: run
Ex->>Child: runAgent(child session, EXPLORE_SYSTEM, limits)
loop Up to 20 steps
Child->>RO: glob, grep, read_file, find_symbol
RO-->>Child: Results
Child-->>Main: tool_progress event ("step N · grep /tokenBudget/")
end
Child-->>Ex: Answer + wrap-up if limit reached
Ex-->>Reg: [explore: 6 steps · 11.2k tokens] + citation list
Reg-->>Main: Concise answer with path:line citations
Key Properties
Section titled “Key Properties”- Read-Only: Executes strictly without user prompts; parallel explore calls in a single turn run concurrently.
- Tools:
readOnlyTools(codeIndex):glob,grep,read_file,find_symbol,find_references,repo_map. - System Prompt (
EXPLORE_SYSTEM): Instructs the child to search broadly first, read only essential lines, cite files aspath:line, and keep responses under 300 words. - Safety: Child reads do not satisfy
read_fileprerequisites foredit_filein the parent agent: the main agent must read a file directly before modifying it.
4. Custom Subagents (custom.ts, agentTool.ts, 0.5)
Section titled “4. Custom Subagents (custom.ts, agentTool.ts, 0.5)”Users can define custom subagents using Markdown files compatible with Claude Code’s format:
flowchart LR
subgraph Discovery[Agent Discovery Order]
UserGaruda["~/.garuda/agents/*.md (Trusted)"]
UserClaude["~/.claude/agents/*.md (Trusted)"]
ProjectGaruda[".garuda/agents/*.md (Needs Consent)"]
ProjectClaude[".claude/agents/*.md (Needs Consent)"]
end
subgraph ConflictResolution[Precedence Engine]
Precedence{Name Clash?}
UserWins[User Agent Wins]
ProjectWins[Project Agent Used]
end
subgraph ConsentFlow[Project Agent Consent]
CheckTrust{Hash in trust.json?}
PromptUser[Ask User: Show Tools & Prompt]
PinHash[Pin SHA-256 to trust.json]
end
UserGaruda --> Precedence
UserClaude --> Precedence
ProjectGaruda --> Precedence
ProjectClaude --> Precedence
Precedence -- "User exists" --> UserWins
Precedence -- "Project only" --> CheckTrust
CheckTrust -- "Known hash" --> ProjectWins
CheckTrust -- "New / Changed" --> PromptUser
PromptUser -- "Approved" --> PinHash
PinHash --> ProjectWins
Folder Discovery & Trust Hierarchy
Section titled “Folder Discovery & Trust Hierarchy”| Folder | Source | Trust Level |
|---|---|---|
~/.garuda/agents/*.md |
User | Trusted (runs immediately) |
~/.claude/agents/*.md |
User (Claude Code) | Trusted (runs immediately) |
<root>/.garuda/agents/*.md |
Project | Asks consent on first use; pinned by SHA-256 |
<root>/.claude/agents/*.md |
Project (Claude Code) | Asks consent on first use; pinned by SHA-256 |
Security Rule: User agents always take precedence over project agents. A repository cannot shadow or replace an agent the user trusts.
Custom Agent Frontmatter Spec
Section titled “Custom Agent Frontmatter Spec”---name: security-auditordescription: Audits code for SQL injection, CSRF, and secret leakstools: Read, Grep, GlobmaxTurns: 15---You are an expert application security auditor...maxTurns: lowers the step limit for this agent; it never raises the limit of the settings (subagents.maxSteps, capped by the team policy) (0.14, review). The consent question shows it.tools: Claude Code names map directly to Garuda tools (Read→read_file,Edit→edit_file, etc.). Omitted tools default to read-only.runsAlone: If any custom agent has write permissions,agenttool runs exclusively without concurrent tool execution.
5. Child Execution Engine (child.ts)
Section titled “5. Child Execution Engine (child.ts)”runChild(run: ChildRun, context: ToolContext) powers all subagent types:
- Session Isolation: Spawns a dedicated child session ID (e.g.
moe-rust-1,explore-2,agent-reviewer-1) stored at.garuda/sessions/<parent-id>/<child-id>.jsonl. - Limit Guardrails:
maxSteps: Model turns limit (default 20, max 200).tokenBudget: Input, output, and cache tokens cap (default 150,000). Since 0.17 (review T9) the child reserves in the parent’s turn budget (ToolContext.budget): its own cap, inside what the parent has left, and never into the parent’s floor for its final answer. Parallel children share it, so together they cannot pass the parent’s cap.- The team policy’s
limitscap both, for explore, custom agents and MoE (withPolicyLimits, 0.14, review). The child’s cap is also constrained by the shared parent allowance.
- Wrap-Up Recovery: When a child hits its step limit, its token limit or repeats a call,
runChildadds a wrap-up prompt (WRAP_UP) and makes one more model call (tool calls in it are ignored), so the subagent can say what it found and what is still open. The call runs only when it fits in the budget that is left (G06): the tokens used so far, plus the size of the wrap-up request (the larger of the last context and an estimate of the whole conversation with the wrap-up note), plus the output limit, must not passtokenBudget, and (0.17) the reservation must fit in the shared budget. Since the third review the wrap-up request is built first (system prompt, tool list, conversation, wrap-up note) and reserved like a main call, also when the child made no step; the answer is cut toLIMITS.childAnswerChars. With no room there is no call; the answer is the child’s last text, or a note that says the budget ran out. - Usage Accounting: Emits a
SubagentReportattached to the tool’sToolOutcome. The report’s usage covers the child’s responses, compaction summaries and wrap-up call. Each reported child charge is also saved immediately in the parent’schild_debitrecords (review of 6c9f929). Returned reports add usage and cost and replace only the debits they cover. Cancellation retains pending charges even when no report returns; partial reports cannot erase descendant spend they omit. USD-cost breakdowns still depend on returned reports; pending debits protect the token allowance. Started parallel calls settle before the parent turn ends. - One end record:
runAgentruns withendRecord: false, andrunChildwrites the singleendrecord of the child journal: the loop’s stop reason,wrap_up,no_wrap_up,errororinterrupted, with the final step count (0.14.1, review: there were two). - What the parent has: a child’s edits get the parent’s diagnostics and formatters (
context.diagnostics,context.format), and MoE specialists get Claude’s web search when the runtime offers it (0.14.1, review). A model client that fails to start is not kept, so the next call tries again.
6. Observability & User Interface
Section titled “6. Observability & User Interface”Start Banner Integration
Section titled “Start Banner Integration”The CLI startup banner provides dedicated, aligned rows for active capabilities:
╭────────────────────────────────────────────────────────────────────────────────────────────────────╮│ ✦ Garuda 0.16.1 · a terminal coding agent ││ ││ model claude-sonnet-5 ││ sandbox seatbelt · no network ││ folder ~/dev/garuda ││ subagents explore · 5 MoE experts (Go, Rust, Python, Java, TS) ││ agents 1 agent (bug-finder) ││ skills 1 skill (commit) ││ tools TypeScript · 1 MCP server · web_fetch · web_search: Claude + fallback │╰────────────────────────────────────────────────────────────────────────────────────────────────────╯Slash Commands
Section titled “Slash Commands”/experts: Lists all 5 MoE language specialists, their test commands, supported extensions, and indexed file counts./agents: Lists configured custom subagents, their sources (user/project), allowed tools, and model targets./session: Displays the active session ID, log path, and a consolidated capability inventory (subagents, agents, skills, tools) with cross-reference tips./audit: Displays the policy files and recent audit events (risk levels, durations);/audit verifychecks the hash chains.
7. Security, Team Policy & Audit Containment
Section titled “7. Security, Team Policy & Audit Containment”A subagent’s tool calls pass the same checks as the main agent’s:
flowchart TD
ChildCall[Subagent Tool Call] --> Step0{Team Policy Check<br/>managed + ~/.garuda/policy.json}
Step0 -- "Policy denial (disallowed command, denied path)" --> Reject[Policy Denied: by policy]
Step0 -- "Pass" --> Perms{Permission Engine<br/>Sensitive paths, protected git}
Perms -- "Denied / Ask required" --> Reject
Perms -- "Pass" --> Sandbox[Run through the executor<br/>OS sandbox when available]
Sandbox --> Duration[Record Duration]
Duration --> AuditLog[Append Event to ~/.garuda/audit/]
Reject --> AuditLog
- Team policy (the managed file and
~/.garuda/policy.json): checked before any subagent tool runs. A denied command or path is refused withby: policy.grep,globand the code index skip files thatdenyPathsdenies (G04). - Audit Trail (
~/.garuda/audit/): Every subagent authorization check is recorded with timestamp, session ID, tool name and risk level (low,medium,high,critical). The outcome of a tool run inside a subagent is not recorded yet (G07, open). - Snapshot & Worktree Isolation: Child runs never contaminate undo snapshot diffs (
SNAPSHOT_EXCLUDES) or scheduled job git branches (NEVER_COMMIT).