{
  "schemaVersion": "1.0",
  "title": "Use AIP through A2A",
  "description": "Use this guide to connect an A2A 1.0 client to getaip-server, discover the local Agent Card, invoke one native AIP capability, and read the projected task. The A2A profile translates JSON-RPC messages into native actions. AIP remains the ow",
  "canonical": "https://getaip.org/docs/guides/use-aip-through-a2a",
  "route": "/docs/guides/use-aip-through-a2a",
  "source": "docs/guides/use-aip-through-a2a.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "Build with AIP",
  "documentType": "Guide",
  "language": "en",
  "revision": {
    "lastReviewedRevision": "d7cce13d1d555644d04a4d73c66c95b113737635",
    "documentationSourceRevision": "9192fef3695ad294994f2712f6d156241e5e92fb",
    "basis": "frontmatter"
  },
  "downloads": {
    "md": "/docs/download/guides/use-aip-through-a2a.md",
    "txt": "/docs/download/guides/use-aip-through-a2a.txt",
    "json": "/docs/download/guides/use-aip-through-a2a.json",
    "pdf": "/docs/download/guides/use-aip-through-a2a.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Use AIP through A2A\ndescription: Connect an A2A 1.0 client to getaip-server and invoke a local AIP capability through the authenticated compatibility edge\nkind: how-to\naudience: developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"d7cce13d1d555644d04a4d73c66c95b113737635\"\n---\n\n# Use AIP through A2A\n\nUse this guide to connect an A2A 1.0 client to `getaip-server`, discover the local\nAgent Card, invoke one native AIP capability, and read the projected task. The\nA2A profile translates JSON-RPC messages into native actions. AIP remains the\nowner of validation, authorization, policy, execution, and durable lifecycle\nstate.\n\nThe walkthrough uses one bearer identity on a loopback listener and invokes\nthe built-in health capability. Later sections explain streaming, push\nnotifications, and the current tenant boundary. The walkthrough does not\nqualify a production deployment or an independent A2A client.\n\nThe examples target source revision\n`d7cce13d1d555644d04a4d73c66c95b113737635`. This authoring pass checked the\nsource and snippet syntax without building the workspace or starting a\nservice.\n\n## Choose the A2A boundary deliberately\n\nUse A2A when an existing agent already implements the A2A task model and needs\nto call a capability in the local `getaip-server` manifest. Use native AIP when the\nclient needs the complete envelope, verified tenant context, operational read\nmodel, or a protocol feature that the A2A projection does not expose.\n\n| Client need | Preferred path |\n|---|---|\n| Discover local skills through an Agent Card | A2A |\n| Send a user message and follow a projected task | A2A |\n| Invoke a tenant-routed remote connector fleet | Native AIP or the documented MCP facade |\n| Preserve complete AIP identity, approval, transaction, and receipt semantics | Native AIP |\n| Launch a command-based compatibility client | MCP over stdio |\n\nAn Agent Card is discovery data, not authorization. A visible skill can still\nrequire scopes, approval, idempotency, or other AIP policy.\n\n## Know the current routes and names\n\nThe preferred public routes are:\n\n| Purpose | Route |\n|---|---|\n| Agent Card | `GET /.well-known/agent-card.json` |\n| A2A 1.0 JSON-RPC | `POST /a2a/v1` |\n\nThe Agent Card aliases `/.well-known/agent.json` and `/a2a/agent-card` return\nthe same local projection. The JSON-RPC aliases `/a2a` and `/aip/v1/a2a`\nreach the same handler.\n\nCurrent operation names are `SendMessage`, `SendStreamingMessage`, `GetTask`,\n`ListTasks`, `CancelTask`, `SubscribeToTask`, the four task push-notification\nconfiguration operations, and `GetExtendedAgentCard`. Explicit v0.3 method\naliases remain accepted for migration. New clients should send current names\nand should not infer a separate legacy task store.\n\nThe `A2A-Version` request header is optional. When present, its value must be\n`1.0` at the reviewed revision.\n\n## Prerequisites\n\nFor the loopback walkthrough, you need:\n\n- the reviewed source checkout and its locked Rust dependencies;\n- `curl` and `jq`;\n- local TCP port `18080`, or another unused loopback port used consistently;\n- permission to create local guide state and an owner-only token file;\n- two terminals, one for `getaip-server` and one for client commands.\n\nThe example token is intentionally local and disposable. Do not reuse it on a\nshared or public endpoint.\n\n## 1. Create the local bearer credential\n\nCreate one owner-readable token file from the repository root:\n\n```sh\numask 077\nprintf '%s\\n' 'a2a-guide-token' > .getaip-server-a2a-token\n```\n\n`getaip-server` trims a conventional trailing line ending when it reads the secret\nfile. Keep the file out of version control.\n\n## 2. Start the authenticated A2A edge\n\nStart the daemon in the first terminal:\n\n```sh\ncargo run --locked -p getaip-server -- \\\n  --bind 127.0.0.1:18080 \\\n  --service-id agent:getaip:server:a2a-guide \\\n  --storage-dir .getaip-server-a2a-guide \\\n  --native-bearer-token-file .getaip-server-a2a-token \\\n  --native-principal service:a2a:guide \\\n  --native-principal-scope action:read \\\n  --native-principal-scope action:write\n```\n\nKeep the process running. In the second terminal, verify readiness:\n\n```sh\ncurl -fsS http://127.0.0.1:18080/ready \\\n  | jq -e '.status == \"ready\"'\n```\n\nA successful check prints `true`. This result covers the local process and its\nrequired workers. It does not prove external connectivity, connector\nqualification, or production readiness.\n\n## 3. Inspect the local Agent Card\n\nAgent Card discovery is public. Fetch it without the bearer token:\n\n```sh\ncurl -fsS http://127.0.0.1:18080/.well-known/agent-card.json \\\n  | tee .getaip-server-a2a-card.json \\\n  | jq -e '\n      .supportedInterfaces[0].url == \"http://127.0.0.1:18080/a2a/v1\"\n      and .supportedInterfaces[0].protocolVersion == \"1.0\"\n      and .capabilities.streaming == true\n      and .capabilities.pushNotifications == false\n      and .securitySchemes.aipBearer.httpAuthSecurityScheme.scheme == \"Bearer\"\n    '\n```\n\nA successful check prints `true`. Push notification support is `false` in this\nwalkthrough because no callback signer or credential-encryption key is\nconfigured.\n\nThe card projects capabilities from the local AIP manifest into A2A skills.\nIt declares content modes, the preferred JSON-RPC interface, and its bearer\nscheme. It does not expose secrets or grant task access.\n\n## 4. Send one health message\n\nCreate `.getaip-server-a2a-send.json`:\n\n```json\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": \"guide-send-1\",\n  \"method\": \"SendMessage\",\n  \"params\": {\n    \"message\": {\n      \"messageId\": \"message-a2a-health-1\",\n      \"taskId\": \"task-a2a-health-1\",\n      \"contextId\": \"context-a2a-guide\",\n      \"role\": \"ROLE_USER\",\n      \"parts\": [\n        {\n          \"data\": {},\n          \"mediaType\": \"application/json\"\n        }\n      ]\n    },\n    \"metadata\": {\n      \"aip\": {\n        \"capability_id\": \"cap:aip:server:health\",\n        \"input\": {}\n      }\n    }\n  }\n}\n```\n\nThe current send mapping requires a non-empty `messageId`, the `ROLE_USER`\nrole, at least one part, and `metadata.aip.capability_id`. The profile maps\n`messageId` to the native idempotency key\n`a2a-message:message-a2a-health-1`. A skill label alone is not stable routing\nauthority.\n\nSend the request and retain the response:\n\n```sh\nA2A_TOKEN=\"$(sed -n '1p' .getaip-server-a2a-token)\"\ncurl -fsS \\\n  -H \"Authorization: Bearer ${A2A_TOKEN}\" \\\n  -H 'A2A-Version: 1.0' \\\n  -H 'Content-Type: application/json' \\\n  --data-binary @.getaip-server-a2a-send.json \\\n  http://127.0.0.1:18080/a2a/v1 \\\n  | tee .getaip-server-a2a-send-response.json \\\n  | jq -e '\n      .error == null\n      and .result.task.id == \"task-a2a-health-1\"\n      and .result.task.status.state == \"TASK_STATE_COMPLETED\"\n      and any(\n        .result.task.artifacts[]?.parts[]?;\n        .text == \"getaip-server is healthy\"\n      )\n    '\n```\n\nA successful check prints `true`. The response is an A2A task projection. Its\nmetadata retains the native action identity needed for later lifecycle reads.\n\nWhen `metadata.aip.input` is absent, the profile derives input from the A2A\nmessage and its first text part. Supply explicit input when the native\ncapability expects a structured contract.\n\n## 5. Read the task again\n\nExtract the returned task ID and issue `GetTask`:\n\n```sh\nA2A_TOKEN=\"$(sed -n '1p' .getaip-server-a2a-token)\"\nTASK_ID=\"$(jq -er '.result.task.id' .getaip-server-a2a-send-response.json)\"\ncurl -fsS \\\n  -H \"Authorization: Bearer ${A2A_TOKEN}\" \\\n  -H 'A2A-Version: 1.0' \\\n  -H 'Content-Type: application/json' \\\n  --data-binary \"$(\n    jq -nc --arg id \"${TASK_ID}\" '{\n      jsonrpc: \"2.0\",\n      id: \"guide-get-1\",\n      method: \"GetTask\",\n      params: {id: $id, historyLength: 5}\n    }'\n  )\" \\\n  http://127.0.0.1:18080/a2a/v1 \\\n  | jq -e --arg id \"${TASK_ID}\" '\n      .error == null\n      and .result.id == $id\n      and .result.status.state == \"TASK_STATE_COMPLETED\"\n    '\n```\n\nA successful check prints `true`. `historyLength` keeps the newest requested\nhistory entries while preserving their native sequence order.\n\n## Choose synchronous, asynchronous, or streaming work\n\nThe send configuration changes response behavior, not the underlying AIP\nlifecycle:\n\n| A2A operation or option | Current behavior |\n|---|---|\n| `SendMessage` | Dispatches through the gateway and returns a completed, submitted, or input-required task according to the native outcome |\n| `SendMessage` with `configuration.returnImmediately: true` | Requests native asynchronous mode and returns the durable task handle |\n| `SendStreamingMessage` | Forces asynchronous mode and emits task status and artifact updates as SSE until a terminal state |\n| `SubscribeToTask` | Opens a new SSE view for an existing nonterminal task |\n| `GetTask` | Reads one native status projection and optionally limits history |\n| `ListTasks` | Lists visible A2A-bound actions with filters and page sizes from 1 through 100 |\n| `CancelTask` | Persists native cancellation intent unless the task is already terminal |\n\nThe streaming handler polls durable native action status and retained chunks.\nIts SSE events do not contain event IDs, and it does not implement\n`Last-Event-ID`. Reconnect a nonterminal task with `SubscribeToTask` and the\ntask ID. Read a terminal task with `GetTask`; terminal-task subscription is\nrejected.\n\nA transport disconnect does not prove that a mutation failed. Read the task or\nnative action before retrying the same logical work, and reuse the original\n`messageId` when idempotency should return the original result.\n\n## Understand identity and tenant limits\n\nEvery A2A JSON-RPC operation requires the configured native bearer token. The\ndaemon compares the token in constant time, binds the configured principal and\nscopes, and constructs trusted gateway context. JSON-RPC metadata cannot choose\nthe authenticated actor. Public Agent Card discovery remains unauthenticated.\n\nThe current command-line A2A edge maps one static token to one principal. It\ndoes not perform OAuth introspection or map different external users to\ndifferent AIP principals. A trusted edge can protect and rate-limit the route,\nbut requests forwarded with the daemon token still share that one daemon-side\nidentity.\n\nAt this revision, A2A JSON-RPC dispatch calls the verified gateway without a\n`VerifiedTenant`. Treat a request `tenant` field as profile data or a list\nfilter, not as tenant authority. When connector fleet services are enabled,\nthe Agent Card advertises an optional tenant-capability-discovery extension\nthat points to a separate authenticated native endpoint. It does not\nmaterialize the remote fleet catalog as Agent Card skills.\n\nUse native AIP or the stable MCP fleet facade when verified tenant routing is a\nrequirement. Do not describe A2A task success as connector-fleet qualification.\n\n## Enable push notifications safely\n\n`getaip-server` advertises A2A push notifications only when both controls are present:\n\n- an Ed25519 callback signer from `--callback-signing-seed-file`, its inline\n  alternative, or the corresponding environment variable;\n- a 32-byte encryption key from `GETAIP_SERVER_A2A_PUSH_ENCRYPTION_KEY_HEX` or the\n  inline `--a2a-push-encryption-key-hex` option.\n\nPrefer a file for the signing seed and secret-manager injection for the\nencryption-key environment variable. Inline hexadecimal values can persist in\nshell history or process inspection.\n\nFor a non-loopback deployment, the A2A-specific controls fit into a command\nsuch as this after the encryption-key environment variable is injected:\n\n```sh\ncargo run --locked -p getaip-server -- \\\n  --bind 0.0.0.0:18080 \\\n  --public-base-url https://aip.example.com \\\n  --service-id agent:getaip:server:a2a-production \\\n  --postgres-url-file /run/secrets/getaip-server-postgres-url \\\n  --native-bearer-token-file /run/secrets/getaip-server-native-token \\\n  --native-principal service:a2a:trusted-edge \\\n  --native-principal-scope action:read \\\n  --native-principal-scope action:write \\\n  --callback-signing-seed-file /run/secrets/aip-callback-signing-seed \\\n  --callback-allowed-host callbacks.example.com\n```\n\nTerminate TLS at a trusted edge and route the public HTTPS origin to the\nprivate listener. The external base URL must be an HTTPS origin without a\npath, query, fragment, or embedded credentials.\n\nBefore accepting a push configuration, verify that:\n\n- the callback URL uses HTTPS and its exact host is allowlisted;\n- private and loopback destinations remain blocked unless an owned isolated\n  network requires an explicit exception;\n- stored callback token and authorization credentials use the configured\n  encryption key;\n- the receiver verifies the signed callback and treats deliveries as\n  idempotent;\n- durable profile state, callback delivery state, recovery, backup, and key\n  rotation are part of the deployment design.\n\nThe delivery worker uses a durable cursor and fencing to coordinate recovery.\nThat control suppresses competing recovery work but does not justify an\nexactly-once provider claim.\n\n## Resolve common failures\n\n| Symptom | Likely boundary | Safe next check |\n|---|---|---|\n| `401 Unauthorized` | A2A bearer identity | Confirm `--native-bearer-token-file`, the exact `Authorization` header, and token-file permissions |\n| `VERSION_NOT_SUPPORTED` | A2A header | Send `A2A-Version: 1.0` or omit the optional header |\n| `INVALID_PARAMS` for send | Message mapping | Check `messageId`, `ROLE_USER`, at least one part, and `metadata.aip.capability_id` |\n| Agent Card omits a fleet capability | Discovery boundary | Use the advertised tenant discovery extension, native AIP, or the stable MCP facade |\n| `TASK_NOT_FOUND` | Identity, task binding, or retention | Reuse the authenticated principal and exact returned task ID; then inspect native action state |\n| Streaming ended before the result was read | Connection boundary | Call `GetTask`; use `SubscribeToTask` only while the task is nonterminal |\n| Push support is `false` | Callback controls | Configure both the signer and A2A credential-encryption key, then restart the daemon |\n| Push configuration is rejected | Destination or ownership policy | Check task access, HTTPS, the exact host allowlist, private-network policy, and configuration ID conflicts |\n\nJSON-RPC application errors normally arrive in a successful HTTP response.\nInspect the JSON `error` field even when `curl` reports HTTP success.\n\n## Stop and clean up the walkthrough\n\nStop `getaip-server` with `Control-C`. Inspect and remove only the local guide files:\n\n```sh\ndu -sh .getaip-server-a2a-guide 2>/dev/null || true\nrm -rf -- .getaip-server-a2a-guide\nrm -f -- \\\n  .getaip-server-a2a-token \\\n  .getaip-server-a2a-card.json \\\n  .getaip-server-a2a-send.json \\\n  .getaip-server-a2a-send-response.json\n```\n\nDo not apply this cleanup to a production state path. Durable task, push,\ncallback, and recovery records can reside there.\n\n## Related documentation\n\n- [Use native AIP](use-native-aip.md)\n- [Profiles and connectors](../concepts/profiles-and-connectors.md)\n- [Actions and sessions](../concepts/actions-and-sessions.md)\n- [Identity and trust](../concepts/identity-and-trust.md)\n- [Approvals and policy](../concepts/approvals-and-policy.md)\n",
    "text": "Use AIP through A2A\n\nUse this guide to connect an A2A 1.0 client to getaip-server, discover the local\nAgent Card, invoke one native AIP capability, and read the projected task. The\nA2A profile translates JSON-RPC messages into native actions. AIP remains the\nowner of validation, authorization, policy, execution, and durable lifecycle\nstate.\n\nThe walkthrough uses one bearer identity on a loopback listener and invokes\nthe built-in health capability. Later sections explain streaming, push\nnotifications, and the current tenant boundary. The walkthrough does not\nqualify a production deployment or an independent A2A client.\n\nThe examples target source revision\nd7cce13d1d555644d04a4d73c66c95b113737635. This authoring pass checked the\nsource and snippet syntax without building the workspace or starting a\nservice.\n\nChoose the A2A boundary deliberately\n\nUse A2A when an existing agent already implements the A2A task model and needs\nto call a capability in the local getaip-server manifest. Use native AIP when the\nclient needs the complete envelope, verified tenant context, operational read\nmodel, or a protocol feature that the A2A projection does not expose.\n\n| Client need | Preferred path |\n\n| Discover local skills through an Agent Card | A2A |\n| Send a user message and follow a projected task | A2A |\n| Invoke a tenant-routed remote connector fleet | Native AIP or the documented MCP facade |\n| Preserve complete AIP identity, approval, transaction, and receipt semantics | Native AIP |\n| Launch a command-based compatibility client | MCP over stdio |\n\nAn Agent Card is discovery data, not authorization. A visible skill can still\nrequire scopes, approval, idempotency, or other AIP policy.\n\nKnow the current routes and names\n\nThe preferred public routes are:\n\n| Purpose | Route |\n\n| Agent Card | GET /.well-known/agent-card.json |\n| A2A 1.0 JSON-RPC | POST /a2a/v1 |\n\nThe Agent Card aliases /.well-known/agent.json and /a2a/agent-card return\nthe same local projection. The JSON-RPC aliases /a2a and /aip/v1/a2a\nreach the same handler.\n\nCurrent operation names are SendMessage, SendStreamingMessage, GetTask,\nListTasks, CancelTask, SubscribeToTask, the four task push-notification\nconfiguration operations, and GetExtendedAgentCard. Explicit v0.3 method\naliases remain accepted for migration. New clients should send current names\nand should not infer a separate legacy task store.\n\nThe A2A-Version request header is optional. When present, its value must be\n1.0 at the reviewed revision.\n\nPrerequisites\n\nFor the loopback walkthrough, you need:\n• the reviewed source checkout and its locked Rust dependencies;\n• curl and jq;\n• local TCP port 18080, or another unused loopback port used consistently;\n• permission to create local guide state and an owner-only token file;\n• two terminals, one for getaip-server and one for client commands.\n\nThe example token is intentionally local and disposable. Do not reuse it on a\nshared or public endpoint.\n1. Create the local bearer credential\n\nCreate one owner-readable token file from the repository root:\n\numask 077\nprintf '%s\\n' 'a2a-guide-token' > .getaip-server-a2a-token\n\ngetaip-server trims a conventional trailing line ending when it reads the secret\nfile. Keep the file out of version control.\n2. Start the authenticated A2A edge\n\nStart the daemon in the first terminal:\n\ncargo run --locked -p getaip-server -- \\\n  --bind 127.0.0.1:18080 \\\n  --service-id agent:getaip:server:a2a-guide \\\n  --storage-dir .getaip-server-a2a-guide \\\n  --native-bearer-token-file .getaip-server-a2a-token \\\n  --native-principal service:a2a:guide \\\n  --native-principal-scope action:read \\\n  --native-principal-scope action:write\n\nKeep the process running. In the second terminal, verify readiness:\n\ncurl -fsS http://127.0.0.1:18080/ready \\\n  | jq -e '.status == \"ready\"'\n\nA successful check prints true. This result covers the local process and its\nrequired workers. It does not prove external connectivity, connector\nqualification, or production readiness.\n3. Inspect the local Agent Card\n\nAgent Card discovery is public. Fetch it without the bearer token:\n\ncurl -fsS http://127.0.0.1:18080/.well-known/agent-card.json \\\n  | tee .getaip-server-a2a-card.json \\\n  | jq -e '\n      .supportedInterfaces[0].url == \"http://127.0.0.1:18080/a2a/v1\"\n      and .supportedInterfaces[0].protocolVersion == \"1.0\"\n      and .capabilities.streaming == true\n      and .capabilities.pushNotifications == false\n      and .securitySchemes.aipBearer.httpAuthSecurityScheme.scheme == \"Bearer\"\n    '\n\nA successful check prints true. Push notification support is false in this\nwalkthrough because no callback signer or credential-encryption key is\nconfigured.\n\nThe card projects capabilities from the local AIP manifest into A2A skills.\nIt declares content modes, the preferred JSON-RPC interface, and its bearer\nscheme. It does not expose secrets or grant task access.\n4. Send one health message\n\nCreate .getaip-server-a2a-send.json:\n\n{\n  \"jsonrpc\": \"2.0\",\n  \"id\": \"guide-send-1\",\n  \"method\": \"SendMessage\",\n  \"params\": {\n    \"message\": {\n      \"messageId\": \"message-a2a-health-1\",\n      \"taskId\": \"task-a2a-health-1\",\n      \"contextId\": \"context-a2a-guide\",\n      \"role\": \"ROLEUSER\",\n      \"parts\": [\n        {\n          \"data\": {},\n          \"mediaType\": \"application/json\"\n        }\n      ]\n    },\n    \"metadata\": {\n      \"aip\": {\n        \"capabilityid\": \"cap:aip:server:health\",\n        \"input\": {}\n      }\n    }\n  }\n}\n\nThe current send mapping requires a non-empty messageId, the ROLEUSER\nrole, at least one part, and metadata.aip.capabilityid. The profile maps\nmessageId to the native idempotency key\na2a-message:message-a2a-health-1. A skill label alone is not stable routing\nauthority.\n\nSend the request and retain the response:\n\nA2ATOKEN=\"$(sed -n '1p' .getaip-server-a2a-token)\"\ncurl -fsS \\\n  -H \"Authorization: Bearer ${A2ATOKEN}\" \\\n  -H 'A2A-Version: 1.0' \\\n  -H 'Content-Type: application/json' \\\n  --data-binary @.getaip-server-a2a-send.json \\\n  http://127.0.0.1:18080/a2a/v1 \\\n  | tee .getaip-server-a2a-send-response.json \\\n  | jq -e '\n      .error == null\n      and .result.task.id == \"task-a2a-health-1\"\n      and .result.task.status.state == \"TASKSTATECOMPLETED\"\n      and any(\n        .result.task.artifacts[]?.parts[]?;\n        .text == \"getaip-server is healthy\"\n      )\n    '\n\nA successful check prints true. The response is an A2A task projection. Its\nmetadata retains the native action identity needed for later lifecycle reads.\n\nWhen metadata.aip.input is absent, the profile derives input from the A2A\nmessage and its first text part. Supply explicit input when the native\ncapability expects a structured contract.\n5. Read the task again\n\nExtract the returned task ID and issue GetTask:\n\nA2ATOKEN=\"$(sed -n '1p' .getaip-server-a2a-token)\"\nTASKID=\"$(jq -er '.result.task.id' .getaip-server-a2a-send-response.json)\"\ncurl -fsS \\\n  -H \"Authorization: Bearer ${A2ATOKEN}\" \\\n  -H 'A2A-Version: 1.0' \\\n  -H 'Content-Type: application/json' \\\n  --data-binary \"$(\n    jq -nc --arg id \"${TASKID}\" '{\n      jsonrpc: \"2.0\",\n      id: \"guide-get-1\",\n      method: \"GetTask\",\n      params: {id: $id, historyLength: 5}\n    }'\n  )\" \\\n  http://127.0.0.1:18080/a2a/v1 \\\n  | jq -e --arg id \"${TASKID}\" '\n      .error == null\n      and .result.id == $id\n      and .result.status.state == \"TASKSTATECOMPLETED\"\n    '\n\nA successful check prints true. historyLength keeps the newest requested\nhistory entries while preserving their native sequence order.\n\nChoose synchronous, asynchronous, or streaming work\n\nThe send configuration changes response behavior, not the underlying AIP\nlifecycle:\n\n| A2A operation or option | Current behavior |\n\n| SendMessage | Dispatches through the gateway and returns a completed, submitted, or input-required task according to the native outcome |\n| SendMessage with configuration.returnImmediately: true | Requests native asynchronous mode and returns the durable task handle |\n| SendStreamingMessage | Forces asynchronous mode and emits task status and artifact updates as SSE until a terminal state |\n| SubscribeToTask | Opens a new SSE view for an existing nonterminal task |\n| GetTask | Reads one native status projection and optionally limits history |\n| ListTasks | Lists visible A2A-bound actions with filters and page sizes from 1 through 100 |\n| CancelTask | Persists native cancellation intent unless the task is already terminal |\n\nThe streaming handler polls durable native action status and retained chunks.\nIts SSE events do not contain event IDs, and it does not implement\nLast-Event-ID. Reconnect a nonterminal task with SubscribeToTask and the\ntask ID. Read a terminal task with GetTask; terminal-task subscription is\nrejected.\n\nA transport disconnect does not prove that a mutation failed. Read the task or\nnative action before retrying the same logical work, and reuse the original\nmessageId when idempotency should return the original result.\n\nUnderstand identity and tenant limits\n\nEvery A2A JSON-RPC operation requires the configured native bearer token. The\ndaemon compares the token in constant time, binds the configured principal and\nscopes, and constructs trusted gateway context. JSON-RPC metadata cannot choose\nthe authenticated actor. Public Agent Card discovery remains unauthenticated.\n\nThe current command-line A2A edge maps one static token to one principal. It\ndoes not perform OAuth introspection or map different external users to\ndifferent AIP principals. A trusted edge can protect and rate-limit the route,\nbut requests forwarded with the daemon token still share that one daemon-side\nidentity.\n\nAt this revision, A2A JSON-RPC dispatch calls the verified gateway without a\nVerifiedTenant. Treat a request tenant field as profile data or a list\nfilter, not as tenant authority. When connector fleet services are enabled,\nthe Agent Card advertises an optional tenant-capability-discovery extension\nthat points to a separate authenticated native endpoint. It does not\nmaterialize the remote fleet catalog as Agent Card skills.\n\nUse native AIP or the stable MCP fleet facade when verified tenant routing is a\nrequirement. Do not describe A2A task success as connector-fleet qualification.\n\nEnable push notifications safely\n\ngetaip-server advertises A2A push notifications only when both controls are present:\n• an Ed25519 callback signer from --callback-signing-seed-file, its inline\n  alternative, or the corresponding environment variable;\n• a 32-byte encryption key from GETAIPSERVERA2APUSHENCRYPTIONKEYHEX or the\n  inline --a2a-push-encryption-key-hex option.\n\nPrefer a file for the signing seed and secret-manager injection for the\nencryption-key environment variable. Inline hexadecimal values can persist in\nshell history or process inspection.\n\nFor a non-loopback deployment, the A2A-specific controls fit into a command\nsuch as this after the encryption-key environment variable is injected:\n\ncargo run --locked -p getaip-server -- \\\n  --bind 0.0.0.0:18080 \\\n  --public-base-url https://aip.example.com \\\n  --service-id agent:getaip:server:a2a-production \\\n  --postgres-url-file /run/secrets/getaip-server-postgres-url \\\n  --native-bearer-token-file /run/secrets/getaip-server-native-token \\\n  --native-principal service:a2a:trusted-edge \\\n  --native-principal-scope action:read \\\n  --native-principal-scope action:write \\\n  --callback-signing-seed-file /run/secrets/aip-callback-signing-seed \\\n  --callback-allowed-host callbacks.example.com\n\nTerminate TLS at a trusted edge and route the public HTTPS origin to the\nprivate listener. The external base URL must be an HTTPS origin without a\npath, query, fragment, or embedded credentials.\n\nBefore accepting a push configuration, verify that:\n• the callback URL uses HTTPS and its exact host is allowlisted;\n• private and loopback destinations remain blocked unless an owned isolated\n  network requires an explicit exception;\n• stored callback token and authorization credentials use the configured\n  encryption key;\n• the receiver verifies the signed callback and treats deliveries as\n  idempotent;\n• durable profile state, callback delivery state, recovery, backup, and key\n  rotation are part of the deployment design.\n\nThe delivery worker uses a durable cursor and fencing to coordinate recovery.\nThat control suppresses competing recovery work but does not justify an\nexactly-once provider claim.\n\nResolve common failures\n\n| Symptom | Likely boundary | Safe next check |\n\n| 401 Unauthorized | A2A bearer identity | Confirm --native-bearer-token-file, the exact Authorization header, and token-file permissions |\n| VERSIONNOTSUPPORTED | A2A header | Send A2A-Version: 1.0 or omit the optional header |\n| INVALIDPARAMS for send | Message mapping | Check messageId, ROLEUSER, at least one part, and metadata.aip.capabilityid |\n| Agent Card omits a fleet capability | Discovery boundary | Use the advertised tenant discovery extension, native AIP, or the stable MCP facade |\n| TASKNOTFOUND | Identity, task binding, or retention | Reuse the authenticated principal and exact returned task ID; then inspect native action state |\n| Streaming ended before the result was read | Connection boundary | Call GetTask; use SubscribeToTask only while the task is nonterminal |\n| Push support is false | Callback controls | Configure both the signer and A2A credential-encryption key, then restart the daemon |\n| Push configuration is rejected | Destination or ownership policy | Check task access, HTTPS, the exact host allowlist, private-network policy, and configuration ID conflicts |\n\nJSON-RPC application errors normally arrive in a successful HTTP response.\nInspect the JSON error field even when curl reports HTTP success.\n\nStop and clean up the walkthrough\n\nStop getaip-server with Control-C. Inspect and remove only the local guide files:\n\ndu -sh .getaip-server-a2a-guide 2>/dev/null || true\nrm -rf -- .getaip-server-a2a-guide\nrm -f -- \\\n  .getaip-server-a2a-token \\\n  .getaip-server-a2a-card.json \\\n  .getaip-server-a2a-send.json \\\n  .getaip-server-a2a-send-response.json\n\nDo not apply this cleanup to a production state path. Durable task, push,\ncallback, and recovery records can reside there.\n\nRelated documentation\n• Use native AIP (use-native-aip.md)\n• Profiles and connectors (../concepts/profiles-and-connectors.md)\n• Actions and sessions (../concepts/actions-and-sessions.md)\n• Identity and trust (../concepts/identity-and-trust.md)\n• Approvals and policy (../concepts/approvals-and-policy.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "a176f7395ce523d2a85a551700b8a806f8ce8af05e34d6103a67b8d7fccdc777"
  }
}
