A2A · Docs

A2A quickstart

Discover Paseo agent-to-agent and dispatch work over A2A. The discovery card and the JSON-RPC task adapter are both live today.

What's live today

Both halves of the A2A surface are live:

  • The agent-native discovery cardGET /.well-known/agent.json (and its /agent-card.json aliases) — is live and unauthenticated. It lets an external agent find Paseo and machine-read its capabilities and endpoints without a credential.
  • The A2A task adapterPOST /v1/a2a JSON-RPC (tasks/send + tasks/sendSubscribe) — is live, gated by your federation key. It translates an inbound A2A task into a Paseo dispatch job and returns an A2A Task with a PoTE acceptance receipt as an artifact.
Auth note. The A2A adapter takes the pamk_ federation key (require_federation_key), not the paseo_dp_ agent key or the Developer JWT. Self-mint a federation key first. Submitting a task spends against that key's mandatory cap.

The agent card

get/.well-known/agent.jsonpublic
get/.well-known/agent-card.jsonpublic(alias)
get/agent-card.jsonpublic(alias)

An A2A-style card describing Paseo's capabilities and endpoints. Capability + endpoint discovery only — it deliberately makes no quality or accuracy claims. It is served with a strong ETag and honors If-None-Match (304). Fetch it with no auth:

curl

Response 200

json
FieldNotes
schema_version0.1.
name / descriptionPaseo and a one-line summary.
provider{ organization, url } — AugmentEV.
urlPublic base URL (overridable via PASEO_PUBLIC_BASE_URL; defaults to https://api.augmentev.ai).
authenticationschemes: ["apiKey"], the Authorization: Bearer <key> shape, and the signup URL.
interfaces{ mcp, rest } — absolute URLs for the MCP and REST surfaces.
pricingPer-call usage metering, plus a rate-card URL.
capabilities.poteThe PoTE advertisement: enabled (true only when the gateway holds a configured signing key), algorithm (ML-DSA-65), a description, and the public verify_endpoint.
agents[]Each agent's id, summary, and REST endpointskhanoor, resolve, docflow.

The task adapter

post/v1/a2aFederation key

A single JSON-RPC 2.0 endpoint. The method is chosen by the method field in the body, not the URL: tasks/send (synchronous) or tasks/sendSubscribe (SSE). The adapter validates the envelope, translates the A2A task into a Paseo dispatch job through the shared submit_job core (the same validation + billing path the job surface uses), and returns the resulting A2A Task.

This adapter implements a deliberately small, typed subset of A2A: tasks/send and tasks/sendSubscribe only. tasks/get, tasks/cancel, and push-notification config are not routed. Message parts are text and data only — an inbound file part is rejected with a typed INVALID_PARAMS error.

Params (both methods)

FieldTypeNotes
idstring?Client-chosen task id for correlation. Minted server-side when omitted.
sessionIdstring?Optional A2A session id, echoed onto the Task. Not used for routing in v1.
messageobject{ role, parts[] }. The compose target is read from a data part's container_image (or image alias), or from a single-token text part treated as a bare image ref. Optional typed knobs in the data part pass through: gpu_type, gpu_count, max_runtime_seconds, max_price_usd, input_refs, output_destination.
metadataobject?Opaque client metadata, echoed back on the Task. Never interpreted for auth or tenant — those come from the federation key, not the body.
Spend. Each accepted task debits a flat pre-flight estimate (50¢, the Standard per-job tier price) against your federation key's mandatory cap before the job is submitted. A hard-cap refusal returns a JSON-RPC SPEND_CAP_EXCEEDED error (code -32010, data.status_hint: 402) and no job is submitted; a submit that fails after the debit is refunded.

tasks/send

Submit a task and receive the A2A Task object synchronously. Because the gateway dispatches the job (the container runs off-process on a fleet agent), the returned Task is in a non-terminal state (submitted/working) carrying the assigned job id, with the PoTE acceptance receipt attached as an artifact. Per JSON-RPC, the HTTP status stays 200 even for errors — the failure rides in the error member.

curl

Response — a JSON-RPC result carrying the Task:

json

tasks/sendSubscribe (SSE)

The streaming variant: send Accept: text/event-stream and set method to tasks/sendSubscribe. The adapter dispatches synchronously, so the stream is a finite, pre-computed sequence — a submitted status update, the resolved status update carrying the dispatch message, a TaskArtifactUpdateEvent delivering the PoTE receipt, and a closing event with final: true.

curl

Event frames — each event: line names the A2A event type and the data: line carries the typed JSON:

text/event-stream

PoTE as a task artifact

A completed Task carries a PoTE receipt as an artifact named pote-receipt — a single data part holding a self-contained, ML-DSA-65-signed record you can lift out and verify unchanged at POST /v1/evidence/verify.

Honest framing — this is an acceptance receipt, not a completion record. The gateway dispatches the job; the container executes off-process and the fleet agent signs the completion PoTE later when the job finishes. The receipt attached at A2A request time is a signed acceptance/dispatch record: it commits, by hash, to the exact inbound task (input) and the dispatch result including the job id (output), signed with the same ML-DSA-65 key and independently verifiable. It proves "Paseo accepted and dispatched this task as job <id>", not "the job finished." When the gateway has no PoTE signer configured, no receipt artifact is attached (no fabricated proof).
Want to verify a receipt right now? The REST verify endpoint is live and needs no credential — paste a signed record and get a verdict.