Repository navigation
Subagent: reuse runtime spine for agent-as-tool delegation #49
Description
Goal
Build subagent as a first-class LLM delegation primitive without creating a second runtime or a second ledger.
A subagent is a real child agent run created through the existing AgentRun / RuntimeKernel.startTurn orchestration, exposed by a thin child-run seam such as RuntimeKernel.startChildTurn(...). RuntimeRunner remains the inner invocation pump; it should not become the persistence or lifecycle boundary.
The existing ExploreAgent should stay as a deterministic read-only helper. It is useful, but it is not the LLM subagent implementation.
Design filter
- Simple enough: Day 1 adds one inline spec, one lineage field, and the minimal display metadata needed after restart.
- Elegant enough: a subagent is still an
AgentRunwithparentRunId, not a new run type. - Reassuring enough: permissions, events, artifacts, recovery, abort, and inspection keep using the existing runtime machinery, with child runs kept out of the parent transcript unless explicitly summarized.
Existing spine to reuse
- Events:
RuntimeEvent/AgentRunEvent - Runs:
AgentRunHeader/AgentRunStore - Permissions: existing
PermissionMode × ToolCategory - Artifacts: existing
ArtifactRecord - Inspection: existing agent-run inspect/read models
- Runtime loop: existing
RuntimeKernel.startTurnwiring,AiSdkFlow, andRuntimeRunner - Future handoff seam:
RuntimeEvent.actions.transferToAgent
Day 1 shape
Add:
- Inline
AgentSpecpassed by the spawn tool, not a stored registry:namesystemPrompt
parentRunIdon stored run headers and invocation/run lineage.agentNamedisplay metadata on the child run header, copied fromAgentSpec.name; do not store the child system prompt in the run header.- A narrow child-run starter, for example
RuntimeKernel.startChildTurn(parentRunId, spec, prompt), exposed to the spawn tool asspawnChildAgent(spec, prompt)or an equally narrow capability. Do not expose fullSessionManager/RuntimeKernelto tools.
Use existing or derived state instead of new duplicates:
- Delegation prompt: first child input event, not a header copy.
- Child identity:
runId+parentRunId, notRuntimeEvent.branchfor Day 1. - Parent linkage: use
parentRunIdbecause inspect/output and runtime ledgers are run-keyed; mirror existing turn lineage only where the current turn-state machinery needs it. - Permission mode: Day 1 spawn policy always runs the child in
explore; do not put a general permission profile inAgentSpecyet. - Recursion limit: child backend does not receive the spawn tool; no Day 1
maxDepthfield is needed. - Consumed state: parent tool result / event, not a mutable header flag.
- Failures: existing
InvocationFailure/AgentRunHeader.failureClass; headlessAutonomousResultTaxonomyonly when headless eval is involved.
Do not add:
SubagentRunSubagentEventPermissionProfileArtifactRef- a subagent-specific failure taxonomy
- fake
AgentRunrows for deterministic tools - a stable custom-agent registry until users can actually define reusable project agents
Important boundaries
Same session is acceptable, but child execution still needs its own backend instance built with the child header and AgentSpec.systemPrompt. The current active-session path is one backend per session; startChildTurn must not accidentally reuse the parent backend through that slot. Either inject a child-built backend into the child AgentRun path or make the child starter own the child backend lifecycle explicitly.
Child backend lifecycle is run-scoped. Parent stop/abort must stop and dispose all active child backends, and child finalization must not incorrectly mark the session active while the parent run is still active.
Default session/chat read models, branch copy, and model-history reconstruction must exclude child runs by default. The parent transcript should contain only the spawn tool call/result or explicit child summary, not the child's raw event stream.
The child receives no implicit prior parent/session context in Day 1. Its first model input is the delegation prompt plus any explicit context the spawn tool chooses to pass.
Day 1 child toolset should contain only non-prompting read-only tools, such as read and shell_safe. Exclude web_read, custom_tool, and subagent until per-backend permission routing exists; otherwise a child permission request has no reassuring route back to the right backend.
Parent abort must propagate into the child run and child backend. Slot release should be tied to child finalization, including cancellation and failure.
Restart recovery must not leave a child permanently running. Day 1 can rely on the existing run recovery sweep if the child run header is created before long awaits; otherwise explicitly mark abandoned children as cancelled/failed.
Artifact lookup for agent_output should use the child run header's turnId, because artifacts are keyed by session/turn rather than only by run id.
First runnable path
Enable only:
- foreground
agent-as-toolexecution - read-only LLM child agent
- same session by default, linked by
parentRunId - fresh child
turnId, distinct from the parent turn - real child run through existing
startTurn/AgentRunwiring - separate child backend with
explorepermissions and the child system prompt - allow-only local read toolset for the child, with no prompting categories and no spawn tool
- existing subagent tool slot cap for concurrent foreground spawn tool calls in the parent turn
agent_list/agent_outputas thin projections over existing run/event/artifact read models
Keep out of Day 1:
- write-capable subagents
- background subagents
- nested subagents beyond one level
- child web/custom tools that require permission prompts
- full handoff
- parallel workflow templates
- custom project agent library / stable agent registry
Acceptance criteria
- Parent can spawn a read-only LLM child agent through a tool call.
- Child is stored as a real
AgentRunthrough existingstartTurn/AgentRunwiring. - Child run header records
parentRunIdandagentName. - Child run has a fresh
turnIddifferent from the parent turn. - Child events use existing
RuntimeEvent/AgentRunEventpaths. - Default parent/sibling session views and future model context do not automatically absorb child runtime events.
- Child does not automatically inherit prior parent/session context.
- Parent receives an explicit child result through the tool result/event path.
- Child runs with a separate backend using the child system prompt and
explorepermissions. - Child receives no tools that can write files, spawn another subagent, or trigger a permission prompt.
- Parent abort cancels the child, stops/disposes the child backend, and releases the slot.
- Restart recovery does not leave child runs permanently
running. agent_listislistSessionRuns(sessionId)filtered to runs withparentRunId, plus header display metadata.agent_outputuses existing run inspect/events plus childturnIdartifact lookup.- Permission denial, timeout/budget, tool failure, model failure, cancellation, and incomplete result map to existing failure concepts.
- UI can show a subagent card with agent name, status, permission mode, elapsed time, result summary, and artifact ids.
Suggested PR sequence
- Add
parentRunId/agentNamerun metadata and update default read models plus model-history reconstruction to exclude child runs by default. - Add minimal inline
AgentSpecand a narrowstartChildTurn/spawnChildAgentseam that reusesstartTurn/AgentRunwiring without reusing the parent backend. - Add foreground spawn tool: child backend lifecycle,
explorepolicy, allow-only local read toolset, abort propagation, and slot release. - Add
agent_list/agent_outputprojections over existing run inspect/events/artifacts. - Add UI card / child inspect view.
- Add runtime/headless tests for context isolation both directions, backend separation, abort, recovery, permission-prompt exclusion, and artifact lookup.
Umbrella: #15
Activity