Remote Agent Delegation
If the plugin is not installed or configured yet, use the a2a-delegation-setup skill first.
Use the remote_agent tool to delegate work to external A2A-compatible agents and manage delegated tasks. send is the only action to start a new remote turn or continue an existing one.
When to delegate
Delegate when:
- The task requires capabilities you do not have (e.g. code execution, web search, domain-specific APIs)
- The user explicitly asks to send work to an external agent
- A configured target agent is better suited for the request
Do not delegate when you can handle the request directly.
Tool
The remote_agent tool exposes five actions: list_targets, send, watch, status, cancel.
Choosing a target
Call list_targets first to discover available agents. Prefer target_alias over target_url — aliases are stable names configured by the user. If a default target is configured, you can omit target_alias from send.
Actions
list_targets
Discover configured targets.
{ "action": "list_targets" }
send
Send a request to a remote agent. Use it for:
- a brand-new remote task
- a follow-up turn on an existing remote task
- a related new task that references prior work
- a new task inside an existing remote conversation
{
"action": "send",
"target_alias": "my-agent",
"parts": [
{
"kind": "text",
"text": "Summarize the latest quarterly report."
}
],
"follow_updates": true
}
parts(required): non-empty array oftext,file, ordataparts.target_alias: configured target name. Omit when a default target exists.continuation: canonical persisted follow-up contract fromsummary.continuation. Round-trip this subtree verbatim forsend,watch,status, andcancel.task_handle: manual compatibility input for follow-up actions when you are not replaying a persistedcontinuation.task_id: manual compatibility continuation id forsend; for follow-up actions it identifies the remote task only when notask_handleis available inside a persistedcontinuation.task_idcontinues an existing task.context_id: manual compatibility conversation continuation id forsend. Use it withtask_id, or by itself to start a new task in the same conversation, only when you are not replaying a persistedcontinuation.reference_task_ids: optional related task ids forsend.reference_task_idsreferences prior tasks without continuing them.task_requirement: optional durability contract.task_requirement="required"forces explicit task creation or fails fast.follow_updates: whentrue, streams updates and returns the full event log.follow_updates=truemeans “stream the initial send”; it does not guarantee task creation unlesstask_requirement="required".blocking: only for non-streamsend; do not combine it withfollow_updates=true.
Preferred continuation forms:
{ "action": "send", "continuation": { "target": { "target_url": "https://my-agent.example/", "card_path": "/.well-known/agent-card.json", "preferred_transports": ["JSONRPC", "HTTP+JSON"], "target_alias": "my-agent" }, "task": { "task_handle": "rah_abc123", "task_id": "task-123" } }, "parts": [{ "kind": "text", "text": "Approved. Continue." }] }
{ "action": "send", "continuation": { "target": { "target_url": "https://my-agent.example/", "card_path": "/.well-known/agent-card.json", "preferred_transports": ["JSONRPC", "HTTP+JSON"], "target_alias": "my-agent" }, "task": { "task_id": "task-123" } }, "parts": [{ "kind": "text", "text": "Continue the task." }] }
{ "action": "send", "continuation": { "target": { "target_url": "https://my-agent.example/", "card_path": "/.well-known/agent-card.json", "preferred_transports": ["JSONRPC", "HTTP+JSON"], "target_alias": "my-agent" }, "conversation": { "context_id": "ctx-123", "can_send": true } }, "parts": [{ "kind": "text", "text": "Start a new task in the same conversation." }] }
Manual compatibility only:
{ "action": "send", "target_alias": "my-agent", "context_id": "ctx-123", "reference_task_ids": ["task-1", "task-2"], "parts": [{ "kind": "text", "text": "Start related work without continuing those tasks." }] }
Continuation safety
Interpret follow-up capability from result.summary.continuation, not from prompt text, message text, or other inferred context.
response_kindis descriptive only. Keep follow-up logic anchored tosummary.continuation.summary.continuation.target: canonical persisted routing contract. Persistsummary.continuationverbatim and pass it back directly for machine follow-up.summary.continuation.task: trackable task continuity. Use it for follow-upsend,watch,status, andcancel.summary.continuation.conversation: conversation continuity only. Use it only withsendto start a new task in the same conversation.summary.target_*is descriptive only and no longer part of the machine follow-up recipe.- Top-level compatibility aliases stay descriptive only. Do not infer task continuity from flat
task_id, flatcontext_id, or other top-level summary fields. - Branch on
summary.continuation.taskvssummary.continuation.conversationbefore choosing the next action. - Never infer or synthesize
summary.continuation.taskfromsummary.continuation.conversation, session ids, run ids, prior prompts, or summary text. - Do not call
watch,status, orcancelfrom a result that has onlysummary.continuation.conversation. - Do not poll from conversation continuity.
- If lifecycle tracking is required, fail fast when the peer returns only
summary.continuation.conversation. - Do not route
summary.continuationback through channela2a; inbound A2A channel delivery is separate fromremote_agentcontinuation. - Inbound A2A defaults to
originRoutingPolicy: "suppress-generic-followup"to reduce accidental host replay through channela2a; treatlegacy-origin-routingas an escape hatch, not as a supported queued follow-up path. - If you see
A2A_OUTBOUND_DELIVERY_UNSUPPORTED, the host selected the wrong boundary. Return to persistedsummary.continuationplusremote_agent.
const task = result.summary.continuation?.task
const conversation = result.summary.continuation?.conversation
if (task) {
// Trackable task lifecycle.
} else if (conversation) {
// Send-only conversation continuity.
}
Invalid follow-up example:
{ "action": "status", "context_id": "ctx-123" }
That is invalid because status, watch, and cancel require task continuity, not just conversation continuity.
status
Poll the current state of a delegated task.
{ "action": "status", "continuation": { "target": { "target_url": "https://my-agent.example/", "card_path": "/.well-known/agent-card.json", "preferred_transports": ["JSONRPC", "HTTP+JSON"], "target_alias": "my-agent" }, "task": { "task_handle": "rah_abc123", "task_id": "task-123" } } }
watch
Subscribe to live updates from a running task.
{ "action": "watch", "continuation": { "target": { "target_url": "https://my-agent.example/", "card_path": "/.well-known/agent-card.json", "preferred_transports": ["JSONRPC", "HTTP+JSON"], "target_alias": "my-agent" }, "task": { "task_handle": "rah_abc123", "task_id": "task-123" } } }
cancel
Cancel a running task.
{ "action": "cancel", "continuation": { "target": { "target_url": "https://my-agent.example/", "card_path": "/.well-known/agent-card.json", "preferred_transports": ["JSONRPC", "HTTP+JSON"], "target_alias": "my-agent" }, "task": { "task_handle": "rah_abc123", "task_id": "task-123" } } }
Task handles
After a successful send, the result usually includes summary.continuation.task.task_handle (prefixed rah_) when the remote peer exposes task continuity. task_handle is returned only when the peer actually created a task. Persist summary.continuation verbatim and pass it back directly for follow-up send/watch/status/cancel actions. Handles are process-local and expire after restart or TTL, but nested continuation still round-trips safely because it also carries durable summary.continuation.target plus summary.continuation.task.task_id. Treat flat send.task_id, send.context_id, and target_alias as manual compatibility inputs, not as a replacement for nested continuation round-tripping. If the result includes only summary.continuation.conversation, there is no task lifecycle to poll, watch, or cancel.
watch vs status
Use watch when the remote agent supports streaming and you want live incremental updates. Use status to poll a snapshot of the current task state. If you are unsure whether the target supports streaming, start with status.
Errors
UNKNOWN_TASK_HANDLE— the handle is expired or invalid. Retry with the same nestedcontinuation, or re-send. Manual callers may fall back to flattask_idplus target routing only when they do not have a persistedcontinuation.TARGET_RESOLUTION_ERROR— the alias or URL did not resolve. Calllist_targetsto check available targets.VALIDATION_ERROR— invalid parameters. Check required fields for the action.