Skip to main content
Wildo.ai Coming soon

Agent protocols

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.

An external agent sends work to an application agent and receives task progress.

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 outcomeWhat the client receivesConnection lifetime
Blocking message/send, completed turnA reply message and contextIdNo task is created for that completed reply
Direct message/stream, completed turnMessage frames, then the final replyDisconnecting during generation aborts the streamed turn; it does not create a background task
Nonblocking message/sendA task with id, contextId and statusOnce the task is returned, the turn runs independently of the original connection
Either send or direct stream reaches an approval gateA task in input-required; for a stream, this is the terminal frameThe 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.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.