OpenClaw Integration
Records agent tool calls as signed PEAC receipts using a two-stage capture pipeline. Each receipt contains an InteractionEvidence extension with SHA-256 digests of inputs and outputs. No raw payloads are stored.
Packages: @peac/adapter-openclaw (v0.10.7+), @peac/capture-core, @peac/capture-node (v0.10.12+).
Two-Stage Pipeline
1. Capture (sync, < 10ms)
- Map OpenClaw event to
CapturedAction - Hash input and output payloads (SHA-256)
- Append to tamper-evident spool
- Link to previous entry via
prev_entry_digest
2. Emit (async background)
- Drain spool on configurable interval
- Convert to
InteractionEvidenceV01 - Sign with Ed25519 key
- Write receipt (JWS compact serialization)
Install
pnpm add @peac/adapter-openclaw @peac/capture-core @peac/capture-node
Activate and Configure
import { createCaptureSession, createHasher } from '@peac/capture-core';
import { createInMemorySpoolStore, createInMemoryDedupeIndex } from '@peac/capture-core/testkit';
import { createHookHandler } from '@peac/adapter-openclaw';
// Configure spool backend (in-memory for development)
const session = createCaptureSession({
store: createInMemorySpoolStore(),
dedupe: createInMemoryDedupeIndex(),
hasher: createHasher(),
});
// Activate hooks
const handler = createHookHandler({
session,
config: {
platform: 'openclaw',
platform_version: '0.2.0',
},
});
// Capture a tool call
const result = await handler.afterToolCall({
tool_call_id: 'call_123',
run_id: 'run_abc',
tool_name: 'web_search',
started_at: '2026-02-01T10:00:00Z',
completed_at: '2026-02-01T10:00:01Z',
status: 'ok',
input: { query: 'example' },
output: { results: ['result1'] },
});
if (result.success) {
console.log('Captured:', result.entry.entry_digest);
}
await handler.close();Agent-Facing Tools
Four MCP tools are exposed to the agent for querying and exporting evidence:
| Tool | Description |
|---|---|
peac_receipts.status | Return capture session state: entry count, latest digest, spool health |
peac_receipts.export_bundle | Export all receipts as a verifiable evidence bundle |
peac_receipts.verify | Verify a receipt or bundle against issuer JWKS |
peac_receipts.query | Query receipts by time range, tool name, or status |
Recording Model
Each captured tool call records the following fields. Input and output are stored as SHA-256 digests only.
| Field | Description |
|---|---|
tool.name | Name of the tool that was called |
timing.started_at | ISO 8601 timestamp when the tool call began |
timing.completed_at | ISO 8601 timestamp when the tool call completed |
status | Outcome of the call (ok or error) |
input.digest | SHA-256 of serialized input payload |
output.digest | SHA-256 of serialized output payload |
prev_entry_digest | SHA-256 chain link to previous entry for tamper detection |
Spool Backends
The capture pipeline is decoupled from storage. Two spool backends are available:
Memory
In-memory spool via createInMemorySpoolStore(). Suitable for development and testing. Data is lost on process exit.
File System
Persistent spool via @peac/capture-node. Writes to a configurable directory. Survives restarts.
Export and Verify
# Export evidence bundle from spool peac bundle create --receipts ./receipts --output evidence.peacbundle # Verify bundle offline (no network) peac bundle verify evidence.peacbundle --offline # Verify a single receipt peac verify ./receipts/receipt-001.jws
Background Emitter
import { createReceiptEmitter, createBackgroundService } from '@peac/adapter-openclaw';
const emitter = createReceiptEmitter({
signer,
writer,
config: { platform: 'openclaw' },
});
const service = createBackgroundService({
emitter,
getPendingEntries: () => spoolStore.getPending(),
markEmitted: (digest) => dedupeIndex.markEmitted(digest),
drainIntervalMs: 1000,
});
service.start();
// Drains spool every 1000ms, signs and writes receipts
// On shutdown:
service.stop();Chain Integrity
Each spool entry links to the previous via prev_entry_digest. The first entry uses GENESIS_DIGEST (64 zeros, not the SHA-256 of an empty string):
0000000000000000000000000000000000000000000000000000000000000000
Replaying the same action sequence produces identical chain digests, making tamper detection deterministic.
Links
Evidence Carrier Contract
Receipts produced by the OpenClaw adapter follow the PeacEvidenceCarrier type and can be transported via MCP _meta, A2A metadata, HTTP headers, or any supported carrier format.