Skip to main content
Delegated sub-agent runs execute synchronously today, so a child that pauses for human-in-the-loop (HITL) approval blocks the parent instead of returning a durable, resumable handle.
Do not assume delegated sub-agent runs are durable, restart-safe, or resumable after a HITL pause. The pieces required for resumable delegation are listed below.
An agent hits this limitation the moment a delegated child needs approval — the parent turn stalls. The background sub-agent path avoids the stall for long work but still does not resume a paused child:

Quick Start

1

See the blocking limitation

delegate_task runs the child synchronously. If that child reaches a HITL approval pause, the parent turn hangs — there is no durable handle to resume it.
2

Use the non-blocking workaround

Spawn the child in the background so the parent stays responsive, then collect the completed output with wait=True.
subagent_result defaults to wait=False, returning a {"status": "running", ...} handle if the job is unfinished. Pass wait=True (or poll until status is terminal) to collect the output. This avoids blocking the parent turn but is not a HITL resume flow.

How It Works

A HITL approval pause inside a delegated child has no path back to the parent turn, so the parent blocks on the child’s chat() call until the timeout fires. Convert the behaviour into what it means for you:

Which option should I pick?

Pick the delegation style by whether the child needs HITL approval and whether it may block.

Missing pieces for resumable delegation

The following pieces are required before delegated children can be considered resumable:
  1. Durable child session persistence through the session store.
  2. A child-run result-state contract, for example pending, completed, failed, and halted.
  3. HITL bubble-up from child to parent, so an approval pause creates a durable pending handle.
  4. A drive_child or equivalent continuation seam to resume the paused child.
  5. Ownership and lifecycle rules for cancellation, timeouts, and result collection.
Prefer a core-first increment: introduce an internal v0 child-run pause/resume contract before designing the full gateway UX. The first contract should be explicitly internal and anti-freeze — keep the resume handle opaque so later metadata (approval IDs, gateway routing, cancellation state) can be added without changing the parent-facing shape.

Proposed v0 state shape

A possible v0 state shape for the internal child-run contract:
Semantics:
  • pending: the child reached a HITL approval pause; the parent should receive a durable handle rather than block indefinitely. pause_reason is set (e.g. approval_required) and resume_token is non-null so the parent can continue the child. result and error are null.
  • completed: the child reached a terminal success state; the parent can collect the output from result. pause_reason, resume_token, and error are null.
  • failed: the child reached a terminal failure state; failure details are available in error. pause_reason, resume_token, and result are null.
  • halted: the child was cancelled or stopped in a non-resumable way that is not a normal success/failure (e.g. timeout or explicit cancellation). pause_reason and resume_token are null.
Separating completed (success) from failed (failure) lets consumers classify terminal outcomes consistently and know exactly where to read the result or the failure reason.

Best Practices

Nested @require_approval tools inside a delegated child do not bubble their approval prompt to the parent turn today — the parent hangs or fails opaquely. Keep approval-gated work out of synchronous delegation.
Run potentially blocking work in the background and pass wait=True to subagent_result(job_id) to collect the completed output. Poll with wait=False if you need to stay responsive between checks.
Delegated child sessions are not persisted through the session store today, so a daemon restart mid-child loses that work. Treat delegated results as ephemeral until resumable delegation ships.
Route the user directly to the specialist with Agent(..., handoffs=[specialist]) so approvals happen in the user’s live turn, not in a blocked worker thread.

Delegate Task

Sub-agent delegation from a parent agent.

Named Agent Delegation

Delegate to specific named agents.

Approval

Human-in-the-loop approval framework.

Run-State Journal

Durable per-event cursor for run resume — the primitive that would unblock Missing Piece #1.