
Let other agents work through a conversation
An outside agent can ask your application for help through a persistent conversation. Wildo routes the request to an exposed actor system and carries the caller’s identity into its work.
The conversation can return an answer, continue with more input or expose a task that the integration follows over time.
Example — Continue work without starting again
A partner agent asks about a record, receives an answer and continues the same conversation with a follow-up question.
For engineers
The agent card advertises the application’s eligible actor systems as skills. A named agent can narrow that list. The caller selects a skill with metadata.skillId; when exactly one is exposed, the resolver can choose it without that field. Unknown skill references are rejected rather than spending a model turn on a fallback.
Send a message under the right identity
This adapted example follows the application’s delegated-write probe. Set agentUrl to the published A2A endpoint and token to a Bearer token issued for that audience. contextId is optional on the first turn:
async function sendMessage(
agentUrl: string,
token: string,
text: string,
contextId?: string,
skillId?: string,
) {
const message = {
role: 'user',
parts: [{ kind: 'text', text }],
...(contextId ? { contextId } : {}),
...(skillId ? { metadata: { skillId } } : {}),
};
const response = await fetch(agentUrl, {
method: 'POST',
headers: { 'content-type': 'application/json', Authorization: `Bearer ${token}` },
body: JSON.stringify({
jsonrpc: '2.0', id: 1, method: 'message/send',
params: { message },
}),
});
return { status: response.status, body: await response.json() };
}
Retain contextId to continue the conversation. A task’s id addresses work you can poll or reattach to; a conversation context alone is not a task handle.
Choose how the caller follows the work
| Request or outcome | What the client receives | Connection lifetime |
|---|---|---|
Blocking message/send, completed turn | A reply message and contextId | No task is created for that completed reply |
Direct message/stream, completed turn | Message frames, then the final reply | Disconnecting during generation aborts the streamed turn; it does not create a background task |
Nonblocking message/send | A task with id, contextId and status | Once the task is returned, the turn runs independently of the original connection |
| Either send or direct stream reaches an approval gate | A task in input-required; for a stream, this is the terminal frame | The person decides through the application’s approval channel; the task reports the pause |
These are the supported 0.2.5 method and state spellings. Other supported dialects project the corresponding names. A stream attached to an existing task is different from a direct message stream: closing that subscription does not cancel the underlying task.
Ask for an addressable task
This request follows the application’s a2a-resubscribe.e2e.ts probe. Send it to the same audience-bound agentUrl with the authenticated headers shown above. The message and identifiers are illustrative; select an actual skill from the card when several are exposed.
{
"jsonrpc": "2.0",
"id": 2,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{ "kind": "text", "text": "Summarize the records I can access." }]
},
"configuration": { "blocking": false }
}
}
A successfully opened task returns this shape. Values below are illustrative, not a recorded execution:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"kind": "task",
"id": "task-id-returned-by-the-server",
"contextId": "conversation-id-returned-by-the-server",
"status": { "state": "working", "timestamp": "2026-09-11T12:00:00.000Z" }
}
}
Check both JSON-RPC errors and the returned result kind. If nonblocking task creation fails, this transport falls back to a blocking reply; never treat a message’s ID as a task ID. If an approval pause cannot create its task, the transport returns an error instead.
With a returned task ID, send tasks/get with params: { id: taskId }, or follow task updates and reattachment. Reattachment supplies current and future state, not a replay of every missed text delta. An approval pause uses the same task shape with status.state: "input-required"; approval itself remains in the application.
Distinguish conversation ownership from permission
The verified token determines the execution principal and owner scope. The client’s text cannot grant a different tenant identity. Operations reached during the turn continue through the application’s service and authorization contracts.
A delegated user can reach behavior available to that user; a machine caller has its own principal. Approval-required actions may pause the work for a decision. Your actor system defines its instructions and tools; the protocol supplies the external conversation and task transport.
Choose skillId from the addressed agent card whenever it exposes several skills. It can be omitted when exactly one eligible actor system is exposed. Keep the same intended skill when continuing a conversation.