Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Reckoner

An onchain agent that verifies its own execution against the chain.

Built for the KeeperHub Agents Onchain Hackathon.

cd agent && pnpm install && pnpm demo

The Reckoner dashboard — 69 executions drawn as a bar field, the one divergent execution a lone amber column in a wall of teal; tally reads 69 executions, 57 confirmed, 1 divergent, 11 undetermined


The problem

On 2026-07-27 this agent executed a transaction through KeeperHub. It succeeded: Sepolia block 11362630, status 1, gas sponsored, zero retries.

Our integration reported failure. Thirty status polls, thirty 404s, then no transaction hash yet — while the transaction sat mined on the chain.

Three traps, all in one execution:

  • the response field is executionId, not id
  • direct executions and workflow executions use different status endpoints; the wrong one 404s silently
  • the transaction is a meta-transactionfrom is a relayer, to is a forwarder, and the agent's wallet appears only inside the calldata

None of these are KeeperHub failing. All of them produce an agent that is confidently wrong about what it just did.

An agent can execute onchain far more reliably than it can tell you whether it did. Reckoner closes that gap.

The claim, stated narrowly

KeeperHub's submission layer is trustworthy. The gap is on the integration side.

We tried to disprove that and failed. Attempting to induce a false positive — a USDC transferFrom with no allowance — KeeperHub simulated it, returned ERC20: transfer amount exceeds allowance, and refused to broadcast. No transaction, no hash, nothing mined.

So false-positive and phantom remain defence-in-depth for execution layers that don't simulate, and are labelled SYNTHETIC in the demo. Everything claimed as live is live.

How it verifies

Every chain read goes to a public RPC with no relationship to KeeperHub. Asking the system that just told you an execution succeeded whether it succeeded is not verification — it is repetition.

Verdict Meaning Evidence
confirmed Reported success, chain agrees, attributable live
false-negative Reported failure — the chain says it succeeded live
unverifiable No hash to check. Reported honestly, not assumed good live
unattributable Succeeded onchain, but nothing ties it to this agent synthetic
phantom Reported success — no onchain record exists, either because the hash is unknown to the chain or because no transaction was ever produced synthetic
false-positive Reported success — the chain says it reverted synthetic
pending Not mined yet. Early, not wrong synthetic

A green run that never ran

Eienel raised the inverse of our own case (#1): on KeeperHub an action node missing actionType is accepted at creation, silently skipped at execution, and the run reports status: success with the node absent from executionTrace. A green run for an automation that never ran. The incentive is backwards, too — adding actionType makes creation reject you for a missing abi, so the less complete definition is the one that passes and does nothing.

Reckoner did not catch it. Any record without a transaction hash returned unverifiable regardless of what had been claimed, and unverifiable is not a divergence — so a run claiming success while never touching the chain rendered as a grey "undetermined", excluded from the divergence rate and indistinguishable from an honest "nothing to check".

It is a phantom now: reported success, no transaction ever produced. A reported failure with no hash is still unverifiable, because that is coherent — nothing was claimed and nothing happened.

Attribution is the hard part

KeeperHub sponsors gas by relaying. A relayer pays, a forwarder contract is the to, and the agent's wallet appears only as a calldata parameter. The obvious check — is receipt.from my agent? — answers no for a transaction the agent absolutely caused.

A verifier that gets this wrong marks every sponsored execution unattributable, which is worse than having no verifier. Reckoner attributes three ways: direct-sender, relayed-calldata, relayed-logs. Every sponsored execution in the record resolves via calldata.

Verified executions

What Tx Verdict
First execution — dust self-transfer 0x34d520a8…4428 false-negative caught — succeeded in block 11362630
Control — dust self-transfer 0x3e5aec78…2718 confirmed, block 11363031, 47,693 gas
Induced failure — USDC transferFrom, no allowance refused before broadcast

Full record in tx-log.md.

69 executions in total, 58 with a transaction hash and 11 refused before broadcast. A verification tool means nothing at n=1: the signal is the divergence rate (1.7% of 58 verifiable), the verdict mix, and the attribution mix across a population. Gas is sponsored, so volume costs nothing but time — DRY_RUN=0 pnpm populate --execute --count 45 produces more.

Guardrails

The model proposes; policy.ts disposes. It is short enough to read before trusting the agent: address validation, amount validation, per-action ceiling. Nothing reaches the chain without passing it.

Two reasoning layers sit behind one enforcement point — the Anthropic API, and Claude Code headless (which costs no API credits). Claude Code has the KeeperHub MCP server configured, so a careless invocation could call execution tools directly and skip the gate; the CLI brain is therefore restricted to read-only tools and must return a structured proposal. Reasoning is delegated; authority is not.

Repo

Path What
agent/ The agent. See agent/README.md for internals.
agent/src/reconcile/ Ground truth and verdict logic.
web/ The dashboard. Next.js 16, reads the same record the agent writes.
tx-log.md Every execution, with explorer links.
friction-log.md Onboarding friction, logged as it happened.
BOUNTY.md Eight findings, submitted for the onboarding bounty.
docs/DEMO.md Shot list for the demo video.

The dashboard

A dark operator UI — the scene is an engineer opening this after an unattended run, usually because something looks off. Its signature element is the execution field: one column per execution, in submission order, each column's bars drawn from that execution's transaction hash, hex digit by hex digit. Verdict sets how it reads — confirmed full-height in teal, undetermined at 40% height in indigo so a gap in knowledge is drawn as a gap, and the one execution where report and chain disagree in amber.

Colour encodes verdict and nothing else. Navigation, links and headings stay neutral, so a hue on this page always means a state — and amber is reserved for divergence, the only state allowed to fill a region. A palette where the alarm colour also decorates the header cannot raise an alarm, and a Playwright spec enforces it.

The palette is computed rather than eyeballed: worst-pair ΔE 14.8 under simulated protanopia and 21.0 under normal vision, against a hard floor of 15. The first cut scored 13.0 and had to be re-stepped.

cd web && pnpm install && pnpm dev     # http://localhost:3000
pnpm exec playwright test              # 19 specs: axe, layout, palette, reconciliation

Measured on the production build, throttled mobile (4× CPU, Slow 4G): LCP 0.9–1.2 s, CLS 0.00, Lighthouse accessibility 100 / best-practices 100 / SEO 100 — 52 audits passed, 0 failed. Runtime dependencies are next, react, react-dom and nothing else.

Run it

cd agent
pnpm install
cp .env.example .env      # add your kh_ organization key
pnpm verify               # pre-flight: key, wallet funding, chain, brain
pnpm demo                 # reconciliations against live chain data
pnpm loop:once            # one reckoning cycle

DRY_RUN=1 and BRAIN=cli are the defaults: no transactions submitted, no API credits spent.

About

An onchain agent that verifies its own execution against the chain — catching integration errors that report failure on success

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages