-
Notifications
You must be signed in to change notification settings - Fork 0
Developer Subagents
Coordinated subagents let the coordinator (main agent turn) spawn parallel, filtered tool loops that share DispatchContext (provider, API key, model, thinking level, workspace root). Results are structured JSON via submit_result; live progress is pushed on the shared AgentEvent queue.
For harness-wide context (core skills, web settings), see Agent Harness. This document focuses only on the subagent stack.
| File | Responsibility |
|---|---|
subagents.rs |
subagents.run tool: validate spec, semaphore, spawn run_one_subagent per agent |
subagent_runner.rs |
HTTP completion loop (OpenAI-compatible + Anthropic), caps, events |
subagent_prompts.rs |
SubagentRole, defaults, system prompt, display names, truncate_submit_result
|
tool_groups.rs |
ToolGroup, registry_filtered, coordinator vs subagent catalogs |
tool_dispatch.rs |
Shared tool routing (coordinator path; subagent runner has local handler) |
tools_extra.rs |
subagents.run and submit_result ToolDef schemas |
protocol.rs / agent_wire.rs
|
SubagentStarted, SubagentStep, SubagentToolCall, SubagentFinished
|
Frontend:
| File | Responsibility |
|---|---|
agent_panel/subagent_debounce.rs |
50 ms debounce before apply_agent_event
|
agent_panel/timeline.rs |
TimelineItem::SubagentGroup, card UI |
agent_timeline.rs |
subagent_status_label, subagent_role_label, tool_label
|
sequenceDiagram
participant Orch as session_orchestrator
participant TD as tool_dispatch
participant SA as subagents.rs
participant R as subagent_runner
participant API as Provider HTTP
participant Q as AgentEngineState queue
participant UI as agent_panel
Orch->>TD: tool_call subagents.run
TD->>SA: run(args, DispatchContext)
par up to maxConcurrency
SA->>R: run_one_subagent (tokio task)
R->>Q: SubagentStarted
loop max 8 rounds
R->>API: chat completion + tools
R->>Q: SubagentToolCall
alt submit_result
R->>R: truncate_submit_result
end
end
R->>Q: SubagentFinished
end
SA-->>TD: ToolOutcome JSON agents[]
UI->>Q: agent_poll_events
Note over UI: subagent events debounced 50ms
Subagent message history is transient (per-task Vec<Value> in the runner). It is not appended to AgentEngineState conversation.
Parsed in subagents.rs as RunSpec / AgentSpec (camelCase JSON):
{
"agents": [
{
"id": "ui-review",
"role": "review",
"title": "Chat UI Review",
"task": "Inspect timeline integration risks.",
"successCriteria": ["List UI touchpoints", "Return concrete risks"],
"allowedToolGroups": ["environment_read", "workspace_read", "diff_read"]
}
],
"mode": "parallel",
"maxConcurrency": 3
}| Field | Rules |
|---|---|
agents |
1–5 entries, required |
role |
scout | review | security_analyst
|
allowedToolGroups |
Optional; empty → SubagentRole::default_groups()
|
maxConcurrency |
Default 3, capped at agent count |
After parsing groups, the runtime always appends ToolGroup::SubagentSubmit and removes SubagentsRun and ShellWrite.
From subagent_prompts.rs:
| Role | Groups |
|---|---|
scout |
environment_read, workspace_read, git_read, memory_read, plans_read, rules_skills_read
|
review |
environment_read, workspace_read, diff_read, tasks_read
|
security_analyst |
environment_read, workspace_read, diff_read, git_read
|
web_read is included only when web_settings::web_tools_enabled() is true at catalog build time.
Registered in tools_extra.rs; only in subagent-filtered catalogs (ToolGroup::SubagentSubmit). Coordinator tool_dispatch rejects or does not expose it on the main loop the same way — subagent runner handles it in handle_tool_call before execute_subagent_tool.
Required properties: status, summary. Typical payload:
{
"status": "completed",
"role": "review",
"displayName": "Review",
"summary": "Three UI risks found.",
"steps": [{ "id": "scan", "title": "Scan timeline.rs", "status": "completed" }],
"findings": [{ "severity": "warning", "title": "...", "evidence": "...", "paths": ["src/..."] }],
"artifacts": [{ "kind": "patch_hint", "title": "...", "content": "..." }],
"recommendedNextActions": ["Add test for SubagentGroup serde"]
}truncate_submit_result (coordinator-facing payload size):
-
findings→ max 20;evidenceper finding → 2000 chars -
artifacts→ max 10;contentper artifact → 4000 chars
| Cap | Constant / behaviour |
|---|---|
| Tool rounds | MAX_SUBAGENT_ROUNDS = 8 |
| Output tokens |
MAX_OUTPUT_TOKENS_ESTIMATE = 20_000 (usage field or char/4 estimate) |
| HTTP timeout | 180 s client timeout |
| Cancel |
state.cancelled() → shell_exec::kill_all_children(), blocked result |
Exit without submit_result → blocked_result with summary "max iterations reached without submit_result".
pub enum SubagentProvider {
OpenAi(Endpoint), // OpenRouter or OpenAI-compatible
Anthropic,
}SubagentProvider::from_settings — if provider kind is unsupported, subagents.run returns an error ToolOutcome.
Implementation note: subagent loops use non-streaming completions (unlike the coordinator’s SSE streams).
| Event | When | UI effect |
|---|---|---|
subagent_started |
Start of run_one_subagent
|
New card in last SubagentGroup
|
subagent_step |
Protocol + timeline support | Merge/update step row by step_id
|
subagent_tool_call |
Each tool before execute | Append ToolActivity on card |
subagent_finished |
After submit_result or cap |
Set card status + summary
|
Note: subagent_runner currently emits SubagentStarted, SubagentToolCall, and SubagentFinished. SubagentStep is handled in timeline.rs but not yet pushed from the runner — steps in UI mainly come from submit_result summary unless you add step events in the runner.
agent_panel/mod.rs routes subagent timeline events through SubagentEventDebounce (50 ms generation counter). Voice and non-subagent events apply immediately.
registry_filtered(groups, web_enabled)
render_for_openai_filtered(groups, web_enabled)
render_for_anthropic_filtered(groups, web_enabled) // names via to_anthropic_namecoordinator_groups(web_enabled) includes SubagentsRun but not SubagentSubmit. Subagent runs never include CoordinatorHarness unless explicitly added via custom groups (unusual).
system_prompt.rs lists subagents.run in the tool index and states explicit-user activation only. Full parameter docs: core skill harness_skills/subagents.md via skills_read.
-
SubagentRoleenum +parse+default_groupsinsubagent_prompts.rs -
subagent_system_promptrole line -
display_name_en+role_id - Validate in
subagents.rs(unknown role error) -
I18nKey::AgRole*inkeys.rs+ alllocales/*.rs agent_timeline::subagent_role_label- Extend
harness_skills/subagents.mdand user Subagents role table
-
tool_groups.rs— filtered registry must not leaksubagents.run/submit_resultincorrectly - Run
cargo test -p blxcodeafter changes tosubagents.rsorsubagent_runner.rs
.agents/plans/coordinated-subagents.md — original design decisions (German), including truncation limits and harness-vs-shell notes.
-
Agent Harness —
tool_dispatch, environment cache, web settings - Tauri IPC — agent poll/submit commands (no separate subagent commands)
- Architecture — agent subsystem overview
- User: Subagents — end-user guide
- User-Agent-Harness
- User-Agent-Providers
- User-Building
- User-Getting-Started
- User-Image
- User-Keyboard-Shortcuts
- User-Language
- User-Memory-And-Tasks
- User-Plans
- User-Rules-And-Skills
- User-Subagents
- User-Troubleshooting
- User-Voice
- User-Workspaces
- Developer-Agent-Harness
- Developer-Architecture
- Developer-Contributing
- Developer-I18n
- Developer-Setup
- Developer-Subagents
- Developer-Tauri-Ipc
- Developer-Voice