Skip to content

EN Course 10 Sub Agent Runtime

lloydzhou edited this page Jun 1, 2026 · 2 revisions

Sub-Agent Runtime

SubAgent is not just another output-producing tool. It starts a restricted child agent runtime that reuses the same major layers as the parent:

child session
  -> agent loop
  -> prompt builder
  -> transport
  -> tools
  -> store/events/stats

The restriction is intentional: nested delegation is limited so a child runtime does not recursively fan out without control.

The tool starts a child agent session:

tool_sub_agent() {
    local prompt="$1" description="$2" fork="${3:-false}" sub_session_id child_dir parent_dir
    sub_session_id="sub_$(util_new_session_id)"
    parent_dir="$(dirname "$CONV_FILE")"
    child_dir="$(dirname "$parent_dir")/$sub_session_id"
    # child loop runs in the background and reports result back through the input FIFO
}

Isolation and Fork Mode

There are two modes:

  • default: a fresh child session with its own conversation
  • fork: copy selected parent context into the child session before running

Fork mode is useful when the child needs the parent’s working context. Default mode is better for independent investigation.

Result Injection

The child does not return as a normal synchronous tool result. It sends a structured result back to the parent input queue:

AGENT_RESULT <session_id> <status> <text> <in> <out> <cache_read> <cache_creation> <requests>

The parent records a sub_agent_result event and starts another model turn so the assistant can interpret the child result.

This is why SubAgent sits late in the course: it combines session store, prompt construction, transport, tools, display events, and stats into a second runtime instance.

Async Sequence (Minimal)

parent tool call
  -> child launched (background)
  -> parent continues
  -> child finishes and emits AGENT_RESULT
  -> parent appends sub_agent_result event
  -> parent triggers next model turn

This separation explains why results arrive later and why the model must match messages by session_id.

Failure Handling

Typical statuses include success and failed. On failure:

  • result text can be partial or empty
  • token counters may still be present
  • parent should not assume retries happened

Handling rule: treat child output as an external async signal, then decide whether to continue, retry, or decompose the task differently.

Next

Runtime Parity closes the course by showing how the same boundaries are kept across Bash, C, Go, and Rust.

Clone this wiki locally