Deploy the console
Vercel plus Upstash Redis in ten minutes, or any VM with the file store.
The console is a Next.js 16 app in apps/web. On Vercel it is stateless, so plans, approvals and the audit trail live in Upstash Redis. The agent key lives in Vercel's environment; the rate limiter and the on-chain mandate bound what a stranger can make it do.
What a public deployment can and cannot do
- Anyone can chat with the agent and make it execute steps inside the mandate: 100 USDC per transaction, 500 USDC per day on the demo account, only allow-listed protocol calls. Bridging and payments still require your Ledger; a visitor cannot get past the approval sheet without the device.
- The rate limiter caps model spend. Cross-origin POSTs are rejected. Details in Operate.
- Kill switch:
MANDATE_EXECUTION_ENABLED=falsemakes everyexecute_stepreturn "disabled by the operator" without a redeploy. - Hard stop: lower the caps or Revoke from the Mandate page, or
cast send $ACCOUNT "revokeMandate()".
1. Upstash Redis
console.upstash.com → Create Database → Regional, N. Virginia (us-east-1) to sit next to Vercel's iad1, TLS on. Copy UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN. (Adding Upstash through the Vercel Marketplace injects KV_REST_API_URL and KV_REST_API_TOKEN instead; both pairs work.)
2. Vercel project
- Push the repo to GitHub. Vercel does not need the Foundry submodule.
- vercel.com/new → import the repo.
- Root Directory
apps/web, and tick Include source files outside of the Root Directory. - Framework Next.js, Node 22. Install and build commands default: Vercel detects the pnpm workspace, installs at the repo root, and the root
preparescript builds the SDK packages beforenext build.
3. Environment variables
| Variable | Value |
|---|---|
MANDATE_ACCOUNT | your account address |
AGENT_PRIVATE_KEY | the agent key (testnet only; it holds gas only) |
GRAPH_API_KEY | Subgraph Studio key |
TOOL_APPROVAL_SECRET | openssl rand -hex 16 |
| model | ANTHROPIC_API_KEY, or AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, BEDROCK_MODEL_ID |
UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN | from step 1 |
CRON_SECRET | random; Vercel sends it as Authorization: Bearer to /api/cron |
BASE_SEPOLIA_RPC | recommended: an Alchemy or QuickNode URL; the public RPC rate-limits under load |
MANDATE_EXECUTION_ENABLED | true |
RL_* | optional rate-limit overrides, see Operate |
Never set in production: NEXT_PUBLIC_DEV_GUARDIAN_KEY, GUARDIAN_PRIVATE_KEY, MANDATE_GUARDIAN_KEY, OWNER_PRIVATE_KEY, DEPLOYER_PRIVATE_KEY. The console needs none of them; the guardian is your Ledger.
4. Verify
/loads the venue table live./api/statusreturnsguardian= your Ledger,agent,mandate.active: true.- Chat: "Show my positions and remaining mandate."
- Rate limit: nine rapid
POST /api/chatfrom one IP; the ninth is a 429 withRetry-After. A POST without anOriginheader is a 403. - One Ledger approval on the production URL in Chrome; WebHID works because the site is HTTPS.
curl -H "Authorization: Bearer $CRON_SECRET" https://…/api/cronreturns reminders JSON.apps/web/vercel.jsonschedules it daily at 09:00 UTC.- Redeploy, then open
/activity: plans persist (Redis), which they would not with the file store.
Docs site
This site is a second Vercel project from the same repo: Root Directory apps/docs, include source files outside the root, Node 22, no environment variables. The root install runs fumadocs-mdx for the docs app and next build does the rest.
Alternative: any VM
git clone --recursive <repo> && cd mandate && pnpm install
cp .env.example .env && $EDITOR .env # MANDATE_STORE_DIR=/var/lib/mandate
cd apps/web && pnpm build && PORT=3000 pnpm start # pm2, nginx with TLS in front; WebHID needs HTTPSNo function time limits; the file store persists on disk; run /api/cron from crontab with the bearer secret. You own updates, backups and TLS renewal.