A2A (Agent-to-Agent)
The @peac/mappings-a2a package provides two capabilities: (1) carrying verifiable evidence through A2A metadata in TaskStatus, Message, and Artifact objects using the Evidence Carrier Contract, and (2) issuing signed handoff observation records for agent-to-agent task delegation events (v0.14.1+).
A2A v1.0.0 compatible. The A2A adapter supports Agent Card, TaskState, and Parts for A2A v1.0.0. Microsoft AGT and AAIF (Agent AI Interoperability Framework) compatible.
Install
pnpm add @peac/mappings-a2a
Quick start
import { attachReceiptToArtifact, extractReceiptFromArtifactAsync } from '@peac/mappings-a2a';
// Attach evidence to an A2A artifact
const artifact = attachReceiptToArtifact(originalArtifact, [
{
receipt_ref: 'sha256:abc123...',
receipt_jws: 'eyJhbGciOiJFZERTQSIs...',
},
]);
// Extract evidence from an A2A artifact
const result = await extractReceiptFromArtifactAsync(incomingArtifact);
if (result) {
for (const carrier of result.receipts) {
console.log(carrier.receipt_ref); // 'sha256:abc123...'
console.log(carrier.receipt_jws); // 'eyJhbGciOiJFZERTQSIs...'
}
}
Carrier placement
A2A evidence is placed in the metadata object using a reverse-DNS extension URI:
{
"metadata": {
"https://www.peacprotocol.org/ext/traceability/v1": {
"carriers": [
{
"receipt_ref": "sha256:abc123...",
"receipt_jws": "eyJhbGciOiJFZERTQSIs..."
}
]
}
}
}
The carrier array supports multiple receipts per A2A object. Each carrier includes at minimum receipt_ref (SHA-256 integrity anchor) and receipt_jws (signed compact JWS).
Agent Card discovery
A2A agents advertise PEAC support via the Agent Card capabilities.extensions array:
{
"name": "Evidence Agent",
"capabilities": {
"extensions": [
"https://www.peacprotocol.org/ext/traceability/v1"
]
}
}
3-step discovery flow
- Agent Card -- check
capabilities.extensions[]for the PEAC traceability extension URI - Well-known -- fetch
/.well-known/peac-issuer.jsonfrom the agent's host for issuer configuration and JWKS URI - Header probe -- check for
PEAC-Receiptheader in HTTP responses from the agent
Transport limits
| Constraint | Value |
|---|---|
| Maximum embed size | 64 KB |
| Carrier format | PeacEvidenceCarrier |
| Integrity check | sha256(receipt_jws) === receipt_ref |
When extracting a carrier from A2A metadata, always verify that sha256(receipt_jws) matches receipt_ref. This prevents tampering during transport.
Supported A2A objects
| Object | Carrier placement |
|---|---|
TaskStatus | status.metadata[extensionURI].carriers[] |
Message | message.metadata[extensionURI].carriers[] |
Artifact | artifact.metadata[extensionURI].carriers[] |
Handoff Observation Records (v0.14.1+)
Beyond evidence carriage, @peac/mappings-a2a can issue signed handoff observation records that describe agent-to-agent task delegation events. These records use the org.peacprotocol/a2a-handoff extension namespace and are compatible with Microsoft AGT (Agent Governance Toolkit) and AAIF (Agent AI Interoperability Framework).
Type URIs
| Type URI | Description |
|---|---|
org.peacprotocol/a2a-task-submitted | Task was submitted to an agent |
org.peacprotocol/a2a-task-accepted | Agent accepted the task |
org.peacprotocol/a2a-task-rejected | Agent rejected the task |
org.peacprotocol/a2a-task-completed | Agent reported task completion |
org.peacprotocol/a2a-task-failed | Agent reported task failure |
org.peacprotocol/a2a-task-state-changed | Task state transition was observed |
org.peacprotocol/a2a-agent-card-observation | An Agent Card was observed |
org.peacprotocol/a2a-human-review-requested | Human review was requested |
org.peacprotocol/a2a-human-approved | A human approved the task or handoff |
org.peacprotocol/a2a-human-rejected | A human rejected the task or handoff |
Issuing a handoff observation record
import { fromA2ATaskObservation } from '@peac/mappings-a2a';
import { issue } from '@peac/protocol';
// Build the handoff observation extension object
const handoffExtension = fromA2ATaskObservation({
event: 'task.submitted',
task_id: 'urn:task:abc-123',
from_agent: { card_ref: 'sha256:orchestrator-card...' },
to_agent: { card_ref: 'sha256:worker-card...' },
state: 'submitted',
upstream_event_ref: 'urn:a2a:event:submit-001',
observed_at: new Date().toISOString(),
});
// Issue a signed record
const { jws } = await issue({
iss: 'https://orchestrator.example.com',
kind: 'evidence',
privateKey: signingKey,
kid: 'orchestrator-key-1',
extensions: { ...handoffExtension },
});
Key fields
| Field | Required | Description |
|---|---|---|
event | Yes | Observed lifecycle event (e.g. task.submitted, task.completed) |
task_id | Yes | Opaque reference to the A2A task (urn:, ref:, did:, sha256:) |
from_agent | Yes | Agent the task is observed from (card_ref plus optional selected_interface_url) |
to_agent | No | Agent the task is observed to |
state | No | Free-form A2A state name as observed |
upstream_event_ref | No | Opaque pointer to the upstream A2A event |
upstream_event_digest | No | sha256:<hex> digest of the upstream A2A event payload |
observed_at | Yes | ISO 8601 timestamp of the observed event |
Handoff observation records describe what your system observed during agent coordination. PEAC does not route tasks, authorize agents, or enforce handoff policies. The upstream A2A infrastructure owns those decisions.
AGT and AAIF Compatibility
Handoff observation records are compatible with Microsoft AGT (Agent Governance Toolkit) and AAIF (Agent AI Interoperability Framework). PEAC records complement AGT governance by providing portable, offline-verifiable signed evidence of agent coordination events that can be verified outside the system that produced them.
Integration pattern:
- Your AGT-governed agent handles a task submission or handoff
- Issue a PEAC handoff observation record at the coordination boundary
- Attach the
receipt_refandreceipt_jwsto the A2A metadata usingattachReceiptToArtifact - The receiving agent or auditor can verify the record offline using only the issuer's public key
import { fromA2ATaskObservation, attachReceiptToArtifact } from '@peac/mappings-a2a';
import { issue } from '@peac/protocol';
import { computeReceiptRef } from '@peac/schema';
// Build the handoff observation at the AGT governance boundary
const handoffExt = fromA2ATaskObservation({
event: 'task.state_changed',
task_id: 'urn:task:agt-governed-001',
from_agent: { card_ref: 'sha256:gateway-card...' },
to_agent: { card_ref: 'sha256:worker-card...' },
state: 'handoff_initiated',
observed_at: new Date().toISOString(),
});
// Sign it into a portable record
const { jws } = await issue({
iss: 'https://gateway.corp.example.com',
kind: 'evidence',
privateKey: signingKey,
kid: 'gateway-key-1',
extensions: { ...handoffExt },
});
// Attach to the outgoing A2A artifact
const artifact = attachReceiptToArtifact(originalArtifact, [
{
receipt_ref: await computeReceiptRef(jws),
receipt_jws: jws,
},
]);