Skip to main content
Every agent you publish gets an agent gateway — an A2A 1.0 endpoint another system can send messages to.
The host is derived from the agent’s handle.

Endpoints

Every A2A method is a POST to /. The method name lives in the JSON-RPC envelope, not the path. There are no REST-shaped routes — no GET /tasks/{id}, no DELETE /tasks/{id}.
There is no WebSocket endpoint. Neither this gateway nor the MCP gateway exposes one. All streaming is Server-Sent Events on a POST response.

Methods

The gateway dispatches exactly eleven method names and returns method not found (-32601) for anything else.
Method names are A2A 1.0 PascalCase. The 0.x slash names — message/send, message/stream, tasks/get, tasks/resubscribe, tasks/pushNotificationConfig/* — are not accepted and return -32601. There are no aliases.
SendStreamingMessage and SubscribeToTask return text/event-stream. Everything else returns a JSON-RPC response body.

Errors arrive with HTTP 200

Every JSON-RPC error is returned with HTTP 200 and the error in the envelope. The HTTP status is not the failure signal on this surface.

Authentication

The gateway takes one bearer credential in two kinds, disambiguated by prefix: an ak- API key belonging to a service principal, or a JWT scoped to this agent. A user’s API key is rejected with 403.
The agent card is public by protocol convention — it is the contract that tells a caller what credential to attach. A run authorizes as the caller, using the caller’s resolved role and grants. There is no elevation.

Authentication

Credential kinds, JWT admission rules, and the delegation chain.
The agent gateway has no rate limiting.

Contexts and threads

The A2A contextId is the Noorle thread id. Echo it on a follow-up turn to continue the same conversation; omit it and a fresh thread is created. A client-supplied taskId is honored if present, otherwise the server mints one. Task creation is atomic — reusing a task id fails rather than clobbering the existing task. Every stored key is scoped by account and agent, derived from the authenticated context. A tenant field on the wire is never trusted.

Extensions

The card declares two Noorle extensions, both optional: Negotiate by sending A2A-Extensions with a comma-separated list of URIs. The legacy header X-A2A-Extensions is also read; the response always echoes the canonical A2A-Extensions name. Unknown URIs are ignored. Messages and artifacts carrying an extension payload are tagged with the extension URI only if you negotiated it.

Approval gates

When an agent’s autonomy policy pauses a call, the task moves to a non-terminal TASK_STATE_INPUT_REQUIRED — the HTTP or SSE request is not held open. Resume by sending a follow-up SendMessage whose parts carry a noorle.gate_decision data part. Both taskId and contextId are required; both are server-minted and echoed back to you. Only user callers may resolve a gate over A2A. A rejected decision returns a noorle.gate_decision_rejected message on the blocking path, or a single non-final INPUT_REQUIRED update on the streaming path. The task stays parked either way.

Wire shapes worth knowing up front

  • Task states are TASK_STATE_* screaming-snake strings on the wire, not lowercase words. See Tasks.
  • Roles are ROLE_USER and ROLE_AGENT.
  • A message part has no file variant. The union is text, raw (base64), url, and data. File attachments lower to raw or url with filename and mediaType alongside.
  • Streamed content rides artifact updates, not messages.

Next steps