Your grandma sends a WhatsApp voice note and it's handled, she never knows it's crypto. A bounded MetaMask delegation + x402 + Venice AI let an agent spend safely, scam-screened. Invisible crypto.
# Guardian
> **Let anyone — your grandma included — use crypto without ever knowing it's crypto.**
Send a WhatsApp text, voice note, or photo. A bounded AI agent pays for it on-chain — within hard limits, screened for scams. No wallet, no seed phrase, no jargon, for the person using it *or anyone watching*.
---
## The problem
**Wallets are unusable for normal people.** Seed phrases, gas, approvals — a non-technical person (let alone an elderly or low-vision one) shouldn't have to learn any of it. A message, a voice note, or a photo of a bill is all they should need.
**Agents with money are unsafe.** Give an AI agent a private key and it can be drained, prompt-injected, or socially-engineered into paying a scammer.
**Doing it for them doesn't scale.** Every payment shouldn't require the person who set it up to be online and approve it.
---
## How it works
**1 · Setup, once.** A guardian connects a wallet and grants a scoped, on-chain budget with the **MetaMask Smart Accounts Kit** (ERC-7715) — a periodic USDC cap with per-transaction, merchant, and expiry limits. The friendly UI controls *are* the on-chain caveats.
**2 · The ward messages** a WhatsApp contact — text, a voice note, or a photo of a bill.
**3 · Venice AI understands it** — transcribes the voice, reads the bill, classifies intent, and runs a fixed scam/anomaly rubric (injection-resistant; the message is treated as data, never instructions).
**4 · Bound check.** In bounds → pay. Out of bounds or scam-flagged → refuse and alert the guardian.
**5 · Pay.** An **x402** request is satisfied by redeeming the **ERC-7710** delegation, relayed through the **1Shot** relayer on **Base** (gas paid in USDC). Out-of-scope redemptions revert on-chain.
**6 · Reply.** A plain-language confirmation with the budget left — by text or a spoken voice note (Venice TTS). No address, no hash, no "USDC".
---
## Why it's safe
- **Hard on-chain boundary** — bounds are delegation caveats; out-of-scope spends revert.
- **Soft vs. hard refusals** — the guardian can override policy, but never the on-chain cap.
- **Real scam screening** — a fixed rubric on every request, not vibes.
- **No key exposure** — the agent never holds the guardian's key.
- **Invisible crypto** — the ward only ever sees plain language and `$` amounts.
---
## What we built — and where to check it
**x402 + ERC-7710**
An x402-gated storefront returns a `402` satisfied by redeeming the guardian's ERC-7710 delegation.
- `server/src/seller/server.ts` — x402 server + `x402ExactEvmErc7710ServerScheme`- `server/src/buyer/pay.ts` — agent pays via `x402Erc7710Client`- `server/src/seller/oneshotFacilitator.ts` — decodes + settles the redemption
**Bounded agent + MetaMask Smart Accounts**
The grant is the main-flow setup; every action is gated by the delegation's caveats.
- `web/lib/chain.ts` — ERC-7715 `requestExecutionPermissions`- `server/src/agent/handle.ts` — the agent loop
- `server/src/bounds/check.ts` — off-chain bound enforcement
**Venice AI**
Voice → text, bill photo → intent, intent + scam rubric, spoken reply.
- `server/src/venice/{transcribe,vision,reason,tts}.ts`- `server/src/agent/scamRubric.ts`
**1Shot relayer**
Relays the 7710 redemption, gas paid in USDC.
- `server/src/oneshot/relayer.ts` → used by `server/src/seller/oneshotFacilitator.ts`
---
## Tech stack
MetaMask Smart Accounts Kit (ERC-7715 → ERC-7710) · x402 · Venice AI (ASR · vision · reasoning · TTS) · 1Shot relayer · Base · USDC · Twilio WhatsApp · Next.js · Node + TypeScript
---<pre><code class="language-markdown">Our progress building Guardian during the hackathon, and the real friction we hit along the way (the kind of thing worth reporting back to the sponsors). --- <span class="hljs-section">## Build journey</span> <span class="hljs-strong">**1 · On-chain lifecycle first.**</span> Before any WhatsApp or AI, we stood up the core: a guardian grants a scoped delegation → the agent redeems it → USDC moves → relayed via 1Shot → confirmed. We proved the bound holds first — an out-of-scope redemption <span class="hljs-emphasis">*reverts*</span> on-chain (<span class="hljs-code">`ERC20PeriodTransferEnforcer`</span>). Everything else depends on this working. <span class="hljs-strong">**2 · x402 + ERC-7710 + 1Shot, end to end.**</span> We made the x402 payment <span class="hljs-emphasis">*be*</span> a 7710 delegation redemption. This took a custom x402 facilitator (see Feedback) and was verified with a real on-chain settlement before we built on it. <span class="hljs-strong">**3 · The grant flow (ERC-7715).**</span> We moved the guardian grant to MetaMask's ERC-7715 <span class="hljs-code">`requestExecutionPermissions`</span> — the friendly UI controls compile straight to on-chain caveats. <span class="hljs-strong">**4 · Venice as the intelligence.**</span> Wired ASR (voice → text), vision (bill photo → intent), and reasoning (intent + a fixed scam rubric). Later added a price-vs-buy classifier (a "how much is X?" question shouldn't trigger a purchase) and <span class="hljs-strong">**TTS**</span> so the agent speaks its reply back — Venice now handles the ward's voice both ways. <span class="hljs-strong">**5 · The WhatsApp loop.**</span> Twilio's inbound webhook times out at ~15s, but an on-chain settlement can take longer — so we answer instantly and run the work on a <span class="hljs-strong">**per-ward queue**</span>, sending the real result via the outbound API. Greetings get an intro; everything else is an action. <span class="hljs-strong">**6 · Bounds, budget & safety.**</span> Off-chain mirror of the caveats (cap · per-tx · merchant · budget), budget awareness ("how much do I have left?"), remaining-budget in every confirmation, and the two first-class refusal paths (out-of-bounds, scam-flagged) with guardian escalation. <span class="hljs-strong">**7 · Guardian dashboard.**</span> Plain-language bounds editor (→ caveats), per-guardian isolation, the MetaMask grant on screen, activity feed, alerts with approve/override, and a 24h Twilio service-window handler. <span class="hljs-strong">**Decisions & pivots.**</span> We settle merchant payments by <span class="hljs-emphasis">*direct*</span> delegation redemption (no operating wallet), pay Venice via API key for simplicity, and enforce the <span class="hljs-strong">**merchant whitelist off-chain**</span> because the on-chain merchant lock isn't feasible alongside the 1Shot fee (see Feedback). The amount cap remains the hard on-chain wall. We also built and verified a 7702-upgrade + signed-webhook path, then set it aside to keep the core tight. </code></pre><p><br></p><pre><code class="language-markdown"><span class="hljs-section">## Feedback</span> A few rough edges that cost us real debugging time, in case it's useful. <span class="hljs-section">### MetaMask Smart Accounts Kit / ERC-7715</span> A dApp can't sign a delegation for a MetaMask-managed account. <span class="hljs-code">`smartAccount.signDelegation(...)`</span> fails with <span class="hljs-code">`External signature requests cannot sign delegations for internal accounts`</span>. A local key signer works, but the extension refuses, and nothing points you to <span class="hljs-code">`requestExecutionPermissions`</span> as the way around it — the error could say that. It's the same story with EIP-7702: the extension won't sign a 7702 authorization for a managed account on a dApp's behalf, even when the target is MetaMask's own <span class="hljs-code">`7702StatelessDelegator`</span> implementation. So upgrading an account to a smart account on the fly only works for a key you actually hold, never the user's MetaMask account — which rules out the wallet-driven 7702 path most relayers expect. ERC-20 periodic permissions only allow a single <span class="hljs-code">`payee`</span>. That breaks any relayer whose fee is a separate transfer: <span class="hljs-code">`payee=[merchant]`</span> reverts the fee with <span class="hljs-code">`AllowedCalldataEnforcer:invalid-calldata`</span>, and <span class="hljs-code">`payee=[merchant, feeCollector]`</span> is rejected outright (<span class="hljs-code">`Multiple payee addresses are not currently supported for ERC20 permissions`</span>). We had to drop the on-chain merchant lock and enforce it off-chain. The hosted x402 facilitator only accepts a <span class="hljs-code">`Stateless7702`</span> buyer — a Hybrid smart account gets <span class="hljs-code">`invalid_exact_evm_erc7710_account_not_delegated`</span>, which isn't obvious from the error. Documenting which facilitator expects which account type would help. <span class="hljs-section">### Venice AI</span> The TTS example voice didn't exist for the model we used. The real voices are listed under <span class="hljs-code">`/models`</span>, but the doc example didn't match, so it took a while to spot. Otherwise Venice was the smooth part — OpenAI-compatible, genuinely multimodal, and per-call billing made it easy to wire ASR, vision, reasoning, and TTS into one flow. <span class="hljs-section">### MetaMask 7715 and 1Shot don't compose</span> The single-<span class="hljs-code">`payee`</span> limit clashes with the 1Shot relayer's separate fee transfer, so you can't keep the merchant locked on-chain while settling through 1Shot — you have to pick one. Worth a heads-up for anyone trying to use the two together. </code></pre><p></p>
<p>None </p>