Subagent tree
The subagents a parent agent started, what each one is doing right now, and what it handed back. Six layouts, from a line in the reply to a run inspector.
Loading preview…
Install
- 1
Run this command in your Tailwind CSS project. It adds
components/ai/subagent-tree-default.tsxand installs its dependencies.$ npx shadcn@latest add https://gradientdeck.com/ai-components/r/subagent-tree-default.json
Usage & API
Example
import { SubagentTree } from "@/components/ai/subagent-tree-default"
<SubagentTree
agents={[]}
/>Props SubagentTree
| Prop | Type & description | Required |
|---|---|---|
agents | Subagent[] | Required |
label | stringDefaults to "Started 3 agents". | Optional |
defaultOpen | boolean | Optional |
logLimit | numberHow many log lines to show in an opened row. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
Subagent tree takes agents, an optional label, defaultOpen and logLimit. The header button uses label, or Started N agents. Under it, a live summary counts running, waiting, done and failed, or says all done. When nothing is active, the header also shows the longest elapsed time. Each agent row shows a color dot, name, task, and, on a wide container, tool count, token count and elapsed. Collapsed, the row's second line is the result, an error, a waiting sentence that names the call it wants approval for, or the call it is currently making. Opening the row shows role, the task again, and the last logLimit entries of log. Older calls are counted as N earlier. A waiting call inside that log reads Needs approval. defaultOpen defaults to true. logLimit defaults to 6. Tokens format as a raw count under 1000 and as thousands otherwise. Elapsed formats as seconds, or as minutes and seconds.
Example
import { SubagentDock } from "@/components/ai/subagent-tree-dock"
<SubagentDock
agents={[]}
/>Props SubagentDock
| Prop | Type & description | Required |
|---|---|---|
agents | Subagent[] | Required |
onStop | (id: string) => voidCalled from the stop button on a running or waiting agent. Leave out to hide the button. | Optional |
defaultOpen | boolean | Optional |
tickerInterval | numberHow long each agent stays in the collapsed ticker, in ms. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
The dock takes agents, optional onStop, defaultOpen and tickerInterval. It is a strip with a flat bottom edge, meant to sit on the composer. The button shows up to four avatars, then N agents working or N agents finished, then a note if any need approval or any failed. Beside that, one active agent is named with what it is doing. If any agent is waiting, only the waiting agents rotate through that slot. Otherwise the running agents do. tickerInterval is how long each stays, in milliseconds, defaulting to 2400. Opening the strip lists every agent with status, the action line, and elapsed. onStop adds a stop button on running and waiting rows only. Omit onStop and that control is absent. Stopped is its own status, with the result you pass, such as a line that the person halted it. defaultOpen defaults to false.
Example
import { SubagentRoster } from "@/components/ai/subagent-tree-roster"
<SubagentRoster
agents={[]}
/>Props SubagentRoster
| Prop | Type & description | Required |
|---|---|---|
agents | RosterAgent[]The main agent first, then its subagents. | Required |
selectedId | string | Optional |
defaultSelectedId | string | Optional |
onSelect | (id: string) => void | Optional |
onApprove | (id: string) => void | Optional |
onDeny | (id: string) => void | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
The roster takes agents, with the main agent first, then optional selectedId, defaultSelectedId, onSelect, onApprove and onDeny. The list shows the main agent, a Subagents label, and the rest. The corner reads N of M running, and that N includes subagents that are waiting as well as running. When neither status is present, it reads that the subagents have finished. Each row has initials, a status dot, and a line: the approval it wants, the failure, the summary, the activity override, or its latest call. Unread work on an agent you are not looking at draws a dot. The detail pane shows the brief, introduced as Brief from plus the from name, or as Your request when from is omitted, then the calls. A call whose tool is Task and whose target matches another agent's id becomes a jump to that agent. A waiting agent shows the approval command and, if you passed the callbacks, Allow once and Deny. A result block is labeled Returned to plus the from name, or Summary when from is omitted. Tokens and elapsed sit in the detail header. An empty agents array renders nothing.
Example
import { SubagentFeed } from "@/components/ai/subagent-tree-feed"
<SubagentFeed
agents={[]}
entries={[]}
/>Props SubagentFeed
| Prop | Type & description | Required |
|---|---|---|
agents | FeedAgent[] | Required |
entries | FeedEntry[] | Required |
elapsed | numberSeconds since the run started, shown next to the filters. | Optional |
height | numberHeight of the scrolling stream in pixels. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
The feed takes agents, entries, optional elapsed and height. An agent has id, name, color and status. An entry has id, agentId, at in seconds, kind, text, and optional target, result and tone. kind is tool, approval, note or summary. The filter row starts with All and the entry count, then one chip per agent with that agent's line count. The visible chip is the name and the count. Its accessible name also includes the status, such as waiting for approval. Choosing a chip filters the log and pins it to the bottom. Choosing it again clears the filter. elapsed, when passed, is a clock beside the chips. The log is a scrolling region of the given height, default 288 pixels. Each line shows the time, the agent name when the speaker changes, and the entry. A summary is a block reading Returned, or Stopped when tone is error. An approval line is the amber one. A note is dim text. If the reader scrolls up, the view stops following and a Jump to latest control appears, with a count of lines that arrived below. An empty filter reads Nothing yet.
Example
import { SubagentLanes } from "@/components/ai/subagent-tree-lanes"
<SubagentLanes
title="…"
parent={parent}
agents={[]}
now={1}
/>Props SubagentLanes
| Prop | Type & description | Required |
|---|---|---|
title | string | Required |
parent | LaneThe agent that started the others. Its lane sits on top. | Required |
agents | Lane[] | Required |
now | numberSeconds since the run started. | Required |
minRange | numberShortest stretch of time the axis shows, in seconds. | Optional |
Dependencies
- React
- Tailwind CSS
- lucide-react
Implementation notes
Lanes take title, parent, agents, now and optional minRange. parent is the agent that started the others and sits on the first row. Each lane has id, name, task, color, status, startedAt, optional endedAt, and spans. A span has kind of read, search, edit, run or approval, a start in seconds, an optional end, a target, an optional result, and an optional failed flag. The header shows title, then N of M returned for the subagents whose status is done or failed, then the clock for now. The parent lane is not part of that count. The axis runs at least minRange seconds, default 60, and longer as now grows. A now marker is drawn while the parent is running or waiting. Hovering or focusing a segment opens a tip with the kind, the target, the start, and either that it is still going or the end and the length. A span with no end is treated as running up to now. An approval segment reads Waiting for approval. A finished lane prints its duration after endedAt. Failed spans use the error color instead of the kind color.
Example
import { DelegationTree } from "@/components/ai/subagent-tree-delegation"
<DelegationTree
root={root}
/>Props DelegationTree
| Prop | Type & description | Required |
|---|---|---|
root | DelegationNode | Required |
defaultCollapsed | string[]Ids of nodes whose subtree starts collapsed. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
Delegation tree takes root and optional defaultCollapsed. A node has id, name, initials, color, status, elapsed, optional ask, optional returned, optional tools, optional tokens, and optional children. The row shows the avatar, the name, a status of Running, Needs approval, Done or Failed, then tools and tokens on a wide container, then elapsed. ask is the parent's instruction, shown on the edge into the node. returned appears on that edge once you set it, with a return mark, and a failed node's return uses the error color. The edge is dashed while the node is running or waiting, and solid otherwise. A node with children has a toggle labeled to hide or show the agents it started. Collapsed, the toggle shows the descendant count. defaultCollapsed lists ids whose subtrees start closed. The root is not indented and has no edge into it.
Choosing a layout
Use the transcript tree when the parent should mention the helpers inside its own reply and then move on. The header summarizes how many are running, waiting, done or failed, and each row shows the task plus the call in flight or the result. Open a row for that agent's own log. Use the dock when those same agents are background work and the composer must stay usable. The collapsed strip rotates through the active agents, and if any are waiting it rotates through only those. Pass onStop only if the person is allowed to halt one.
Use the roster when someone will supervise the run: switch agents, read the brief, and allow or deny a command. Use the feed when the interesting fact is the order things happened across agents, not the tree. Use the lanes when overlap matters, because a shared axis shows who was busy while someone else waited. Use the delegation tree when the nesting itself is the story, including agents started by agents, and a collapsed node should show how many descendants it hides. A todo list or a step timeline is a better fit when there are no separate agents, only steps of one run.
Which layout can stop or approve an agent?
The dock can stop one. Pass onStop and a running or waiting row shows a stop button that calls it with the agent id. Omit the prop and the button is not rendered. The roster can approve or deny the command in approval, through onApprove and onDeny, and only while that agent's status is waiting. The other four layouts do not render those decisions. A waiting state there is a label, or a segment, not a button.
Do tool calls share one shape across the six layouts?
They do not. The transcript tree's call has kind, target, detail and status. The dock's call has kind and target. The roster's call has a tool name such as Read or Task, a target, a result and a tone. The feed uses entries with a kind of tool, approval, note or summary. The lanes use spans on a clock. Pass the shape that layout declares, even when two of them describe the same run.