Agent Governance Foundation

A2A Gateway integration

Register your A2A (Agent2Agent) agent once, and AGF fronts it — no SDK, no changes to either agent. Same pattern as the MCP Gateway, adapted to A2A's task-delegation model.

1. Register your A2A agent

target_url is your agent's A2A endpoint. audience is the aud value your delegation tokens should carry. upstream_auth is optional — the bearer token AGF sends to your agent, if it requires one. Requires a Growth plan or above.

curl -X POST https://api.agentgovernancefoundation.com/v1/a2a-gateways \
  -H "X-AGF-Key: agfk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "specialist-agent",
    "target_url": "https://agents.internal.acme.com/a2a",
    "audience": "a2a-prod",
    "upstream_auth": "your-a2a-agents-own-bearer-token"
  }'

Response includes the gateway ID you'll route traffic to. The secret is never echoed back.

{
  "id": "b2c3d4e5-...",
  "name": "specialist-agent",
  "target_url": "https://agents.internal.acme.com/a2a",
  "audience": "a2a-prod",
  "enabled": true,
  "log_message_content": false,
  "timeout_ms": 30000
}

2. Send a delegation through the gateway

Call /a2a/{gateway_id} instead of your agent directly. message/send and message/sendStreaming — the two methods that actually initiate work — need a delegation chain in the X-AGF-Chain header. Read-only/management methods (tasks/get, tasks/list, agentCard/get, tasks/cancel, push-notification config) pass straight through once your API key checks out — no chain needed.

A2A has no mandated field naming which skill a message invokes — set metadata.skill_id if you want your policies to distinguish between skills; otherwise every delegation is authorized against the generic resource "message".

curl -X POST https://api.agentgovernancefoundation.com/a2a/b2c3d4e5-... \
  -H "X-AGF-Key: agfk_your_key_here" \
  -H "X-AGF-Chain: [\"eyJhbGciOi...\"]" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "message/send",
    "params": {
      "message": {
        "messageId": "msg_abc123",
        "role": "ROLE_USER",
        "parts": [{ "text": "Summarize Q2 churn and email the finance team." }],
        "metadata": { "skill_id": "summarize-and-notify" }
      }
    }
  }'
On ALLOW: the call forwards to your agent byte-for-byte, and the response carries an X-AGF-Artifact-ID header so you can correlate it with the audit trail.

What a blocked delegation looks like

A non-ALLOW decision never reaches your agent. The caller gets a standard JSON-RPC error — any A2A client already knows how to handle this without new code:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32000,
    "message": "AGF decision: DENY",
    "data": { "decision": "DENY", "artifact_id": "dec_...", "approval_request_id": null }
  }
}

Which methods get a decision

MethodDecision-gated?Requires X-AGF-Chain
message/sendYesYes
message/sendStreamingYes (real streaming not yet implemented — proxied as a single response)Yes
tasks/get, tasks/list, agentCard/get, tasks/cancel, taskPushNotificationConfig/*No — passthroughNo

Related