Agents over A2A
Serve Agents to A2A 1.0 clients, and hand work to them with push updates instead of a stream.
import { createA2aClient } from "@nylorun/agents/a2a";
const a2a = createA2aClient({
url: `${process.env.NYLORUN_RUNTIME_URL}/v1/a2a/agents/support`,
key: process.env.NYLORUN_SERVER_KEY!,
subject: "a2a:billing",
});
const task = await a2a.send({
messageId: crypto.randomUUID(),
contextId: "ticket-4821",
parts: [{ text: "Refund order demo-123 and tell me when it is done." }],
returnImmediately: true,
push: { url: "https://app.example.com/a2a/push" },
});
// task.status.state: "TASK_STATE_SUBMITTED"; updates arrive at the push URLThe Runtime serves every Agent over
A2A 1.0 on the JSON-RPC
binding. A context is one session per caller, Agent, and contextId; a task
is one turn of that session. Updates reach the caller as signed
push notifications, once the operator sets the Runtime's
push secret, and a change feed catches up
on any it missed.
A2A leaves some questions open, such as which state an approval uses. The Nylorun profile answers them for every Agent, and its five extensions carry what a client shows a person: approvals, plan steps, cost, a trace id, and file versions. Every extension is optional, so any A2A 1.0 client can call an Agent.
Where callers reach an Agent
| Caller | Endpoint | Credentials |
|---|---|---|
| Your own server | POST /v1/a2a/agents/{agentId} on the Runtime; the card at GET /v1/a2a/agents/{agentId}/card | An application key with the Nylorun-Subject header, as client.as() sends it. Scope sessions:own. |
| A partner's A2A client | createA2aHandler() on your server, at {basePath}/{agent}; the card at {basePath}/{agent}/.well-known/agent-card.json | Whatever your server checks. The handler forwards each request as the subject you name. See A2A. |
A caller sees only its own contexts and tasks: another subject's task answers as not found. Request and response shapes are on Call an agent over A2A.
Versions
Profile v2 needs @nylorun/runtime 0.37.0-beta or later, which lists the Host
feature a2a-profile-v2, and the change feed the Host feature turns. The
A2A client is in @nylorun/agents 0.31.0-beta or later.
const features = await client.hostFeatures(); // client from createClient()
const v2 = features.includes("a2a-profile-v2");Pages
| Page | What it covers |
|---|---|
| Profile v2 | The rules, the extensions, what a v2 Agent serves, and what a client gets |
| Push notifications | Push configs, delivery, Standard Webhooks signing, and retries |
| A2A client | createA2aClient(), reading the extensions, verifying pushes, and the change feed |
| Conformance | What the Runtime claims for A2A 1.0, its documented choices, and the TCK results |
interactions/v1, effects/v1, progress/v1, telemetry/v1, files/v1 | One page per extension. Its URI, https://docs.nylorun.com/a2a/<name>/v1, opens it |