subagents source, OpenHarness auto-registers a task tool that lets the parent spawn child agents by name.
Basic Setup
task tool listing the available subagents. It can call task with an agent name and a prompt, and the child runs to completion autonomously.
Key Behaviors
- Stateless by default — each
taskcall creates a fresh subagent instance with no shared conversation state - No approval — subagents run autonomously without prompting for permission
- Configurable nesting — by default subagents cannot themselves have subagents (
maxSubagentDepth: 1). Set a higher depth to enable nested delegation. - Abort propagation — the parent’s abort signal is forwarded to the child
- Concurrent execution — the model can call
taskmultiple times in one response to run subagents in parallel
subagentSessions.
Dynamic Catalogs
subagents can be either a static Agent[] or a dynamic catalog:
task tool schema and description stay in sync with whatever agents are currently available.
Nested Subagents
By default, subagents cannot delegate further. SetmaxSubagentDepth to allow nesting:
explore gets depth 1, and search gets depth 0.
Resumable Subagent Sessions
To let subagents keep their own message history across multipletask calls, enable subagentSessions. This layers Session persistence on top of the built-in task tool while keeping Agent itself stateless.
subagentSessions enabled, task accepts an optional session object:
Session Modes
| Mode | Behavior |
|---|---|
stateless | Current behavior. Fresh child agent, no saved history. |
new | Create a new persistent subagent session and return its session_id. |
resume | Load an existing session by ID and continue from its saved history. |
fork | Clone an existing session into a new session_id, then continue from there. |
Configuration
| Option | Default | Description |
|---|---|---|
messages | (required) | SessionStore used to save and load subagent messages |
metadata | in-memory | Tracks sessionId -> agentName and timestamps |
defaultMode | stateless | Default mode when task(..., session) is omitted. Only stateless and new are valid defaults. |
sessionOptions | — | Extra Session options to apply to child sessions (compaction, retry, hooks, etc.) |
new, resume, or fork, the tool result includes session_id="...":
sessionId is already running, the next resume or fork attempt fails instead of interleaving histories.
Live Subagent Events
To observe what subagents are doing in real time, pass anonSubagentEvent callback:
path parameter is a string[] representing the full ancestry from outermost to innermost agent. Events from nested subagents automatically bubble up through the chain.
Background Subagents
By default, all subagent calls are synchronous. EnablesubagentBackground to let the parent spawn subagents in the background, do other work, and collect results later.
taskgains an optionalbackgroundparameter. Whentrue, the subagent is spawned in the background and the tool returns immediately with a run ID.agent_awaitis registered for waiting on background runs using different strategies.agent_statusandagent_cancelare registered for checking and cancelling runs.
- run ID — returned as
agent_id="bg-1"and used withagent_status,agent_await, andagent_cancel - session ID — returned as
session_id="sub-123"and used with latertask(..., session: { mode: "resume", id: "sub-123" })
Await Modes
| Mode | Behavior |
|---|---|
all | Wait for all runs to succeed. Fails fast if any run fails. |
allSettled | Wait for all runs to finish. Returns results and errors. |
any | Wait for the first run to succeed. Only fails if all runs fail. |
race | Wait for the first run to settle (succeed or fail). |
Configuration
Passtrue for sensible defaults, or an object for fine-grained control:
| Option | Default | Description |
|---|---|---|
maxConcurrent | Infinity | Maximum number of background runs running simultaneously |
timeout | — | Auto-cancel background runs after this many milliseconds |
autoCancel | true | Cancel all running background runs when agent.close() is called |
tools.status | true | Register the agent_status tool |
tools.cancel | true | Register the agent_cancel tool |
tools.await | all four modes | Which await modes to expose (true = all, false = disable, or an array) |
Cleanup
Background subagents respect the parent’s abort signal. WhenautoCancel is true, calling agent.close() cancels any still-running background runs.