Skip to content

Sub-agents

Run graphs as sub-agents of a node, in this process or on a background executor. See Sub-agents.

Spawn and gather

spawn_agents

async spawn_agents(tasks, *, parent_thread_id=None, thread_prefix=None, registry=None) -> list[AgentHandle]

Start sub-agents concurrently on their own threads.

Each sub-agent runs on the thread "<prefix>:sub:<handle id>", or "sub:<handle id>" without a prefix. Every state_in runs before any sub-agent starts.

Parameters
taskslist[AgentTask]

Sub-agents to start.

parent_thread_idstr | None

Prefix for the generated thread ids.

thread_prefixstr | None

Thread prefix; wins over parent_thread_id.

registryAgentRegistry | None

Registry that tracks the handles.

Raises
TypeError

If a task has no input.

ValueError

If thread_prefix is empty.

gather_agents

async gather_agents(handles, *, timeout=None, return_exceptions=False, registry=None) -> list[AgentResult]

Wait for sub-agents and collect their results.

Parameters
handlesSequence[AgentHandle | str]

Handles returned by spawn_agents, or their ids, which need registry.

timeoutfloat | None

Seconds to wait before cancelling the unfinished sub-agents.

return_exceptionsbool

Return failed and cancelled results, with the exception in AgentResult.error, instead of raising.

registryAgentRegistry | None

Registry the handles were registered with.

Returns
list[AgentResult]

Results in the order of handles.

Raises
AgentTimeoutError

If the timeout expires first.

AgentGroupError

If a sub-agent failed or was cancelled and return_exceptions is False; it holds every result.

AgentHandleLostError

If a handle is not in registry.

TypeError

If a handle id is given without registry.

AgentTask

AgentTask(graph, input, name=None, state_in=None, state_out=None, on_progress=None, context=None)

A graph to run as a sub-agent.

Attributes
graphGraph

Graph to run.

inputAny

Input of the sub-agent's run. None continues an existing thread and is accepted only by AgentExecutor.submit with thread_id=.

namestr | None

Display name; defaults to the graph name.

state_inCallable[[Any], Any] | None

Maps input before the run; needs an input.

state_outCallable[[dict[str, Any]], dict[str, Any]] | None

Maps the final state dict to the result's data; must return a dict.

on_progressCallable[[AgentStatus], None] | None

Called with the AgentStatus after every superstep and once at the end. If it raises, the sub-agent stops with an "error" result holding that exception and the callback is not called again; an exception raised for "cancelled" is dropped.

contextobject | None

context= of the sub-agent's run; the parent's context is not passed.

AgentHandle

AgentHandle(id, name, task, graph_name, thread_id)

Handle to a sub-agent running in the current process.

Attributes
idstr
namestr
taskTask[AgentResult]

The asyncio task running the sub-agent.

graph_namestr
thread_idstr

Thread the sub-agent runs on.

Methods

done()

Whether the sub-agent has finished.

done() -> bool

async status()

Return the current status of the sub-agent.

async status() -> AgentStatus

AgentResult

AgentResult(id, name, state, data, status, error=None, thread_id=None, checkpoint_id=None)

Outcome of a sub-agent run.

Attributes
idstr

Id of the handle the sub-agent was started with.

namestr
stateAny

Final state as the graph's state type; None when the run failed.

datadict[str, Any]

Final state as a dict, or what state_out returned; empty when the run failed.

statusstr

"completed", "interrupted", "error" or "cancelled".

errorBaseException | None

What stopped a failed or cancelled run.

thread_idstr | None

Thread the sub-agent ran on.

checkpoint_idstr | None

History event to load the final or interrupted state at; None without a state store.

AgentStatus

AgentStatus(id, name, status, step, node, thread_id, updated_at)

Progress of a sub-agent, derived from its own stream events.

Attributes
idstr

Handle id of the sub-agent.

namestr

Display name of the sub-agent.

statusLiteral['running', 'completed', 'interrupted', 'error', 'cancelled']

Where the sub-agent is.

stepint

Number of supersteps the sub-agent's thread has finished; 0 before the first one finishes.

nodestr | None

Last node that finished; None before the first superstep.

thread_idstr | None

Thread the sub-agent runs on.

updated_atfloat

time.time() of the last change.

Background executors

AgentExecutor

Protocol for running sub-agents in the background.

Methods

