Skip to main content
When a coordinator agent spawns specialist subagents — a researcher, an analyst, a writer — you need to render the orchestrator’s messages separately from each subagent’s streaming output. Set filterSubagentMessages: true in useStream to cleanly split these two streams, then use getSubagentsByMessage to attach each subagent’s progress card to the coordinator message that triggered it.

Why filter subagent messages

Without filtering, every token produced by every subagent appears interleaved in the coordinator’s message stream — making it unreadable. With filterSubagentMessages: true:
  • stream.messages contains only the coordinator’s messages
  • Each subagent’s content is accessible through stream.subagents and stream.getSubagentsByMessage
  • The UI stays clean: the coordinator’s reasoning is separate from the specialists’ work
This separation lets you render the orchestrator’s messages in one place and attach each subagent’s progress card exactly where it belongs — beneath the coordinator message that spawned it.

Setting up useStream

Always set filterSubagentMessages: true. This removes subagent tokens from the main message stream so you can render the coordinator’s messages and subagent output independently. Define a TypeScript interface matching your agent’s state schema and pass it as a type parameter to useStream for type-safe access to state values. In the examples below, replace typeof myAgent with your interface name:

Submitting with subgraph streaming

When submitting a message, enable subgraph streaming and set an appropriate recursion limit. Deep agent workflows often involve multiple layers of nested subagraphs, so a higher recursion limit prevents premature termination:
DeepAgents sets a default recursion limit of 10,000, which is sufficient for most multi-expert setups. You can override this via config.recursion_limit if needed.

The SubagentStreamInterface

Each subagent exposes a SubagentStreamInterface with metadata about the subagent’s task, status, and timing:

Linking subagents to messages

The getSubagentsByMessage method returns the subagents spawned by a specific AI message. This lets you render subagent cards directly beneath the coordinator message that triggered them:
This returns an array of SubagentStreamInterface objects. If the message didn’t spawn any subagents, it returns an empty array.

Building the SubagentCard

Each subagent card shows the specialist’s name, task description, streaming content or final result, and timing information:

Status icons and badges

Consistent visual indicators help users parse subagent status at a glance:

Progress tracking

Show a progress bar and counter so users know how many subagents have finished:

Rendering messages with subagent cards

The key layout pattern: render each coordinator message, and if that message spawned subagents, render their cards immediately below it:

Synthesis indicator

After all subagents complete, the coordinator takes time to synthesize their results into a final response. Show a clear indicator during this phase:
The synthesis phase can take several seconds for complex multi-expert workflows. A clear “Synthesizing results…” indicator prevents users from thinking the agent has stalled.

Debug unfiltered output

During development, you can temporarily set filterSubagentMessages: false to see the raw, interleaved output from all subagents in the main message stream. This is useful for verifying that subagent tokens are flowing correctly, but should not be used in production UIs.

Use cases

Deep agent subagent cards are the right choice when your agent workflow involves:
  • Deep research — a coordinator dispatches researchers to investigate different facets of a question, then synthesizes their findings
  • Multi-expert analysis — domain specialists (legal, financial, technical) each contribute their perspective
  • Complex task decomposition — a planner breaks a large task into subtasks and assigns each to a specialist worker
  • Code review pipelines — separate agents handle security review, style checking, performance analysis, and documentation review

Accessing the full subagents map

Beyond per-message lookup, you can access all subagents at once through stream.subagents:
This is useful for building global progress indicators or dashboards that summarize all subagent activity regardless of which coordinator message spawned them.

Best practices

  • Always set filterSubagentMessages: true. Unfiltered streams produce an unreadable interleaving of coordinator and subagent tokens.
  • Show task descriptions — the toolCall.args.description field tells users exactly what each subagent was asked to do. Always display this prominently.
  • Use collapsible cards — in workflows with 5+ subagents, auto-collapse completed cards so users can focus on active work.
  • Display timing data — showing how long each subagent took helps users understand performance characteristics and identify bottlenecks.
  • Set an appropriate recursion limit — deep agent workflows with nested subgraphs need higher limits than the default 25. Start with 100.
  • Handle errors per subagent — one subagent failing shouldn’t crash the entire UI. Show the error in that subagent’s card while others continue running.