Multi-Agent Orchestration (AskCollaborator)
This playbook shows how one orchestrator agent delegates subtasks to named specialist responders (a researcher and a writer) through the loopback-by-default AskCollaborator MCP tool. The wiring is code-only: you build collaborator responders, create a runtime extension, and attach it to the orchestrator per request.
For in-process helpers, the built-in Agent tool
provides a config-first option. Configure subagents.models to offer model choices,
then select model and effort on each call; omitted values inherit profile pins
or the parent’s effective route. For continued work in one conversation, create a
helper with persist: true and resume or close it using AgentManage; configure
subagents.instances for its idle TTL and caps. The collaborator setup below remains useful for
separately composed responders.
Who this is for
Section titled “Who this is for”Workflow designers composing specialist agents — you want a single orchestrator that decides when to hand a subtask to a researcher, a writer, or any other named collaborator, rather than doing everything in one prompt.
One orchestrator agent delegates subtasks to named collaborator responders (researcher, writer) via the loopback-by-default AskCollaborator MCP tool.
Features used
Section titled “Features used”orchestrator.ask-collaborator— loopback-by-default MCP tool delegating to named collaborator responders, with guarded non-loopback opt-in, call caps, and per-collaborator timeout (coverage: code).harness.request-runtime-options— per-request runtime option extensions viacreateConfiguredAgentResponder({ runtimeOptionsForRequest })(coverage: code).runtime.custom— custom runtime composition that drives the orchestrator (coverage: code).
Configuration
Section titled “Configuration”This capability is code-only — there is no mono-agent.config.json key for it. You construct the collaborator extension programmatically and pass its run options to the orchestrator’s responder. See programmatic composition and multi-agent.
After importing createConfiguredAgentResponder and
createCollaboratorToolRuntimeExtension, build the config and both collaborator
responders, then attach the request-scoped extension:
// Assume config and both collaborator responders have already been created.const orchestrator = await createConfiguredAgentResponder({ config, runtimeOptionsForRequest: async (input) => { const extension = await createCollaboratorToolRuntimeExtension({ collaborators: [ { id: "researcher", label: "Researcher", responder: researcherResponder }, { id: "writer", label: "Writer", responder: writerResponder }, ], conversationId: input.request.conversationId, originalUserMessage: input.request.userMessage, abortSignal: input.request.abortSignal, maxCalls: 10, }); return { runtimeOptions: extension.runtimeOptions, cleanup: extension.cleanup, }; },});- Build collaborator responders (one
createConfiguredAgentResponderper specialist, or A2A consumers). - Inside
runtimeOptionsForRequest, callcreateCollaboratorToolRuntimeExtensionwith the requiredcollaborators,conversationId,originalUserMessage, andabortSignalfields (plus optionalmaxCalls). - Return
{ runtimeOptions: extension.runtimeOptions, cleanup: extension.cleanup }from the callback so the host attaches the loopback tool and closes the ephemeral MCP server when the turn ends. - Run the orchestrator with a task that requires delegation.
- Inspect the run artifact for
AskCollaboratorcalls.
Smoke test
Section titled “Smoke test”For command-based workers, use background process jobs
to hand off Exec/Bash stages and resume from their completion turns.
processJobs.maxChainDepth defaults to 4 and accepts at most 64; choose a
budget for the workflow without resetting lineage. A depth-32 exhausted wake
cannot start another background stage when the configured budget is 32.
Use wake_on_completion: false explicitly for helpers whose terminal card
is sufficient, and treat an unknown wake receipt as non-replayable.
Related
Section titled “Related”- Programmatic: multi-agent
- Programmatic: composition
- Programmatic: A2A consumer
- Runtime backends
- Observability: artifacts and traces
- Composer skill:
mono-agent-composer(run/mono-agent-composerto scaffold and validate an agent from one config).
Let a persistent child ask for direction
Section titled “Let a persistent child ask for direction”Start a child with Agent({persist: true, prompt: "Review the design"}).
A child can call AskParent({question: "Which scope?", options: ["API", "UI"]})
to save its question and end its turn. The successful parent-facing result has
status awaiting_reply, an instance id, and the structured question. Answer with
AgentManage({id, message: "Focus on the API"}); the child resumes its own durable
context. Global or profile AskParent denies disable this dialogue. The child
cannot contact the user: the parent decides whether to answer or ask the user.
Failed replies leave the question pending. Close-only retires the instance;
there is no background execution or automatic wake in this dialogue path.
Detached persistent work
Section titled “Detached persistent work”Use Agent with persist:true, background:true when the current reply need not
wait for the child. Continue it with AgentManage and background:true plus a
message. The started receipt is durable, and the exact originating conversation
wakes on completion, failure, interruption or AskParent. Answer an awaiting
child with AgentManage. Do not poll or replay. A terminal childStillBusy:true job
means another send must wait for ownership resolution. Late settlement is not
proof that a failed transcript was retained: lost/unknown continuity requires
explicit close/create, and unavailable owners cannot be bypassed. See
background child lifecycle.
For long verification inside a child, use foreground Bash/Exec with
timeout_ms. Its ceiling is min(remaining budget, subagents.commandTimeoutMs)
at child-run setup (command default: 30 minutes): detached children use remaining
job runtime; foreground children use remaining turn time minus a settlement
reserve (10% for short turns, at most 15 seconds). The child timer, parent abort,
and detached job deadline still apply throughout execution. Configure subagents.timeoutMs / definitions[].timeoutMs (1,000–14,400,000
ms) and processJobs.maxRuntimeMs for the whole task too. The effective
detached child timer reserves 10% of remaining job runtime (at most 15 seconds)
for settlement; raise the job limit above 14,415,000 ms for a full four-hour
child turn. A settled native-certified timeout is inspectable as resumable:true
and continues on the same transcript through an ordinary AgentManage message,
foreground or background:true, without ack. Unknown/lost or still-owned turns
remain fenced. Child-owned background commands remain unsupported; interactive
parent turns and NodeRepl keep their existing 120-second caps.
Tolerate provider outages in native children
Section titled “Tolerate provider outages in native children”Native Agent children default to a two-minute recovery window per assistant
request on Anthropic, OpenAI Responses and Codex. Configure
subagents.providerRetryBudgetMs (0–180000 ms); zero restores legacy policy.
Inherited providers.piNative.piMaxRetries:0 disables both kinds of retry.
Leave enough whole-child/job time for recovery: the window is not a hard request
timeout, tools are not replayed, and unknown-outcome resends may duplicate billing.
Ordinary throttling keeps short header-aware retries; parent turns and Bedrock
are unchanged. On exhaustion inspect the bounded phase/attempt/elapsed/cause
suffix before deciding how to continue certified retained context. See
provider outage timing and diagnostics.