Skip to main content
All three communication modes — sync, async, and stream — use the same envelope. The format never changes based on delivery mechanism; only the endpoint and response behavior differ.

Request envelope (body)

The JSON body carries routing and payload fields. The signature is in HTTP headers — not the body.
{
  "from": "agent://sender.com",
  "to": "agent://receiver.com",
  "skill": "review-code",
  "mode": "sync",
  "nonce": "a1b2c3d4e5f6",
  "timestamp": "2026-04-11T10:00:00Z",
  "traceId": "root-correlation-uuid",
  "spanId": "this-hop-uuid",
  "parentSpanId": "caller-span-uuid",
  "delegationToken": null,
  "auth": { "scheme": "bearer", "token": "…" },
  "payload": {
    "code": "function foo() { return 1 }",
    "language": "typescript"
  }
}
FieldRequiredDescription
fromYesSender’s agent:// identity
toYesReceiver’s agent:// identity
skillYesSkill ID to invoke
modeYessync, async, or stream
nonceYesUnique random value; receivers reject duplicates within 5 minutes
timestampYesISO 8601 UTC; receivers reject messages older than 5 minutes
traceIdYesRoot correlation ID for distributed tracing
spanIdYesThis hop’s unique ID
parentSpanIdNoParent span ID; null for root hops
delegationTokenNoEdDSA JWT; null when not delegating
authNoRequired for authenticated skills
callbackUrlNoAsync mode only — URL for webhook delivery
payloadNoSkill input; must conform to inputSchema

Signature (RFC 9421 HTTP Message Signatures)

Authentication uses RFC 9421 — three standard HTTP headers on every POST request:
Content-Digest: sha-256=:base64-sha256-of-body:
Signature-Input: sig1=("@method" "@path" "content-digest");keyid="key-2";alg="ed25519";created=1744371600
Signature: sig1=:base64-ed25519-signature:
What’s signed: @method, @path, and content-digest — so the receiver can verify both which endpoint was targeted and that the body hasn’t been tampered with. Signing procedure:
  1. Serialize the body to UTF-8 bytes
  2. Compute sha-256 of the bytes → Content-Digest
  3. Build the RFC 9421 signature base (method + path + content-digest + params), sign with Ed25519
  4. Send all three headers with the request
The keyid in Signature-Input references the kid in the sender’s agent card — enabling key rotation without changing the protocol.
The SDK handles all of this automatically. You never construct or verify these headers manually.

Response envelope

{
  "traceId": "root-correlation-uuid",
  "spanId": "responder-uuid",
  "status": "ok",
  "result": {
    "issues": [],
    "summary": "No issues found"
  }
}
On error:
{
  "traceId": "root-correlation-uuid",
  "spanId": "responder-uuid",
  "status": "error",
  "error": {
    "code": "SCHEMA_INVALID",
    "message": "Field 'code' exceeds maxLength of 50000 characters"
  }
}

JSON Schema