Home/Docs/Quickstart

Quickstart

Run Agent Passport locally and drive the Northbank Sandbox — a fake brokerage with a real API — from allow to deny to live revocation to a 403 block. About five minutes.

What you'll run

The demo bundle starts four things on your machine: the passport service (verify + mandates), the Northbank Sandbox brokerage (guarded by requireKYA), the principal & platform dashboards, and an MCP server + CLI for the agent. Storage is SQLite via Drizzle — no external services.

Prerequisites #

  • Node.js 20+ and npx.
  • Optional: Claude Code (or any MCP-capable runtime) to drive the agent through the MCP server. A plain CLI path is included if you'd rather not.

Everything is sandboxed: KYC is a stub with the same interface shape as Persona / Stripe Identity, and the sanctions screen is a stub. No real identity data, no real money.

Spin up the stack #

One command boots the passport, the demo brokerage, and both dashboards:

terminalrun once
# boot passport + Northbank Sandbox + dashboards
npx @passport/demo up

# → passport   http://localhost:4000
# → northbank  http://localhost:4100  (guarded by requireKYA)
# → dashboard  http://localhost:4200

Leave it running. The next steps use the dashboard for the human parts (KYC, issuing and revoking mandates) and the CLI or MCP server for the agent parts.

Onboard a principal #

Open the dashboard at http://localhost:4200 and create a principal. Run it through the sandbox KYC flow (any test input passes) to reach kyc: verified. Behind the scenes this is a POST /v1/principals plus the vendor callback.

or via APIPOST /v1/principals
curl -X POST http://localhost:4000/v1/principals \
  -H "Authorization: Bearer $PLATFORM_KEY" \
  -d '{ "type": "individual", "country": "US" }'
# → { "id": "prn_a1…", "kyc": "pending", "onboarding_url": "…" }

Register an agent & issue a mandate #

Register the agent's public key, then issue a scoped mandate. The demo agent is treasury-bot, and the mandate mirrors the pitch: account.refill up to $1,000 / transaction and $2,500 / week at Northbank.

terminalagent CLI
# generate a keypair & register the public key → agt_…
passport agent init --name treasury-bot --runtime claude-code

# issue the mandate from the dashboard, or:
passport mandate issue \
  --agent agt_9f… \
  --action account.refill \
  --max-per-tx 100000 \        # $1,000.00 (minor units)
  --max-per-period 250000 \    # $2,500.00 / week
  --period week --currency USD \
  --platform plt_northbank
# → mnd_tr7…  status: active
Custodial issuance (MVP)

In the alpha the passport signs the mandate after the principal authorizes it in the dashboard — the CA model. The documented upgrade is principal-held keys / W3C Verifiable Credentials with identical semantics.

Present a signed assertion #

The agent signs a per-request assertion and calls Northbank. From Claude Code, use the MCP tool passport_present; or use the CLI directly:

terminalagent CLI
# signs { mandate_id, action, amount, currency, platform_id, nonce, ts }
# with the agent key, attaches X-Passport, and calls Northbank
passport present --action account.refill --amount 500
# → ALLOW  $500.00  remaining_this_period $2,000.00  vrf_9c1…

In Claude Code the same thing looks like a tool call — see the MCP server guide:

Claude Code · MCPpassport_present
passport_present({ action: "account.refill", amount: 50000, currency: "USD" })
// → { decision: "allow", chain: {…}, verification_id: "vrf_9c1…" }

Walk the demo storyline #

Run these in order to see every decision path. This is the pitch:

terminalthe whole story
passport present --action account.refill --amount 500    # ALLOW · remaining $2,000
passport present --action account.refill --amount 2000   # DENY  per_tx_cap
passport present --action account.refill --amount 900    # ALLOW · remaining $1,100
passport present --action account.refill --amount 900    # ALLOW · remaining $200
passport present --action account.refill --amount 900    # DENY  period_cap

# now revoke mnd_tr7… in the dashboard (one click), then:
passport present --action account.refill --amount 500    # DENY  mandate_revoked  (< 2s later)

# and an anonymous caller with no passport:
curl -s -X POST http://localhost:4100/v1/account/refill -d amount=250
# → HTTP 403  "KYA required"  { onboarding_url: "…/kya/start" }
ok per_tx_cap period_cap mandate_revoked 403 kya_required

Each ALLOW returns the full resolved chain of agency and a JWS receipt. After Northbank executes the refill it can countersign the verification, producing a record signed by both sides.

Teardown #

terminal
npx @passport/demo down   # stops services, keeps the SQLite audit log
npx @passport/demo reset  # wipes local state for a clean run