Skip to main content
Version: v0.10.13

OpenClaw Capture

The OpenClaw adapter provides a one-call setup for capturing interaction evidence. It combines the capture pipeline -- spool store, deduplication index, export, and query -- into a single activate() call.


Install

Terminal
pnpm add @peac/adapter-openclaw @peac/capture-core @peac/capture-node

Quick start

capture.ts
import { activate } from '@peac/adapter-openclaw';

const claw = await activate({
privateKey: process.env.PEAC_PRIVATE_KEY,
kid: 'peac-2026-02',
issuer: 'https://api.example.com',
});

// Capture an interaction
await claw.capture({
type: 'api.request',
subject: 'user:agent-123',
status: 'executed',
metadata: {
path: '/api/data',
method: 'GET',
statusCode: 200,
},
});
activate() handles all the setup

A single activate() call configures Ed25519 signing, spool store buffering, deduplication indexing, and the export pipeline. No manual wiring required.


Key generation

Generate an Ed25519 keypair for receipt signing:

Terminal
npx peac-keygen
Output
Private key (keep secret):
<base64url-encoded-private-key>

Public key (publish at .well-known/peac-issuer.json):
{
"kty": "OKP",
"crv": "Ed25519",
"use": "sig",
"kid": "peac-2026-02",
"x": "<base64url-encoded-public-key>",
"alg": "EdDSA"
}

Set the private key as PEAC_PRIVATE_KEY in your environment. Publish the public key JSON at your issuer's /.well-known/peac-issuer.json endpoint.


Capture stores

In-memory

Testing only

In-memory stores do not survive process restarts. Use file-system stores for production workloads.

memory-stores.ts
import { MemorySpoolStore, MemoryDedupeIndex } from '@peac/capture-core';

const store = new MemorySpoolStore();
const index = new MemoryDedupeIndex();

File-system

fs-stores.ts
import { FileSpoolStore, FileDedupeIndex } from '@peac/capture-node';

const store = new FileSpoolStore({ dir: './spool' });
const index = new FileDedupeIndex({ path: './dedupe.json' });

File-system stores provide:

  • Durable persistence -- survives process restarts and deployments
  • Atomic writes -- no partial writes on crash or power loss
  • Deduplication -- prevents duplicate captures for the same interaction

Pass custom stores to activate() via the spoolStore and dedupeIndex options.


Export

Export captured receipts as an evidence bundle (.peac.tar.gz):

export.ts
const result = await claw.export({
output: './evidence.peac.tar.gz',
since: new Date('2026-02-01'),
});

console.log(result.counters);
Structured counters
{ "scanned": 150, "exported": 148, "skipped": 2 }

The structured counters give you a precise breakdown: how many receipts were scanned from the spool, how many made it into the bundle, and how many were skipped (duplicates or invalid).


Query

Query the capture store for receipts matching specific criteria:

query.ts
const receipts = await claw.query({
since: new Date('2026-02-19'),
type: 'api.request',
limit: 100,
});

console.log(receipts.counters);
// { scanned: 500, exported: 100, skipped: 0 }

Configuration

Required options

OptionTypeDescription
privateKeystringEd25519 private key (base64url or hex encoded)
kidstringKey ID -- must match your published JWKS
issuerstringIssuer URL (becomes the iss claim)

Optional options

OptionTypeDefaultDescription
spoolStoreSpoolStoreMemorySpoolStoreCustom spool store for receipt buffering
dedupeIndexDedupeIndexMemoryDedupeIndexCustom deduplication index
attestationTypestring'interaction'Default attestation type for captures

Next steps