Skip to main content

Overview

SubagentRegistry runs agent tasks in the background on a ThreadPoolExecutor, tracking each as a SubagentTask with status, retries, depth, and parent linkage. Use it when one agent needs to fan out work to other agents — recursively if needed — and gather results later. The module exports three symbols:

Installation

TaskStatus

Backed by (str, Enum), so the values compare equal to plain strings (TaskStatus.PENDING == "pending").

SubagentTask

Dataclass describing a single in-flight or completed task. Populated by SubagentRegistry.spawn().
str
Unique task ID, e.g. task-a1b2c3d4.
Any
The agent instance assigned to this task.
str
The prompt/task handed to agent.run(...).
TaskStatus
default:"TaskStatus.PENDING"
Current execution status.
Any
default:"None"
Return value from the agent — set when status == COMPLETED.
Exception | None
default:"None"
Last exception raised — set when status == FAILED.
concurrent.futures.Future | None
default:"None"
Underlying Future returned by the thread pool.
str | None
default:"None"
ID of the parent task that spawned this one, if any.
int
default:"0"
Recursion depth — incremented when an agent spawns another subagent.
int
default:"0"
Number of retries used so far.
int
default:"0"
Retry budget for this task.
List[Type[Exception]] | None
default:"None"
Whitelist of exception classes that trigger retries. None retries on any exception.
float
Unix timestamp when the task was spawned.
float | None
default:"None"
Unix timestamp when the task entered a terminal state.

SubagentRegistry

Constructor

int
default:"3"
Maximum recursion depth. spawn() raises ValueError if depth > max_depth.
int | None
default:"None"
Thread-pool size. None defers to ThreadPoolExecutor’s default.

Methods

spawn()

Submit an agent task to the pool. Returns the new task ID synchronously; the agent runs in the background.
Any
required
Agent instance with a .run(task) method.
str
required
The prompt to run.
str | None
default:"None"
Set when this task was spawned by another task. Used for tracking trees.
int
default:"0"
Recursion depth. Spawning from inside another task increments this.
int
default:"0"
Retry budget on failure.
List[Type[Exception]] | None
default:"None"
Only retry on these exception types. None retries on any exception.
bool
default:"True"
When True, the underlying thread re-raises on final failure (the exception surfaces when you call future.result()). When False, the failure is captured on the SubagentTask and the thread returns None.
Raises: ValueError if depth > max_depth.

get_task()

Look up a SubagentTask by ID.
Raises: KeyError if the ID is not in the registry.

get_results()

Return a Dict[task_id, Any] for every completed or failed task. Failed tasks map to their exception object.

cancel()

Attempt to cancel a not-yet-started task. Returns True if the underlying Future accepted the cancellation.

gather()

Block until tasks complete and return a list of results.
"wait_all" | "wait_first"
default:"\"wait_all\""
Wait policy. "wait_all" returns once every pending task settles; "wait_first" returns as soon as one does.
float | None
default:"None"
Max seconds to wait. None blocks indefinitely.
Returns: Mixed list — successful tasks contribute their result, failed tasks contribute their exception object.

shutdown()

Tear down the thread pool without waiting for outstanding tasks.

tasks

Read-only property — snapshot of all known tasks as Dict[task_id, SubagentTask].

Usage Examples

Fan Out, Gather, Map by Agent

Retries on Specific Exceptions

Retry only on transient network errors; surface anything else immediately.

Take the First Successful Result

Depth-Limited Recursion

Source Code

View the source on GitHub.