A separate product
A signed, hash-chained evidence ledger for OpenClaw. It records what agents did on a runtime we do not build and do not control.
This is not the Hexr platform.
Everything else on this console rests on a per-process SPIFFE identity: each agent process holds its own X509-SVID, and a row can name which process acted. HexrClaw has none of that. It is a plugin, it holds one signing key on the Gateway host, and its strongest claim is that silent edits and deletions become detectable. That is a real raise in cost and it is not attestation. Both products are listed here because the difference is the point.
OpenClaw already keeps an audit ledger, and a good one. Its own documentation is also unusually honest about what it is not, and those sentences are the whole product case:
Absence of a row proves nothing. […] queue saturation, storage failure, or a bounded shutdown timeout can drop records
Queries never return records older than 30 days, and the ledger is capped at 100,000 rows
It is not a lossless compliance archive; if you need one, use an external system
So HexrClaw adds four things and claims nothing else: a hash chain whose sequence number sits inside each row’s own hash, so a deleted row becomes a detected gap rather than an absence; an Ed25519 signature per row; retention of seven years by default that records where it cut; and coverage accounting rather than a row count.
A real Gateway, openclaw 2026.9.9 (bcfc888), started on an ephemeral port with the plugin installed from a packed tarball. Verbatim from its startup log:
[gateway] http server listening (16 plugins: anthropic, bonjour, browser, canvas, cua-computer, device-pair, file-transfer, geolocation, github, hexr-claw, linux-node, memory-core, ollama, openai, talk-voice, xai; 2.4s)
hexr-claw is in the host’s own list of loaded plugins. And from plugins inspect:
{
"status": "loaded",
"activated": true,
"hookCount": 12,
"commands": [
"hexr-claw"
],
"cliCommands": [
"hexr-claw"
]
}Twelve hooks bound and the command registered on both the chat and CLI surfaces.
The ledger below came from that same kind of Gateway run: one run, nothing stitched together. It contains the Gateway lifecycle, the session, the parent agent run, its tool calls, a subagent spawn and end, and the parent resuming afterwards.
The ledger below is a real governed agent run: 38 rows from the claims-appeal agent on deepseek/deepseek-v4-pro, captured 2026-10-11. Your browser recomputes every hash from the row fields using the same length-prefixed canonical encoding the plugin uses, and checks each signature with Web Crypto against the public key the capture shipped with. Nothing is taken on trust from us.
Edit a field or delete a row and watch what happens. Then read what does not break.
| seq | event | decision | tool | chain | sig |
|---|
Pick any row and press tamper to edit a field or delete it, then watch the chain above.
A US provider gets a claim denied. Someone must read the denial, read the payer’s own medical policy, decide whether it is appealable, and draft the appeal before the 90-day deadline. High volume, deadline-bound, and exactly the work an agent is good at.
It is also work nobody lets an agent do unsupervised, for three reasons that have nothing to do with how good the model is. The case contains PHI, so an agent with a web tool is an exfiltration path. The appeal is a legal assertion to a payer, so an invented citation creates liability rather than saving work. And when a regulator asks what happened, “the agent did it” is not an answer.
HexrClaw does not make the model better. It makes the third problem solvable and the first two enforceable.
The oldest control in financial operations: whoever prepares a transaction never approves it. It transfers to agents cleanly.
┌────────────────────────────────────┐
case files ──► │ MAKER (the agent) │
payer policy │ reads case, reasons, drafts appeal │
└───────────────┬─────────────────┘
│ write ./case/appeal-draft.md
▼
┌────────────────────────────────────┐
│ CHECKER (a person) │
│ approves, refuses, or lets it time │
│ out — and the answer is attested │
└────────────────────────────────────┘
refused outright, with no route around it:
exec, apply_patch no shell on a host holding PHI
web_fetch, web_search PHI must not leave
anything else the policy defaults to deny| The question | The evidence |
|---|---|
| Which agent, in which session? | session_open, plus agent and session on every row |
| Under what instructions? | promptHash — the SHA-256 of the system prompt, never its text — carried on every tool call in the session |
| What was refused, and by which rule? | a deny row with the rule’s own words and that policy’s hash |
| Who approved the sensitive action? | tool_approval_resolved, recording allow-once, deny or timeout as themselves |
| Is the record complete and unaltered? | the chain above, and coverage rather than a row count |
The fourth row is the one worth dwelling on. A timeout is recorded as a timeout, not as a denial. Both stop the write, and an auditor asking why needs to see whether somebody refused or nobody answered.
This run really happened.
The 38 rows you can verify above came from this agent, on deepseek/deepseek-v4-pro, under the enforcing claims-appeal-2026-10 policy, as an a Gateway run (openclaw agent, isolated Gateway on a pinned port). Every hash and signature is the one that run wrote. What the agent produced was a real appeal: it cited the payer’s own §3.1–3.4 with the matching record dates, marked the fields the case file did not contain as MISSING rather than inventing them, and added a note of its own that the 90-day appeal window had already closed.
agent_run_start carries a real promptHash, and every tool-call row in that run carries the same one. That is the answer to “under what instructions?”, and the prompt text appears nowhere in the store.subagent_spawned, recording both the parent session and the child. The execution graph is reconstructable from the chain rather than guessed from timestamps. A signed receipt cannot produce this row, because a receipt format has no vantage point from which to see one agent create another.agent_run_start, with a different promptHash. The delegated work ran under different instructions, and the chain says which instructions governed which part of it. That is the question an auditor actually asks about delegation.An earlier run of this same agent is worth mentioning because it failed. The policy allowed read but not ls, so the agent could not list the case directory; it spent the whole turn guessing filenames and timed out after 85 failed reads. Nobody had to debug that from logs. The chain showed two deny rows naming the rule, then the flood of reads. The evidence diagnosed the misconfiguration, which is the same job it does when the misconfiguration is yours.
The deny row is the one to show a buyer. It is not a log line saying something was blocked. It names the rule, carries that rule’s hash so the decision can be re-checked against the policy in force at the time, and sits inside a chain where removing it is detectable.
The same three reports an auditor would run. verify exits non-zero when the ledger does not verify, so it works as a cron check or a CI gate.
$ openclaw hexr-claw verify Ledger verifies. rows checked: 2 chain: intact from genesis signatures: 2 valid, 0 invalid, 0 unsigned $ openclaw hexr-claw coverage Signed 2 of 2 rows over 30 days: 100% unsigned with a recorded reason: 0 unsigned with no reason at all: 0 <- the only alarming number here signature present and invalid: 0 chain: intact
The useful part of any evidence tool is the part it declines to claim.
0600 in a 0700 directory, which is the strongest statement a plugin can make and a weak one: anything running as the Gateway user can read it. An attacker who holds the host can rewrite the chain and re-sign it coherently, and nothing here would catch that.ledger_open and ledger_close rows bound that problem; they do not remove it.Every command run against the real Gateway, its verbatim output, the three defects that loading into a real host exposed, and a section listing what was not tested. Apache-2.0, no runtime dependencies.
Ledger captured 2026-10-11 from openclaw 2026.9.9 (bcfc888). Row hashes and signatures are the ones that run produced.