Skip to main content
Version: v0.16.4

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-03',
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/cli 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-03",
"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 { createInMemorySpoolStore, createInMemoryDedupeIndex } from '@peac/capture-core/testkit';

const store = createInMemorySpoolStore();
const index = createInMemoryDedupeIndex();

File-system​

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

const store = await createFsSpoolStore({ filePath: './spool.jsonl' });
const index = await createFsDedupeIndex({ filePath: './dedupe.idx' });

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
spoolStoreSpoolStoreInMemorySpoolStoreCustom spool store for receipt buffering
dedupeIndexDedupeIndexInMemoryDedupeIndexCustom deduplication index
attestationTypestring'interaction'Default attestation type for captures

Next steps​