async submit(task, ...)

Start a sub-agent.

async submit(task, *, thread_id=None, thread_prefix=None) -> DurableAgentHandle

Parameters
taskAgentTask
thread_idstr | None

Thread to run on.

thread_prefixstr | None

Without thread_id, the thread is "<prefix>:bg:<handle id>"; without either, "bg:<handle id>".

Raises
TypeError

If the task has a state_in but no input, or no input and no thread_id.

async poll(handle_id)

Return the result if the sub-agent finished, else None.

async poll(handle_id) -> AgentResult | None

Parameters
handle_idstr
Returns
AgentResult or None

A "cancelled" result for a cancelled sub-agent.

Raises
AgentHandleLostError

If the executor does not know handle_id.

async status(handle_id)

Return the current status of a sub-agent.

async status(handle_id) -> AgentStatus

Parameters
handle_idstr
Raises
AgentHandleLostError

If the executor does not know handle_id.

async cancel(handle_id)

Cancel a running sub-agent.

async cancel(handle_id) -> bool

Parameters
handle_idstr
Returns
bool

Whether a sub-agent was cancelled.

Raises
AgentHandleLostError

If the executor does not know handle_id.

async list_running()

List the sub-agents that are still running.

async list_running() -> list[DurableAgentHandle]

AsyncioExecutor

AsyncioExecutor(*, executor_id='asyncio')

Background executor that runs sub-agents as asyncio tasks in this process.

Keeps every sub-agent it started, finished or not, until forget.

Parameters
executor_idstr

Id stored on the handles it creates; "asyncio" by default.

Methods

async submit(task, ...)

Start a sub-agent as an asyncio task.

async submit(task, *, thread_id=None, thread_prefix=None) -> DurableAgentHandle

Parameters
taskAgentTask
thread_idstr | None

Thread to run on.

thread_prefixstr | None

Without thread_id, the thread is "<prefix>:bg:<handle id>"; without either, "bg:<handle id>".

Raises
TypeError

If the task has a state_in but no input, or no input and no thread_id.

ValueError

If thread_prefix is empty.

async poll(handle_id)

Return the result if the sub-agent finished, else None.

async poll(handle_id) -> AgentResult | None

Parameters
handle_idstr
Returns
AgentResult or None

A "cancelled" result for a cancelled sub-agent.

Raises
AgentHandleLostError

If the executor does not know handle_id.

async status(handle_id)

Return the current status of a sub-agent.

async status(handle_id) -> AgentStatus

Parameters
handle_idstr
Raises
AgentHandleLostError

If the executor does not know handle_id.

async cancel(handle_id)

Cancel a running sub-agent and wait until it stopped.

async cancel(handle_id) -> bool

Parameters
handle_idstr
Returns
bool

Whether a sub-agent was cancelled; False for sub-agents that had already finished.

Raises
AgentHandleLostError

If the executor does not know handle_id.

async forget(handle_id)

Release a finished or cancelled sub-agent; its id is unknown afterwards.

async forget(handle_id) -> None

Parameters
handle_idstr
Raises
AgentHandleLostError

If the executor does not know handle_id.

ValueError

If the sub-agent is still running.

async list_running()

List the sub-agents that are still running.

async list_running() -> list[DurableAgentHandle]

DurableAgentHandle

DurableAgentHandle(id, name, executor_id, graph_name, thread_id=None)

Handle to a sub-agent submitted to an AgentExecutor.

Attributes
idstr
namestr
executor_idstr

executor_id of the executor that runs the sub-agent.

graph_namestr
thread_idstr | None

Thread the sub-agent runs on.

Registry

AgentRegistry

Tracks the sub-agents spawned during one graph run.

Methods

register(handle)

Remember a spawned sub-agent.

register(handle) -> None

Parameters
handleAgentHandle

resolve(handle_id)

Look up a spawned sub-agent.

resolve(handle_id) -> AgentHandle

Parameters
handle_idstr
Raises
AgentHandleLostError

If the handle is not registered.

remove(handle_id)

Forget a sub-agent.

remove(handle_id) -> None

Parameters
handle_idstr

async cancel_all()

Cancel and forget every sub-agent that was not gathered.

async cancel_all() -> list[AgentHandle]

Returns
list[AgentHandle]

The sub-agents that were still registered, in spawn order, including finished ones whose results nobody collected.