Agent identity
Every ProofLedger agent has a registered identity — name, owner, framework, model, version — and an Ed25519 keypair. The agent signs each event with its private key; the server verifies against the registered public key. A forged or altered event fails verification and is blocked by default policy.
Registering an agent
const result = await ProofLedger.registerAgent({
agentId: "support-agent", // stable id used everywhere
name: "Support Agent",
owner: "customer-success",
framework: "langchain",
model: "gpt-4.1",
version: "1.0.0",
});
// The keypair is generated IN THIS PROCESS; only the public key is sent.
// result.privateKey is returned once so you can persist it in your secret
// manager. The SDK holds it in memory and signs events automatically.Registration is idempotent when you pass the saved key back (registerAgent({ privateKey }) / register_agent(private_key=…)): metadata updates and the identity stays the same. Once an agent has a key, ProofLedger refuses to replace it from a project API key alone. Registering with a different key returns 409 key_rotation_requires_proof, and PATCH /api/agents/:id cannot change publicKey or status. Otherwise anyone holding the API key could impersonate the agent.
Security
Identity across restarts
// First boot: register and persist the private key.
const { privateKey } = await ProofLedger.registerAgent();
await secrets.put("support-agent-key", privateKey);
// Every boot after: re-register with the SAME key (idempotent)...
await ProofLedger.registerAgent({ privateKey: await secrets.get("support-agent-key") });
// ...or just re-attach the identity without a network call:
ProofLedger.identifyAgent("support-agent", await secrets.get("support-agent-key"));How signing works
For each event, the SDK signs the canonical JSON of { eventId, agentId, eventType, action, timestamp } with the agent's Ed25519 private key. The server recomputes the same canonical body and verifies. The result is stored on the event (signatureValid) and shown as a ✓ signed badge on the timeline. Signatures are byte-compatible between the TypeScript and Python SDKs.
// Verify a signature yourself — offline, no API call:
import { verifyEvent } from "@proofledger/sdk";
const ok = verifyEvent(publicKey, {
eventId: "evt_…",
agentId: "support-agent",
eventType: "decision",
action: "Refund approved under policy",
timestamp: "2026-07-02T18:00:00.000Z",
}, signature);Lifecycle & statuses
Agents move through active · warning · blocked · inactive · pending_approval. Unknown agents that send events are quarantined as pending_approval and raise an unknown_agent security event. Scores below 50 escalate to warning; below 30, blocked — and blocked agents fail policy for every privileged action. Operators manage status from the agent detail page or POST /api/agents/:id/block.
Agent-to-agent messages
// Signed messages between agents, verified server-side:
const { verified } = await ProofLedger.sendAgentMessage({
fromAgent: "support-agent",
toAgent: "billing-agent",
content: { task: "refund ORD-123", amount: 49 },
privateKey: supportAgentKey,
});
// verified === true only if the signature matches the sender's registered key