Sender Identity (Layer 1)

By default, A2A messages are anonymous — the receiving agent has no idea who sent the message. Layer 1 adds Ed25519 cryptographic signatures so the receiver can verify which agent is calling.

Signing Outbound Messages

Provide a signingIdentity (DID + Ed25519 private key) and set signOutboundMessages: true. Every outbound message will automatically include a signed envelope in the A2A metadata.

import { AletheiaA2A } from "@a2aletheia/a2a";

const client = new AletheiaA2A({
  registryUrl: "https://registry.aletheia.dev",
  signOutboundMessages: true,
  signingIdentity: {
    did: "did:key:z6Mk...",              // Your agent's DID
    privateKey: process.env.AGENT_KEY!,   // Ed25519 hex
  },
});

// Messages now carry:
// metadata["urn:aletheia:sender-identity:v1"] = {
//   senderDid, signature, timestamp, messageId
// }
const result = await client.sendByCapability("translate", "Hello");

Verifying Inbound Senders

Enable verifySenderIdentity on a PeerAgent to automatically verify incoming message signatures. Use getVerifiedSender(context) inside the handler.

import { PeerAgent, getVerifiedSender } from "@a2aletheia/a2a";

const peer = new PeerAgent({
  name: "Hotel Agent",
  // ... other config ...
  verifySenderIdentity: true,
  // requireSignedMessages: true,  // reject unsigned
  // maxMessageAge: 300_000,       // 5 min replay window
});

peer.handle(async (context, response) => {
  const sender = getVerifiedSender(context);

  if (sender?.signatureValid) {
    console.log(`Verified call from: ${sender.did}`);
  } else if (!sender) {
    console.log("Unsigned message (no sender identity)");
  } else {
    console.log("Signature verification FAILED");
  }

  response.text("Hello from Hotel Agent");
});

VerifiedSender

interface VerifiedSender {
  did: string;            // Sender's DID
  signatureValid: boolean; // Ed25519 signature valid
  didResolved: boolean;    // DID document resolved
  signedAt: number;        // Timestamp from signature
}

Security Properties

Layer 1 protects against:

  • Agent impersonation — wrong key produces an invalid signature
  • Replay attacks — 5-minute timestamp window
  • Message tampering — parts digest is signed

API Reference

computePartsDigest()

Compute a SHA-256 digest of message parts for signing.

async function computePartsDigest(parts: unknown[]): Promise<string>

Parameters:

Parameter Type Description
parts unknown[] Message parts to digest

Returns: Promise<string> - Hex-encoded SHA-256 digest


createSenderEnvelope()

Sign an outbound message and produce a SenderIdentityEnvelope.

async function createSenderEnvelope(
  messageId: string,
  partsDigest: string,
  identity: AgentSigningIdentity
): Promise<SenderIdentityEnvelope>

Parameters:

Parameter Type Description
messageId string Unique message identifier
partsDigest string SHA-256 digest of message parts
identity AgentSigningIdentity Agent’s DID and private key

Returns: Promise<SenderIdentityEnvelope>


extractSenderEnvelope()

Extract a SenderIdentityEnvelope from A2A message metadata.

function extractSenderEnvelope(
  metadata?: Record<string, unknown> | null
): SenderIdentityEnvelope | null

Parameters:

Parameter Type Description
metadata Record<string, unknown> \| null Message metadata

Returns: SenderIdentityEnvelope | null


verifySenderEnvelope()

Verify a SenderIdentityEnvelope from an inbound message.

async function verifySenderEnvelope(
  envelope: SenderIdentityEnvelope,
  partsDigest: string,
  options?: { maxMessageAge?: number }
): Promise<VerifiedSender>

Parameters:

Parameter Type Description
envelope SenderIdentityEnvelope The envelope to verify
partsDigest string Expected parts digest
options.maxMessageAge number Maximum message age in ms (default: 300000)

Returns: Promise<VerifiedSender>


getVerifiedSender()

Retrieve the verified sender identity for a request context.

function getVerifiedSender(context: object): VerifiedSender | undefined

Parameters:

Parameter Type Description
context object Agent context from handler

Returns: VerifiedSender | undefined


This site uses Just the Docs, a documentation theme for Jekyll.