feat(extensions): add AIAR identity extension (v0 MVP)#1592
feat(extensions): add AIAR identity extension (v0 MVP)#1592ibrahimokuyucu wants to merge 1 commit intoa2aproject:mainfrom
Conversation
Introduce the Agent Identity and Accountability Reporting (AIAR) extension, providing verifiable identity binding for Agent Cards and runtime proof-of-possession for agent endpoints. Includes: - Extension spec: docs/extensions/aiar-identity-v0.md - Agent Card extension params (issuer, kid, JWS, attestations) - Message-level opt-in request and proof bundle response - Optional RPC methods (aiar.getProofBundle, aiar.getIssuer) - Example payloads with verification README - Updated specification.md and extensions.md with AIAR examples Made-with: Cursor
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces the Agent Identity and Accountability Reporting (AIAR) extension, a significant enhancement to the A2A protocol. It addresses the critical need for verifiable identity binding in Agent Cards and runtime endpoints, allowing clients to cryptographically confirm the authenticity and ownership of agents. By providing a robust framework for identity and accountability, this extension lays the groundwork for more trusted and secure agent interactions within the A2A ecosystem, all while maintaining full backwards compatibility. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces the Agent Identity and Accountability Reporting (AIAR) extension, a significant and well-documented feature. The specification is thorough, covering verifiable identity in Agent Cards and runtime proof-of-possession. My feedback focuses on improving consistency across the new documentation and examples, particularly regarding naming conventions for enum-like values and metadata keys, and ensuring JWS headers in examples align with the specification.
Note: Security Review has been skipped due to the limited scope of the PR.
| "issuer": "https://example.com", | ||
| "kid": "example-key-2025-01", | ||
| "proofOfPossession": { | ||
| "protected": "eyJhbGciOiJFUzI1NiJ9", |
There was a problem hiding this comment.
The JWS protected header in this example for proofOfPossession is missing the kid field. Other examples in this specification (e.g., for the Agent Card signature and the message-level response) include the kid in the protected header. For consistency within the AIAR specification, the kid should also be included here.
The current protected value eyJhbGciOiJFUzI1NiJ9 decodes to {"alg":"ES256"}. It should also contain the kid to be consistent with other examples, like {"alg":"ES256","kid":"example-key-2025-01"}.
| "protected": "eyJhbGciOiJFUzI1NiJ9", | |
| "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImV4YW1wbGUta2V5LTIwMjUtMDEifQ", |
|
|
||
| | Field | Type | Required | Description | | ||
| | :--- | :--- | :--- | :--- | | ||
| | `minAssurance` | string | Yes | Minimum assurance level required. Values: `"self-signed"`, `"org-signed"`, `"third-party-signed"`. | |
There was a problem hiding this comment.
The string values for minAssurance ("self-signed", "org-signed", "third-party-signed") resemble enum values. To align with the A2A protocol's convention of using SCREAMING_SNAKE_CASE for enum values, it would be better to use this format. This improves consistency across the protocol. This also applies to the Assurance levels table on lines 202-204 and the example on line 229.
| | `minAssurance` | string | Yes | Minimum assurance level required. Values: `"self-signed"`, `"org-signed"`, `"third-party-signed"`. | | |
| | `minAssurance` | string | Yes | Minimum assurance level required. Values: `"SELF_SIGNED"`, `"ORG_SIGNED"`, `"THIRD_PARTY_SIGNED"`. | |
References
- Enum values in the A2A protocol should be in
SCREAMING_SNAKE_CASEto comply with the ProtoJSON specification.
| `Message.metadata` for direct message responses), keyed by the extension URI | ||
| with a `/proof_bundle` suffix: | ||
|
|
||
| **Metadata key:** `https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proof_bundle` |
There was a problem hiding this comment.
The metadata key for the response proof bundle is .../proof_bundle. This is inconsistent with the request metadata key suffix, which is /request. For consistency with JSON camelCase conventions used elsewhere in the protocol, I suggest changing this to /proofBundle.
| **Metadata key:** `https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proof_bundle` | |
| **Metadata key:** `https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proofBundle` |
| }, | ||
| "metadata": { | ||
| "https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/request": { | ||
| "minAssurance": "org-signed", |
There was a problem hiding this comment.
To maintain consistency with the suggested change in docs/extensions/aiar-identity-v0.md, the value for minAssurance should be updated from "org-signed" to ORG_SIGNED. This aligns with the SCREAMING_SNAKE_CASE convention for enum-like values.
| "minAssurance": "org-signed", | |
| "minAssurance": "ORG_SIGNED", |
References
- Enum values in the A2A protocol should be in
SCREAMING_SNAKE_CASEto comply with the ProtoJSON specification.
| ## How to Verify a Runtime Proof Bundle | ||
|
|
||
| 1. **Extract the proof bundle** from the response `metadata` under the key | ||
| `https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proof_bundle`. |
There was a problem hiding this comment.
The metadata key .../proof_bundle should be updated to .../proofBundle to be consistent with the suggested change in the main extension specification for better naming consistency.
| `https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proof_bundle`. | |
| `https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proofBundle`. |
| }, | ||
| "metadata": { | ||
| "https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/request": { | ||
| "minAssurance": "org-signed", |
There was a problem hiding this comment.
For consistency with protocol conventions, the minAssurance value should be ORG_SIGNED instead of org-signed, following the SCREAMING_SNAKE_CASE format for enum-like values.
| "minAssurance": "org-signed", | |
| "minAssurance": "ORG_SIGNED", |
References
- Enum values in the A2A protocol should be in
SCREAMING_SNAKE_CASEto comply with the ProtoJSON specification.
| } | ||
| }, | ||
| "metadata": { | ||
| "https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proof_bundle": { |
There was a problem hiding this comment.
The metadata key .../proof_bundle should be updated to .../proofBundle for consistency with other metadata keys and JSON naming conventions.
| "https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proof_bundle": { | |
| "https://github.com/a2aproject/A2A/extensions/aiar.identity/v0/proofBundle": { |
| "issuer": "https://example.com", | ||
| "kid": "example-key-2025-01", | ||
| "proofOfPossession": { | ||
| "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImV4YW1wbGUta2V5LTIwMjUtMDEiLCJ0eXAiOiJwb3Aram3rIn0", |
There was a problem hiding this comment.
The protected header in the proofOfPossession JWS includes "typ":"pop+jws". This typ value is not defined in the AIAR specification. To maintain consistency with the spec, it's best to remove this undocumented field. The new protected header would be {"alg":"ES256","kid":"example-key-2025-01"}.
| "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImV4YW1wbGUta2V5LTIwMjUtMDEiLCJ0eXAiOiJwb3Aram3rIn0", | |
| "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImV4YW1wbGUta2V5LTIwMjUtMDEifQ", |
| "issuer": "https://example.com", | ||
| "kid": "example-key-2025-01", | ||
| "proofOfPossession": { | ||
| "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImV4YW1wbGUta2V5LTIwMjUtMDEiLCJ0eXAiOiJwb3Aram3rIn0", |
There was a problem hiding this comment.
The protected header in the proofOfPossession JWS includes "typ":"pop+jws". This typ value is not defined in the AIAR specification. To keep the examples aligned with the specification, I suggest removing this field. The new protected header would be {"alg":"ES256","kid":"example-key-2025-01"}.
| "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImV4YW1wbGUta2V5LTIwMjUtMDEiLCJ0eXAiOiJwb3Aram3rIn0", | |
| "protected": "eyJhbGciOiJFUzI1NiIsImtpZCI6ImV4YW1wbGUta2V5LTIwMjUtMDEifQ", |
|
This directly addresses a gap we've encountered in production: discovery ≠ identity. When building Agenium — a platform where agents have persistent addresses (agent://name.agenium) — we found that most implementations conflate the endpoint URL with the agent's identity. AIAR's proof-of-possession approach is the right abstraction. One question on the v0 spec: how does AIAR handle identity continuity across endpoint migrations? If an agent moves from host A to host B (common with rolling deploys), the cryptographic binding needs to transfer. Is the issuer identity anchored to a key pair independent of the endpoint, or is there a re-attestation flow? This matters especially for A2A trust scoring — behavioral reputation accumulated at identity X should persist even if X migrates endpoints. Otherwise you get cold-start penalties every deploy cycle. |
Great question. The intent in v0 is that identity is anchored to the key pair, not the endpoint. So an agent can move from host A to host B and keep the same identity as long as it proves possession of the same key and presents a valid signed Agent Card. Key rotation / successor identities are not specified in v0 yet. How did you handle this in Agenium? |
|
Strong proposal. The JWS + JCS canonicalization approach is well-suited for enterprise environments where existing PKI infrastructure already issues keys. I maintain AIP (Agent Identity Protocol) and submitted a DID-based identity extension in #1511. Reading through AIAR, I see significant overlap in goals but complementary design choices:
Rather than competing proposals, I think A2A benefits from a unified approach. Some thoughts:
Would be interested in collaborating on a unified identity extension that supports both enterprise (JWS/JWKS) and decentralized (DID/Ed25519) patterns. The verification procedure in AIAR Section 5 could accept either format. |
Summary
This PR introduces the Agent Identity and Accountability Reporting (AIAR) extension (
v0MVP), a backwards-compatible A2A extension that provides verifiable identity binding for Agent Cards and runtime proof-of-possession for agent endpoints.Problem: The A2A protocol enables agent discovery and communication but does not provide a mechanism for clients to verify that an Agent Card or runtime endpoint is bound to a verifiable issuer identity. Discovery is not identity; runtime auth is not ownership.
Solution: AIAR adds opt-in, cryptographic identity primitives using standard formats (JWS, JCS canonicalization) that higher-level trust frameworks can build upon.
What's included
Extension specification (
docs/extensions/aiar-identity-v0.md):issuer,kid,signedFields,jws,attestationsminAssurance,acceptableIssuers,requireFreshnessSeconds)cardDigest,proofOfPossession, timestamps)aiar.getProofBundle,aiar.getIssuerSpecification updates (
docs/specification.md):Extensions list update (
docs/topics/extensions.md):Example payloads (
examples/aiar-identity/):agent-card.json— standard Agent Card without AIARagent-card.signed.json— Agent Card with AIAR extension params + JWSmessage.request.json— SendMessage with identity requirements in metadatamessage.response.json— task response with proof bundle in metadataproof-bundle.json— standalone proof bundle (as returned byaiar.getProofBundle)README.md— step-by-step verification guideHow clients opt in
capabilities.extensions[]in the Agent Card for the AIAR URIA2A-Extensions: https://github.com/a2aproject/A2A/extensions/aiar.identity/v0headerSendMessageRequest.metadataWhat's explicitly out of scope (v0)
aiar.rotateKeysdeferred to future version)Compatibility
AgentExtension.params,Message.metadata,Task.metadata)a2a.protoor core data structuresChecklist
docs/extensions/aiar-identity-v0.mdexists with full spec + examplesexamples/folder includes valid JSON payloads + verification README