{"id":145,"date":"2026-08-17T05:05:24","date_gmt":"2026-08-17T05:05:24","guid":{"rendered":"https:\/\/www.akarnik.com\/blog\/agent-to-agent-protocol-citations"},"modified":"2026-08-17T05:05:24","modified_gmt":"2026-08-17T05:05:24","slug":"agent-to-agent-protocol-citations","status":"publish","type":"post","link":"https:\/\/www.akarnik.com\/blog\/agent-to-agent-protocol-citations","title":{"rendered":"Agent to Agent Protocol for Citations: JSON Patterns"},"content":{"rendered":"<p><em>Written by: Arjun Karnik, Growth Marketing Specialist<\/em><\/p>\n<h2 id=\"key-takeaways\">Key Takeaways<\/h2>\n<ul>\n<li>The A2A protocol has no native citation tracking, so you must add custom provenance wrappers in <code>Artifact.metadata<\/code> to keep attribution intact across multi-hop agent interactions.<\/li>\n<li>Citation metadata belongs in <code>Artifact.metadata<\/code> for lifecycle survival, in <code>Part.metadata<\/code> for claim-level attribution, and in <code>Task.metadata<\/code> only for tracing context to preserve audit boundaries.<\/li>\n<li>Extensions declared on AgentCard with <code>required: true<\/code> ensure downstream agents can verify citation provenance using the <code>x-citation-provenance-v1<\/code> schema.<\/li>\n<li>Verification status values (<code>agent-reported<\/code>, <code>verified<\/code>, <code>conflict-detected<\/code>, <code>unresolvable<\/code>) must be enforced by receiving agents to block fabricated attribution in production systems.<\/li>\n<li>Arjun Karnik\u2019s test lab methodology provides production-ready patterns for citation provenance; <a href=\"https:\/\/www.akarnik.com\/demo\" target=\"_blank\"><strong>book a demo<\/strong><\/a> to apply these patterns to your agent architecture.<\/li>\n<\/ul>\n<h2>JSON Provenance Wrapper Pattern in Artifact.metadata<\/h2>\n<p>The recommended citation metadata pattern uses a JSON provenance wrapper embedded in <code>Artifact.metadata<\/code> under a declared extension URI. This wrapper pairs each claim with its source URL, retrieval timestamp, confidence score, and verification status so any receiving agent can audit attribution without calling back to the originating agent. The wrapper travels with the artifact across every hop.<\/p>\n<p><a href=\"https:\/\/deepwiki.com\/a2aproject\/a2a-python\/2.4-extensions-and-metadata\" target=\"_blank\" rel=\"noindex nofollow\">Metadata is represented as arbitrary key-value data on most core A2A types, including DataPart, TextPart, PartBase, Message, Task, and TaskIdParams<\/a>, which gives you a standard channel for contextual information across the system. The citation object below uses that channel.<\/p>\n<p>The following example shows a complete provenance wrapper with a single citation and a two-hop chain. Notice how <code>citation_id<\/code> links the claim to its source and how the <code>provenance_chain<\/code> array records each agent that touched the artifact.<\/p>\n<pre><code>{ \"metadata\": { \"x-citation-provenance-v1\": { \"schema_uri\": \"https:\/\/akarnik.com\/schemas\/citation-provenance\/v1\", \"citations\": [ { \"citation_id\": \"cit-001\", \"claim_text\": \"A2A v1.0 has no native citation schema.\", \"source_url\": \"https:\/\/example.com\/source-document\", \"source_title\": \"Source Document Title\", \"retrieved_at\": \"2026-08-16T09:00:00Z\", \"confidence\": 0.92, \"verification_status\": \"agent-reported\", \"originating_agent\": \"research-agent-01\", \"hop_index\": 1 } ], \"provenance_chain\": [ { \"agent_id\": \"research-agent-01\", \"hop_index\": 1, \"timestamp\": \"2026-08-16T09:00:00Z\", \"action\": \"retrieved\" }, { \"agent_id\": \"synthesis-agent-02\", \"hop_index\": 2, \"timestamp\": \"2026-08-16T09:01:00Z\", \"action\": \"forwarded\" } ] } } }<\/code><\/pre>\n<p>Every field is required at write time. Receiving agents must not strip or overwrite <code>x-citation-provenance-v1<\/code> when forwarding an artifact.<\/p>\n<h2>Placement Rules for Artifact, Part, and Task Metadata<\/h2>\n<p><a href=\"https:\/\/deepwiki.com\/a2aproject\/a2a-python\/2.4-extensions-and-metadata\" target=\"_blank\" rel=\"noindex nofollow\">The A2A Python implementation describes a full metadata flow with eight stages: client initiation on TaskIdParams.metadata, transport serialization, CallContextBuilder extraction, DefaultRequestHandler access, proto_utils.ToProto conversion, TaskStore persistence, proto_utils.FromProto restoration, and TaskUpdater.update_status acceptance<\/a>. Placement decisions map directly to that flow.<\/p>\n<p>Use <strong>Artifact.metadata<\/strong> for citation data that must survive the full task lifecycle and remain auditable by downstream agents. An artifact is the terminal output of an agent step. <a href=\"https:\/\/deepwiki.com\/a2aproject\/a2a-python\/2.4-extensions-and-metadata\" target=\"_blank\" rel=\"noindex nofollow\">TaskUpdater.add_artifact() accepts an extensions parameter (list of URIs) and a metadata dict, which lets you attach extension declarations and contextual data to artifacts during multi-hop task updates<\/a>. Place the full provenance wrapper here.<\/p>\n<p>Use <strong>Part.metadata<\/strong> for claim-level citation when a single artifact contains multiple independently sourced claims. <a href=\"https:\/\/deepwiki.com\/a2aproject\/a2a-python\/2.4-extensions-and-metadata\" target=\"_blank\" rel=\"noindex nofollow\">Metadata is available on DataPart, TextPart, and PartBase<\/a>. Attach a reduced citation object with <code>citation_id<\/code>, <code>source_url<\/code>, <code>confidence<\/code>, and <code>verification_status<\/code> to each Part so the retrieval layer can resolve attribution at the claim level without parsing the full artifact.<\/p>\n<p>Use <strong>Task.metadata<\/strong> for session-scoped routing and tracing data that supports the citation audit but is not itself a citation. <a href=\"https:\/\/deepwiki.com\/a2aproject\/a2a-python\/2.4-extensions-and-metadata\" target=\"_blank\" rel=\"noindex nofollow\">Metadata usage patterns in A2A include tracing via trace_id and span_id, routing via tenant_id and region, analytics via source and user_segment, and debugging via debug_mode and test_id<\/a>. Store <code>trace_id<\/code> and <code>session_id<\/code> at Task level and store citation objects at Artifact and Part level.<\/p>\n<p>The rule is simple: citation content lives at Artifact and Part level, while tracing context lives at Task level. Mixing them collapses the audit boundary.<\/p>\n<h2>How to Add Provenance So Downstream Agents Can Verify<\/h2>\n<p><a href=\"https:\/\/tyk.io\/learning-center\/a2a-protocol-architecture-and-technical-specification\" target=\"_blank\" rel=\"noindex nofollow\">A2A Extensions are formalized in Section 4.6 of the specification and can be declared on the AgentCard to embed additional schema information such as per-skill JSON Schema fragments<\/a>. The extension URI acts as the declaration mechanism that tells receiving agents a citation provenance wrapper is present and required.<\/p>\n<p><a href=\"https:\/\/deepwiki.com\/a2aproject\/a2a-python\/2.4-extensions-and-metadata\" target=\"_blank\" rel=\"noindex nofollow\">The A2A protocol defines AgentExtension with fields uri (str), description (str or None), params (dict or None), and required (bool or None). When required is True, agents reject requests from clients lacking support for the extension<\/a>. Set <code>required: true<\/code> for any agent that must emit verifiable citations. When <code>required<\/code> is true, agents reject requests from clients that do not declare support for the extension.<\/p>\n<p>The <code>verification_status<\/code> field distinguishes what an agent reported from what has been independently confirmed. Receiving agents must read this field before treating a citation as ground truth. To ensure downstream agents can read and enforce this field, you must first declare the citation extension on the AgentCard.<\/p>\n<h2>Example AgentCard Extension for Citations<\/h2>\n<p>Declare the extension on the AgentCard before any task starts so client agents can evaluate capability before delegating work. This signals to client agents that citation provenance is a required capability. The example below shows how the <code>required: true<\/code> flag enforces the extension and how the <code>params<\/code> object sets minimum quality thresholds.<\/p>\n<pre><code>{ \"agentCard\": { \"name\": \"research-agent-01\", \"version\": \"1.0.0\", \"extensions\": [ { \"uri\": \"https:\/\/akarnik.com\/schemas\/citation-provenance\/v1\", \"description\": \"Embeds source attribution and provenance chain in Artifact.metadata for downstream verification.\", \"required\": true, \"params\": { \"min_confidence\": 0.7, \"require_source_url\": true, \"require_retrieved_at\": true } } ] } }<\/code><\/pre>\n<p><a href=\"https:\/\/deepwiki.com\/a2aproject\/a2a-python\/2.4-extensions-and-metadata\" target=\"_blank\" rel=\"noindex nofollow\">Extensions are signaled differently by transport, with JSON-RPC using params.extensions, REST using the X-A2A-Extensions header, and gRPC using metadata headers, but all populate ServerCallContext.extensions for uniform access in AgentExecutor implementations<\/a>. The URI above is the stable identifier across all three transports.<\/p>\n<h2>Verification Status Field Patterns for Production Safety<\/h2>\n<p>The <code>verification_status<\/code> field carries one of four values. Each value has a defined meaning that receiving agents must enforce rather than interpret loosely.<\/p>\n<ul>\n<li><strong>agent-reported<\/strong>: The originating agent retrieved and included this citation. No independent check has been performed. Receiving agents must treat this as unverified.<\/li>\n<li><strong>verified<\/strong>: A dedicated verification agent has confirmed the claim against the source URL and the source content matched at retrieval time. The <code>verified_by<\/code> and <code>verified_at<\/code> fields must be populated when this status is set. Receiving agents must not promote <code>agent-reported<\/code> to <code>verified<\/code> without executing an independent retrieval check, because promotion without verification is the primary failure mode in multi-hop citation chains.<\/li>\n<li><strong>conflict-detected<\/strong>: Two or more agents returned contradictory claims for the same <code>citation_id<\/code>. The full set of conflicting citations must be preserved in a <code>conflicts<\/code> array. <a href=\"https:\/\/claudearchitectcertification.com\/scenarios\/multi-agent-research-system\" target=\"_blank\" rel=\"noindex nofollow\">Contradictions must retain full attribution and explanatory context rather than being resolved silently<\/a>.<\/li>\n<li><strong>unresolvable<\/strong>: The source URL returned a non-200 response at verification time or the source content no longer matches the claim. The <code>checked_at<\/code> timestamp must be populated.<\/li>\n<\/ul>\n<p>Receiving agents must enforce these meanings consistently to keep fabricated attribution out of production systems.<\/p>\n<h2>Full Artifact Example for Independent Audit<\/h2>\n<p>The following example shows a complete, production-ready Artifact that a receiving agent can consume and audit without calling back to the originating agent. This example differs from earlier fragments by including the full provenance chain with three hops (retrieve, verify, forward) and a verified status with timestamps, which gives everything needed for independent audit.<\/p>\n<pre><code>{ \"artifact\": { \"artifact_id\": \"art-20260816-001\", \"task_id\": \"task-20260816-research-001\", \"created_at\": \"2026-08-16T09:01:30Z\", \"content\": { \"type\": \"text\", \"text\": \"A2A v1.0 has no native citation schema. Engineers must add a provenance wrapper.\" }, \"extensions\": [ \"https:\/\/akarnik.com\/schemas\/citation-provenance\/v1\" ], \"metadata\": { \"x-citation-provenance-v1\": { \"schema_uri\": \"https:\/\/akarnik.com\/schemas\/citation-provenance\/v1\", \"citations\": [ { \"citation_id\": \"cit-001\", \"claim_text\": \"A2A v1.0 has no native citation schema.\", \"source_url\": \"https:\/\/chatforest.com\/guides\/a2a-protocol-v1-production-ready\", \"source_title\": \"A2A Protocol v1 Production Ready Guide\", \"retrieved_at\": \"2026-08-16T08:55:00Z\", \"confidence\": 0.95, \"verification_status\": \"verified\", \"verified_by\": \"verification-agent-03\", \"verified_at\": \"2026-08-16T09:00:45Z\", \"originating_agent\": \"research-agent-01\", \"hop_index\": 1 } ], \"provenance_chain\": [ { \"agent_id\": \"research-agent-01\", \"hop_index\": 1, \"timestamp\": \"2026-08-16T08:55:00Z\", \"action\": \"retrieved\", \"trace_id\": \"4bf92f3577b34da6a3ce929d0e0e4736\" }, { \"agent_id\": \"verification-agent-03\", \"hop_index\": 2, \"timestamp\": \"2026-08-16T09:00:45Z\", \"action\": \"verified\", \"trace_id\": \"4bf92f3577b34da6a3ce929d0e0e4736\" }, { \"agent_id\": \"synthesis-agent-02\", \"hop_index\": 3, \"timestamp\": \"2026-08-16T09:01:30Z\", \"action\": \"forwarded\", \"trace_id\": \"4bf92f3577b34da6a3ce929d0e0e4736\" } ] }, \"trace_id\": \"4bf92f3577b34da6a3ce929d0e0e4736\", \"span_id\": \"00f067aa0ba902b7\" } } }<\/code><\/pre>\n<p><a href=\"https:\/\/tyk.io\/learning-center\/a2a-protocol-architecture-and-technical-specification\" target=\"_blank\" rel=\"noindex nofollow\">The A2A specification recommends including W3C Trace Context headers (traceparent and tracestate) on every call to enable tracing of a single user request across an entire multi-agent chain<\/a>. The <code>trace_id<\/code> and <code>span_id<\/code> fields in the example above satisfy that requirement and link the citation audit record to the observability trace.<\/p>\n<p><a href=\"https:\/\/www.akarnik.com\/demo\" target=\"_blank\"><strong>Book a demo<\/strong><\/a> to walk through this Artifact pattern against your own agent topology with Arjun Karnik\u2019s test lab.<\/p>\n<h2>Performance Numbers from Arjun Karnik\u2019s Test Lab<\/h2>\n<p>The following numbers come from Arjun Karnik\u2019s own site and test lab, not from AI Growth Agent case studies.<\/p>\n<p>In Arjun\u2019s tests, pages can drop 78% to 99% in two months without updates. That decay rate applies equally to agent-generated content that is not refreshed after initial publication. The citation provenance patterns documented here were developed and validated on his own properties, with controls held back to isolate the effect of structured metadata on retrieval and citation behavior.<\/p>\n<p>New articles on Arjun\u2019s site reached thousands of monthly Google impressions within weeks of deployment. The GEO subfolder went from zero to the only source of new impressions on the entire domain in 60 days, measured in Google Search Console. Pages rewritten to match extracted fan-out queries earned citations while control pages did not. These results are from his own site, not from client engagements.<\/p>\n<p>For independent market context, <a href=\"https:\/\/seerinteractive.com\" target=\"_blank\" rel=\"noindex nofollow\">Seer Interactive analyzed 47,097 AI citations across 7,683 pages in ChatGPT, Gemini, and Perplexity between March and June 2026, and found that 75% of cited pages had been updated within the last year, with consistently cited pages averaging under six months since their last update<\/a>. Structured, fresh content earns citations. The provenance wrapper is the structural component and freshness is the operational one.<\/p>\n<figure style=\"text-align: center\"><a href=\"https:\/\/www.akarnik.com\/demo\" target=\"_blank\"><img decoding=\"async\" src=\"https:\/\/cdn.aigrowthmarketer.co\/1786472438102-dfd59b5fabac.png\" alt=\"Bar chart showing 75 percent of pages cited by AI assistants were updated within the last year and 25 percent were older. Source: Seer Interactive, July 2026, 7,683 pages and 47,097 citations across ChatGPT, Gemini and Perplexity.\" style=\"max-height: 500px\" loading=\"lazy\"><\/a><figcaption><em>Three quarters of cited pages were updated inside a year, and the consistently cited ones averaged under six months. The page you refresh beats the page you write.<\/em><\/figcaption><\/figure>\n<p>AI Growth Agent case studies are AI Growth Agent\u2019s results, not Arjun\u2019s. They are cited separately and attributed to AI Growth Agent wherever they appear.<\/p>\n<h2>Frequently Asked Questions<\/h2>\n<h3>What is a citation object in the A2A protocol?<\/h3>\n<p>A citation object is a JSON structure embedded in <code>Artifact.metadata<\/code> that pairs a claim with its source URL, retrieval timestamp, confidence score, and verification status. The A2A spec does not define one natively. Engineers must add it using the extension and metadata surfaces the spec provides. The citation object travels with the artifact across every agent hop so downstream agents can audit attribution without calling back to the originating agent.<\/p>\n<h3>What is a provenance wrapper and why does it matter?<\/h3>\n<p>The provenance wrapper is the outer JSON structure that contains both the citations array and the provenance chain array, as described in the recommended pattern above. The citations array records what was claimed and where it came from, and the provenance chain records which agent handled the artifact at each hop and what action it took. Together they give a receiving agent a complete, auditable record of how a claim moved through the system.<\/p>\n<h3>Where exactly should citation metadata be stored, Artifact, Part, or Task?<\/h3>\n<p>Store the full provenance wrapper in <code>Artifact.metadata<\/code> as described in the placement rules section. Store a reduced citation object with <code>citation_id<\/code>, <code>source_url<\/code>, <code>confidence<\/code>, and <code>verification_status<\/code> in <code>Part.metadata<\/code> when a single artifact contains multiple independently sourced claims. Store only tracing and routing data such as <code>trace_id<\/code> and <code>session_id<\/code> in <code>Task.metadata<\/code>. Citation content belongs at Artifact and Part level and tracing context belongs at Task level.<\/p>\n<h3>What is the difference between agent-reported and verified citation status?<\/h3>\n<p>See the \u201cVerification Status Field Patterns for Production Safety\u201d section for the full definitions of <code>agent-reported<\/code> versus <code>verified<\/code> status and the rules for promotion.<\/p>\n<h3>How do I declare the citation extension URI on an AgentCard?<\/h3>\n<p>See the \u201cHow to Add Provenance So Downstream Agents Can Verify\u201d section for details on declaring the extension URI, setting <code>required: true<\/code>, and configuring the <code>params<\/code> object.<\/p>\n<h2>Conclusion and Next Steps for Production Rollout<\/h2>\n<p>The A2A protocol provides the extension and metadata surfaces needed to carry citation provenance across agent hops, but it does not provide the citation schema itself. Engineers must add the provenance wrapper, declare the extension URI on the AgentCard, place citation objects at Artifact and Part level, and enforce the verification status field so receiving agents can distinguish agent-reported claims from verified ones.<\/p>\n<p>The four required components are:<\/p>\n<ol>\n<li>A declared extension URI on the AgentCard with <code>required: true<\/code><\/li>\n<li>A citations array in <code>Artifact.metadata<\/code> containing claim text, source URL, retrieval timestamp, confidence, and verification status<\/li>\n<li>A provenance chain array recording each agent hop, action, and timestamp<\/li>\n<li>A verification agent that promotes <code>agent-reported<\/code> to <code>verified<\/code> only after an independent retrieval check<\/li>\n<\/ol>\n<p>Arjun Karnik\u2019s test lab has documented the implementation patterns, placement rules, and verification mechanisms on his own properties, with controls and misses included. The methodology is public and self-verifying.<\/p>\n<p><a href=\"https:\/\/www.akarnik.com\/demo\" target=\"_blank\"><strong>Book a demo<\/strong><\/a> to review the full citation provenance schema, extension URI declaration, and verification patterns against your specific agent architecture.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to add citation tracking to the A2A protocol with JSON provenance patterns that survive multi-hop chains. Practical guide by Arjun Karnik.<\/p>\n","protected":false},"author":118,"featured_media":144,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-145","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/posts\/145","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/comments?post=145"}],"version-history":[{"count":0,"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/posts\/145\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/media\/144"}],"wp:attachment":[{"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/media?parent=145"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/categories?post=145"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.akarnik.com\/blog\/wp-json\/wp\/v2\/tags?post=145"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}