Before an agent spends or signs, Preflight checks what it is about to trust and blocks what fails.
Preflight is a fail-closed check for the two moments an agent with a wallet gets wrong: hiring another agent, and signing a transaction to a contract nobody has read.
Disclosed prior inputs, before any feature. This project consumes @polygraphso/litmus, an open behavioral grading engine, from npm as a plain dependency, and never reads its source. It was planned in a private prose and mockup repo. No project code existed before the event clock, and every grade on screen was produced during the event by this project's own validator, then read back from the ERC-8004 Validation Registry.
The validator grades an agent's live tool surface A to F and posts the score to a Validation Registry we deployed ourselves. ERC-8004 has a canonical Identity Registry on Base, but no Validation Registry deployment exists on any chain, so we deployed the reference contract on Base Sepolia and verified it. Two gates read from that registry and refuse by default.
vetAgent refuses any agent below the grade floor, B or above, and refuses any agent whose live tool surface no longer hashes to what was graded. Change your tools after grading and the recheck catches it.
txGuard forks the chain at the live block and simulates the exact pending call before a signature is ever requested. Four flags, a closed set: an unlimited approval to an unverified spender, a token that buys but cannot sell, value routed to an unverified callee, a hidden owner or upgrade path. Any one of them blocks.
Both ship as a TypeScript SDK and as an MCP server, so an MCP-capable agent adopts the check without code changes.
In the demo, a client agent reads the hiring floor, is refused the F-graded candidate, hires one that clears the floor, pays it per call in HBAR on Hedera Testnet, and freezes the remaining budget the moment that agent's own tool output turns hostile mid-task. The hostile agent nets one honest call's fee and nothing after it. Then txGuard blocks four staged fixtures, and blocks a contract we did not write: a documented Base mainnet drainer, pasted live. A clean verified router passes, because a gate that blocks everything is not a gate. Every decision emits an Ed25519-signed, hash-chained receipt, so a verdict can be re-derived offline instead of taken on trust.
Each graded agent is also discoverable by name. An ENS subname under the validator's name carries the grade, score, and evidence hash as text records, labelled on the name itself as a mirror of the registry and never a second source of truth.
Three limits we state rather than bury. Evasion: a target that detects the test context and behaves during the check. We validate the capability surface, not intent, and the live fingerprint recheck narrows that window without closing it. State: a per-transaction verdict is reproducible for a given block and state, not a prediction of what lands. Independence: v1 is self-run and self-minted, so reproducibility here means falsifiable, not independent. The engine is open, so anyone can re-run it and disprove a verdict.
Preflight is TypeScript throughout: a Next.js 16 console on Vercel, an SDK, and an MCP server. viem for chain reads, Foundry's anvil for forking and simulating a pending transaction, Sourcify for verified-source status. Sourcify is deliberate: verified-source status is a fact about the chain, whereas a proprietary threat score inside the verdict path would break re-derivation, which is the whole point. @polygraphso/litmus, pulled from npm and never read as source, produces the A to F letter and is the only prior code this build touches. The ERC-8004 Identity Registry is the canonical deployment on Base; the Validation Registry has no canonical deployment anywhere, so we deployed the reference ValidationRegistryUpgradeable behind an ERC1967 proxy on Base Sepolia and verified the source. Every gate decision is Ed25519-signed into a hash chain that depends on no chain at all, so a verdict can be re-derived offline.
Hedera. Beat one's agent-to-agent payment settles as a real HBAR transfer on Hedera Testnet over the Hedera x402 scheme (@x402/hedera), against a facilitator we self-host in Docker from the scaffold-hbar template. Two fixes were needed to get there: the template pins @x402/core 2.14 and @x402/hedera 2.13 while the client side needed 2.19, and the payment envelope shape changed in between; 2.19 also requires verifyPayerSignature on the facilitator signer. One more trap worth naming, since it costs an hour to find: aliasPolicy is "reject", so a hollow auto-created account cannot pay, and every demo account has to send one transaction of its own before it can be a payer. Separately, the Hedera Agent Kit mirrors each signed receipt onto a Hedera Consensus Service topic, fire and forget, as a public audit trail that witnesses a decision afterward and never gates it.
0G. Evidence bundles are pinned to 0G Storage, and we re-fetch and re-hash each bundle to confirm it still matches the hash carried in the receipt. The advisory source scanner runs its inference on 0G Compute. Advisory is architectural, not a hedge: the scanner proposes candidate findings, only a simulator-confirmed finding moves a verdict, and so a jailbroken "all clear" cannot suppress a deterministic flag. One of our fixtures instructs the scanner to report the contract clean. Running on 0G Compute, it reported the manipulation attempt instead.
ENS. Each graded agent gets a subname under the validator's name, carrying fifteen text records: the grade and score, the evidence hash, the 0G and Hedera pointers, and a URL to that agent's public grade page. The trust surface resolves from the name alone, and the console can grade an agent by name rather than by registry id. Names and records are live on Base Sepolia and writes off testnet are refused on purpose, and every record states on the name itself that it is a mirror of the registry.
Two things worth naming as hacky. First, a remote MCP server cannot grade above B under this engine, because two of the four checks (a sandboxed egress check and a planted canary) need control of the target's environment that a remote operator's server does not hand you. We show the true B on screen rather than host a target locally to manufacture an A. Second, our demo MCP server is serverless, so flipping it to a hostile tool list does not survive between requests on the same instance. Rather than stand up a database for demo state, the tool surface is named in the URL itself, so a single request is fully self-describing and needs no shared state to be trusted.

