Skip to main content

Module subagent

Module subagent 

Source
Expand description

Subagent lifecycle: SUBAGENT_STARTED, SUBAGENT_FINISHED, SUBAGENT_ERROR.

Many frameworks let an agent delegate to child agents — a supervisor dispatching research tasks, an agents-as-tools pattern where a tool call is a nested agent, a planner farming out subtasks in parallel. To a frontend all of that arrives as one event stream, and without extra information three concurrent researchers render as one undifferentiated wall of text.

The protocol’s subagent support solves exactly that and nothing more: it attributes each event to the subagent that produced it, and reports when subagents start and stop. It does not orchestrate, schedule or define subagents — that stays with the framework.

§Attribution

Most events carry an optional subagentRunId naming who produced them — the text, tool-call, activity, reasoning, step and state families, plus RAW and CUSTOM. An event without one belongs to the parent agent, so a stream that never sets the field behaves exactly as it did before subagents existed. The events that describe the run as a whole — RUN_STARTED, RUN_FINISHED, RUN_ERROR — cannot carry it, and neither can MESSAGES_SNAPSHOT, whose messages carry their own. See Event::subagent_run_id and EventType::is_attributable.

Attribution stands on its own: a producer may tag events without ever emitting the three lifecycle events, and a consumer must accept an identifier it never saw announced. Attribution on STATE_* is provenance, not ownership — the state stays run-scoped, and an attributed snapshot replaces the run’s state like any other. There is no per-subagent state.

§subagentRunId names an invocation, not a definition

The easiest thing to get wrong. A SubagentRunId is an opaque handle for one invocation: run the same subagent twice and you get two values. It is not a name and not a stable id for a reusable definition — that is SubagentStartedEvent::name. The symmetry with the top-level run is the way to remember it: agentId is to runId as name is to subagentRunId.

The one exception is suspension. A subagent that finished with SubagentOutcome::Suspended may reuse its id on the run that resumes it; a consumer treats that later SUBAGENT_STARTED as a continuation, never a duplicate.

§Compatibility

Attribution is additive and safe — an unknown field is tolerated — but the three lifecycle events are unknown event types to a client older than subagent support, and such a client fails while decoding, before any application code runs. A producer with older consumers must not emit them; the server runtime’s SubagentVisibility transformer exists for that.

The model here follows upstream’s docs/concepts/subagents.mdx.

Structs§

SubagentErrorEvent
Marks a subagent invocation as failed.
SubagentFinishedEvent
Closes a subagent invocation’s stream segment for this run.
SubagentStartedEvent
Announces a subagent invocation and gives it a name a UI can display.

Enums§

SubagentOutcome
How a subagent invocation’s stream segment closed for this run.