Identity & Verification

Learn how to work with Decentralized Identifiers (DIDs), generate Ed25519 key pairs, and sign/verify agent messages.


Overview

Aletheia uses DIDs for agent identity. The SDK supports:

DID Method Resolution Example
did:web Fetches /.well-known/did.json from the domain did:web:my-agent.example.com
did:key Derives DID Document from the public key itself did:key:z6Mk...

Resolving DIDs

Using AletheiaClient

import { AletheiaClient } from "@a2aletheia/sdk";

const aletheia = new AletheiaClient();

const didDocument = await aletheia.resolveDID("did:web:example.com");
console.log(didDocument.id);
console.log(didDocument.verificationMethod);

Using DIDResolver Directly

import { DIDResolver } from "@a2aletheia/sdk";

const resolver = new DIDResolver();

// Resolve did:web (fetches https://example.com/.well-known/did.json)
const webDoc = await resolver.resolve("did:web:example.com");

// Resolve did:key (constructs document from public key)
const keyDoc = await resolver.resolve("did:key:z6Mk...");

DID Document Structure

A resolved DID Document contains:

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  id: "did:web:example.com",
  verificationMethod: [
    {
      id: "did:web:example.com#key-1",
      type: "Ed25519VerificationKey2020",
      controller: "did:web:example.com",
      publicKeyMultibase: "z6Mk..."
    }
  ],
  authentication: ["did:web:example.com#key-1"],
  service: [
    {
      id: "#a2a",
      type: "A2AAgent",
      serviceEndpoint: "https://example.com"
    }
  ]
}

Key Pair Generation

Generate an Ed25519 key pair for agent message signing:

import { generateAgentKeyPair } from "@a2aletheia/sdk";

const keys = await generateAgentKeyPair();

console.log(keys.privateKey);          // Hex-encoded private key (keep secret!)
console.log(keys.publicKey);           // Hex-encoded public key
console.log(keys.publicKeyMultibase);  // Multibase-encoded (for DID documents)
console.log(keys.didKey);              // did:key:z6Mk... identifier

Using with AletheiaAgent

When building an agent with AletheiaAgent, you have two options:

Option 1: Auto-generated did:key (Development)

import { AletheiaAgent } from "@a2aletheia/sdk/agent";

// No keys needed - agent generates them on startup
const agent = new AletheiaAgent({
  name: "DevAgent",
  version: "1.0.0",
  url: "http://localhost:4000",
  description: "Development agent",
  skills: [...],
});
// Agent gets a new did:key each restart

Option 2: Persistent did:web (Production)

import { AletheiaAgent } from "@a2aletheia/sdk/agent";
import { generateAgentKeyPair } from "@a2aletheia/sdk";

// Generate once, store securely
const keys = await generateAgentKeyPair();

const agent = new AletheiaAgent({
  name: "ProductionAgent",
  version: "1.0.0",
  url: "https://my-agent.example.com",
  description: "Production agent",
  skills: [...],
  aletheiaExtensions: {
    did: "did:web:my-agent.example.com",
    publicKeyMultibase: keys.publicKeyMultibase,
  },
});
// Agent serves /.well-known/did.json with your public key

Key Storage

Important: Store the private key securely. Never commit it to source control or expose it in client-side code.

The publicKeyMultibase value is what you publish in your DID Document’s verificationMethod.


Message Signing

Sign arbitrary payloads with Ed25519 to prove your agent’s identity:

import { signAgentMessage } from "@a2aletheia/sdk";

const signedMessage = await signAgentMessage(
  { action: "book", hotelId: "123", date: "2025-03-15" },
  keys.privateKey,
  keys.didKey // or "did:web:your-agent.com"
);

// signedMessage contains:
// {
//   payload: { action: "book", hotelId: "123", date: "2025-03-15" },
//   signature: "base64-encoded-signature",
//   signer: "did:key:z6Mk...",
//   timestamp: "2025-01-15T10:30:00.000Z"
// }

The signed message includes a timestamp for replay protection.


Message Verification

Method 1: Verify with Public Key

If you already have the signer’s public key:

import { verifyAgentSignature } from "@a2aletheia/sdk";

const isValid = await verifyAgentSignature(signedMessage, publicKeyHex);
console.log(isValid); // true or false

Automatically resolves the signer’s DID and verifies against their published public key:

// Using AletheiaClient (recommended)
const result = await aletheia.verifyAgentMessage(signedMessage);

if (result.valid) {
  console.log(`Verified message from ${result.didDocument?.id}`);
} else {
  console.log(`Verification failed: ${result.error}`);
}
// Or using the low-level function
import { verifyAgentMessageWithDID } from "@a2aletheia/sdk";

const didDocument = await aletheia.resolveDID(signedMessage.signer);
const isValid = await verifyAgentMessageWithDID(signedMessage, didDocument);

End-to-End Example

Complete flow: generating keys, publishing identity, signing messages, and verifying.

Step 1: Agent Setup (One-Time)

import { generateAgentKeyPair } from "@a2aletheia/sdk";

// Generate keys (do this once, store securely)
const keys = await generateAgentKeyPair();

Step 2: Publish DID Document

Host this at https://your-agent.com/.well-known/did.json:

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:web:your-agent.com",
  "verificationMethod": [
    {
      "id": "did:web:your-agent.com#key-1",
      "type": "Ed25519VerificationKey2020",
      "controller": "did:web:your-agent.com",
      "publicKeyMultibase": "<keys.publicKeyMultibase>"
    }
  ],
  "authentication": ["did:web:your-agent.com#key-1"]
}

Step 3: Sign Outgoing Messages

import { signAgentMessage } from "@a2aletheia/sdk";

const signedResponse = await signAgentMessage(
  { result: "booking confirmed", confirmationId: "ABC123" },
  keys.privateKey,
  "did:web:your-agent.com"
);

// Send signedResponse to the requesting agent

Step 4: Verify Incoming Messages

import { AletheiaClient } from "@a2aletheia/sdk";

const aletheia = new AletheiaClient();

const verification = await aletheia.verifyAgentMessage(signedResponse);

if (!verification.valid) {
  throw new Error("Message not from the claimed agent!");
}

// Trusted: this message really came from did:web:your-agent.com
console.log("Verified response:", signedResponse.payload);

Fetching Agent Manifests

The manifest (Agent Card) is the A2A-compliant description of an agent’s capabilities:

// Fetches https://my-agent.example.com/.well-known/agent-card.json
const manifest = await aletheia.fetchManifest("https://my-agent.example.com");

// Or from an arbitrary URL
const manifest = await aletheia.fetchManifestFromUrl(
  "https://cdn.example.com/agents/manifest.json"
);

The manifest includes the agent’s name, description, skills, supported capabilities, and Aletheia-specific extensions.


Next Steps


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