Skip to content

Latest commit

 

History

History
123 lines (92 loc) · 4.38 KB

File metadata and controls

123 lines (92 loc) · 4.38 KB

PEAC Integration Kit: Agent-to-Agent Protocol (A2A)

Carry signed receipts across A2A agent flows: declare PEAC support in your Agent Card, attach receipts to task metadata, and extract/verify them on the receiving side.

Overview

PEAC integrates with A2A at the metadata layer. Receipts travel as Evidence Carriers inside A2A TaskStatus metadata, using the reverse-DNS extension URI org.peacprotocol. No A2A protocol changes are required; PEAC uses the standard metadata extension mechanism.

Compatibility: @peac/mappings-a2a targets A2A v1.0.0 (shipped in v0.12.3). A2A v0.3.0 compat shim is retained through v0.12.x; removal scheduled for v0.13.0.

Prerequisites

  • Node.js >= 22.0.0
  • @peac/mappings-a2a, @peac/protocol, @peac/crypto
pnpm add @peac/mappings-a2a @peac/protocol @peac/crypto

Quick Start: Attach a Receipt to a Task

import { generateKeypair } from '@peac/crypto';
import { issue } from '@peac/protocol';
import { attachReceiptToTaskStatus, type A2ATaskStatusLike } from '@peac/mappings-a2a';
import { computeReceiptRef } from '@peac/schema';

const { publicKey, privateKey } = await generateKeypair();

// Issue a receipt
const { jws } = await issue({
  iss: 'https://gateway.example.com',
  kind: 'evidence',
  type: 'org.peacprotocol/payment',
  extensions: {
    'org.peacprotocol/commerce': {
      payment_rail: 'stripe',
      amount_minor: '5000',
      currency: 'USD',
    },
  },
  privateKey,
  kid: 'gateway-key',
});

// Attach to A2A TaskStatus
const taskStatus: A2ATaskStatusLike = { state: 'completed', metadata: {} };
const ref = await computeReceiptRef(jws);
attachReceiptToTaskStatus(taskStatus, [{ receipt_ref: ref, receipt_jws: jws }]);
// taskStatus.metadata now contains the PEAC carrier

Use Case 1: Gateway Issues Receipts per State Transition

A gateway agent issues one receipt per A2A task state transition (submitted, working, completed), building a verifiable chain.

See examples/a2a-gateway-pattern for the full runnable demo.

Use Case 2: Consumer Extracts and Verifies Receipts

import { extractReceiptFromTaskStatusAsync } from '@peac/mappings-a2a';
import { verifyLocal } from '@peac/protocol';

const extracted = await extractReceiptFromTaskStatusAsync(taskStatus);
if (extracted) {
  for (const carrier of extracted.receipts) {
    if (!carrier.receipt_jws) continue;
    const result = await verifyLocal(carrier.receipt_jws, publicKey);
    console.log(result.valid ? 'Verified' : `Failed: ${result.code}`);
  }
}

Use Case 3: Declare PEAC in Your Agent Card

Add the PEAC extension to your A2A Agent Card so peers know you support receipts:

{
  "name": "My Agent",
  "url": "https://agent.example.com",
  "capabilities": {
    "extensions": [
      {
        "uri": "org.peacprotocol",
        "required": false,
        "description": "PEAC evidence receipts for verifiable interaction records"
      }
    ]
  }
}

Check for PEAC support: hasPeacExtension(agentCard) returns true if declared.

Configuration

Option Type Required Description
receipt_ref string Yes SHA-256 hash of the compact JWS (computeReceiptRef())
receipt_jws string Yes The compact JWS receipt
receipt_url string No Optional HTTPS locator hint (not auto-fetched)

Transport size limit: 64 KB for MCP/A2A/UCP embed.

Troubleshooting

No receipts found after extraction: Verify the metadata key is org.peacprotocol (not org.peacprotocol/receipt). Check hasPeacExtension() on the agent card.

Receipt ref mismatch: The receipt_ref must equal sha256(receipt_jws). Use computeReceiptRef() from @peac/schema.

Verification fails with E_ISS_NOT_CANONICAL: The iss field must be https:// (ASCII, RFC 3986) or did: (DID Core). No other schemes are accepted.

Next Steps