Skip to content
v0.11.2Since v0.10.7

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

activate.tsTypeScript
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:

ToolDescription
peac_receipts.statusReturn capture session state: entry count, latest digest, spool health
peac_receipts.export_bundleExport all receipts as a verifiable evidence bundle
peac_receipts.verifyVerify a receipt or bundle against issuer JWKS
peac_receipts.queryQuery 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.

FieldDescription
tool.nameName of the tool that was called
timing.started_atISO 8601 timestamp when the tool call began
timing.completed_atISO 8601 timestamp when the tool call completed
statusOutcome of the call (ok or error)
input.digestSHA-256 of serialized input payload
output.digestSHA-256 of serialized output payload
prev_entry_digestSHA-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

Terminal
# 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

emitter.tsTypeScript
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.