Foreground and Background Runs¶
Delegation tools are model-facing tools added to the parent's profile. They are not global Python functions and not Kedi statements. The names below describe the schema that the model sees.
Foreground Result¶
delegate_task(subagent, task, final_schema=None, background=False) waits for
the selected direct child and returns run_id, subagent, task_summary, and
final_result. Use foreground work when the next parent step depends on it.
Every ordinary delegation starts a fresh conversation. A failure raises instead of returning a success-shaped envelope with fabricated output.
Background Handle¶
With background=True, a supported adapter starts the child and returns a
handle such as:
This is an admission acknowledgment, not a result. The child may fail after the
handle is returned. Retain the exact run_id; do not construct one from a
profile name or assume it identifies every call to that profile.
| Tool | Returned data | Interpretation |
|---|---|---|
subagent_status(run_id) |
run_id, subagent, status |
Snapshot only; does not observe the result. |
wait_subagent(run_id, timeout=None) |
Completed result envelope | Successfully consumes the result. Repeated waits are allowed. |
wait_subagent(run_id, timeout=...) while still running |
Running handle | The caller stopped waiting; the child is still active. Wait again later. |
cancel_subagent(run_id) |
run_id, cancel_requested, status |
Cancellation request, not proof that the child has stopped. |
Lifecycle states are pending, running, completed, failed, cancelled,
and timed_out. A cancellation response can still report running while the
child processes cancellation. Repeated cancellation is idempotent.
Two Different Timeouts¶
The optional wait_subagent timeout bounds only that wait. It does not restart
or cancel the child. If the child is still running, the tool returns its handle
so the parent can do other work and wait again.
The runtime's subagent_timeout_seconds bounds the child itself, starting when
it is started, not on its first wait. Repeated short waits do not extend that
deadline. A child deadline produces a timed_out run and a failed wait, not a
running handle. See Limits and Safety.
Observe Before Returning¶
Under fail-closed delegation policy, a parent cannot claim completion while
delegated work is unresolved. Background work must be successfully observed
through wait_subagent. Status inspection and cancellation alone are not
successful observation. A failed task may be recovered by a successful
replacement under the delegation recovery rules; ignoring it is not recovery.
Unknown or expired IDs, a failed/cancelled/timed-out child, invalid structured results, and unresolved work are explicit failures. Do not convert these into empty findings or an affirmative approval.
Ownership and Cleanup¶
Live tasks belong to a runtime and an event loop. A handle is not a portable job URL. Closing the runtime cancels and joins its owned children; it does not leave them executing as detached host processes. Finished handles are retained only within bounded retention.
Pydantic AI, LangChain, Claude and Codex support background lifecycle tools. DSPy's bridge supports blocking delegation and continuation but not the background lifecycle. See the capability matrix.
For durable completed results rather than live task migration, see Continuations and Persistence.