A policy and approval control plane for AI agents using Ledger as the final hardware signing gate.
Agents propose. Policies filter. Ledger signs.
AI agents can read invoices, summarize requests, and draft crypto operations. That is useful, but dangerous if the same agent can also move value through software secrets. Ledger Agent Firewall separates intent from authority:
- The agent extracts a structured transaction intent from an untrusted document (invoice, email thread).
- Deterministic policy checks decide whether the intent is even eligible for signing.
- Allowed intents produce an Agent Intent Receipt.
- Wallet CLI dry-run previews the transaction.
- Ledger hardware confirmation remains the final gate.
This is built for the Ledger N3XT Build & Show bounty using the Ledger Agent Stack path around Wallet CLI, with DMK left as a stretch integration.
The agent layer turns a raw document into a normalized TransactionIntent (src/lib/parser.ts):
- Deterministic parser — rule-based extraction of amount, asset, network and payout address. Zero dependency, fully tested, the reliable demo path.
- Local LLM (optional) — the same contract, backed by a model running on your machine via Ollama (no cloud, no API key). Falls back to the deterministic parser if the model is unavailable.
The firewall never trusts the extractor: whatever comes out still goes through evaluatePolicy. A poisoned "we changed our wallet" reply is extracted faithfully and then blocked by policy before it can reach the signer.
npm run extract # deterministic
npm run extract -- --llm # local Ollama model (set OLLAMA_MODEL to override)To use the local LLM in the web app, run a model (ollama run llama3.2) and toggle Local LLM in the Source panel — requests are proxied through Vite to 127.0.0.1:11434.
Run the deterministic demo:
npm install
npm run demoRun the operational console (web app):
npm run devThe console is a security dashboard: an agent request queue, the source document, the extracted intent, live policy evaluation, the Ledger signing gate, an execution timeline, and the Agent Intent Receipt. It shows three treasury scenarios:
- Approved vendor under budget: passes policy and requires Ledger confirmation.
- Unknown recipient (poisoned address): blocked before signing.
- Approved recipient over limit: blocked before signing.
Install Ledger Wallet CLI:
npm i -g @ledgerhq/wallet-cli
wallet-cli --versionConnect and unlock the Ledger, open the Ethereum app, then run the capture helper. It walks
the full path and writes every real output into proof/wallet-cli-proof.md:
npm run ledger:proof # version → account discover → balances → receive --verify → send --dry-run
npm run proof:render # regenerate the proof imageThe strongest single proof is receive --verify, which displays the receive address on the
Ledger screen for physical confirmation. Signing (send without --dry-run) always requires
that on-device confirmation; this demo never broadcasts.
Proof captured in this repository:
flowchart LR
A["User request"] --> B["Agent intent"]
B --> C["Policy firewall"]
C -->|Blocked| D["Receipt: blocked"]
C -->|Allowed| E["Wallet CLI dry-run"]
E --> F["Ledger confirmation"]
F --> G["Receipt: signed or rejected"]
- This demo does not provide financial advice.
- The app does not autonomously broadcast transactions.
- Blocked requests never reach the signing gate.
- Approved requests still require Ledger hardware confirmation.
- Public X or LinkedIn post tags
@Ledger. - Public post includes
#Sponsoredor#LedgerSponsor. - Form component selection:
Wallet CLIfor the MVP,Bothonly if DMK is added. - Proof link: GitHub repo plus Wallet CLI screenshot or screen recording.
- Repo link: this repository.