--- name: KleePay description: AI-agent payment infrastructure — issue virtual cards, authorize spends via PolicyWindows, manage wallets. Cards default to frozen; agents must request explicit authorization for each spend. --- # KleePay — AI Agent Skill You are interacting with **KleePay**, a programmable payment platform built specifically for AI agents. Your tools let you issue virtual cards, authorize spends through short-lived PolicyWindows, and manage wallet funds. The user's signing key never leaves their device — a local daemon called **klw** (KleePay Local Wallet) holds it and signs every write request on the user's behalf. ## What is KleePay (one-paragraph elevator) KleePay separates the *agent* (you) from the *signing authority* (the user's local klw daemon). You request a payment by calling an MCP tool; klw serializes a canonical PolicyWindow, signs it with the user's Ed25519 key, and submits it to the KleePay API. The API enforces the policy server-side (amount, merchant, expiry, scope) and routes the resulting authorization to the card network (RDP / Lithic / Visa / Mastercard) or a programmable rail (x402 / Lightning / Solana Pay). You never see the private key. The user audits and revokes any time from the dashboard. ## Core concept: frozen-by-default + PolicyWindow This is the most important section. Read it before any payment flow. **Cards are FROZEN at rest.** The card-issuer provider (RDP / Lithic) refuses every authorization while the card is frozen. There is no "active" mode — only "frozen" and "frozen-with-an-active-PolicyWindow". To spend, the agent must create a **PolicyWindow** (PW) — a signed, short-lived authorization that says: *"this card may be charged up to $X by merchant Y until time T"*. Creating a PW unfreezes the card *only* within that policy's bounds. When the window expires or the charge settles, the card auto-freezes again. **PolicyWindow lifecycle:** ``` unfreeze ──► authorize (creates PW, ~30 min default TTL) ──► merchant charges ──► settle │ ▼ card auto-freezes (next request blocked) ``` **Three PolicyWindow types** — pick the right one: | Type | Tool | Uses | Window | When to use | |----------------|--------------------------------|----------|--------|-------------------------------------------------------| | `charge` | `kleepay_authorize` | 1 | ~30 min | "Pay $50 to Amazon, single charge" | | `merchant_bind`| `kleepay_merchant_bind` | 1 (≤$2) | 30 min | "Verify card with merchant before first real charge" | | `recurring` | `kleepay_recurring` | many | months | "Allow Netflix to charge $15.99 on the 1st of each month" | Each PW is **signed by the user's Ed25519 key** (klw does the signing) so the server can prove the user authorized this exact spend. Only one active policy per card at a time — creating a new one cancels the previous. **Why this design:** structural defense against compromised agents. Even if an agent goes rogue, it cannot exceed the current PolicyWindow. There is no persistent "card is unlocked" power — every spend requires a fresh, narrow authorization. ## klw — the local signing daemon klw runs on the user's machine and holds the master Ed25519 key, encrypted at rest with the user's local password (Argon2id KDF + AES-256-GCM, with mlock to prevent swap leakage). **Two interfaces:** - **MCP** — for AI agents. Launched by the agent host as `klw mcp` (stdio JSON-RPC). - **CLI** — for humans + scripts. Subcommands like `klw authorize`, `klw list-cards`, `klw wallet allocate`. **Daemon endpoint:** `http://127.0.0.1:7723` (loopback only). HTTP API clients use a Bearer token at `~/.kleepay/daemon_token` (mode 0600). The MCP server inherits the daemon's keystore via a local IPC socket and does not need credentials. **Started by:** `klw start` (prompts for keystore password) or `KLW_PASSWORD=... klw start --password-from-env` (headless). **Stopped by:** `klw stop`. ## MCP usage **What MCP is here.** klw exposes an MCP server when invoked as `klw mcp` on stdio. The agent host (Claude Code / Codex CLI / OpenClaw / Cursor / Cline / Windsurf / Claude Desktop) launches `klw mcp` as a subprocess and pipes JSON-RPC over stdin/stdout. The MCP server resolves each tool call to a daemon HTTP request on `127.0.0.1:7723`, where the keystore signs write payloads. **One-liner config.** After `klw setup` completes, run: ```bash klw mcp-install ``` This auto-detects every supported agent on your machine + their config directories and writes the appropriate `mcpServers` entry. You can re-run it any time after installing a new agent. Use `klw mcp-install --uninstall` to remove the entries. **Per-agent manual config.** Claude Code (`~/.claude/mcp.json`): ```jsonc { "mcpServers": { "kleepay": { "command": "klw", "args": ["mcp"] } } } ``` Codex CLI (`~/.codex/config.toml` — or run `codex mcp add kleepay klw mcp`): ```toml [[mcp.server]] name = "kleepay" command = "klw" args = ["mcp"] ``` OpenClaw (`~/.openclaw/skills/...` — see OpenClaw docs for the schema; the daemon command is identical: `klw mcp`). **Auth model.** The MCP server inherits the daemon's keystore via local IPC. Agents do not need API keys, JWTs, or passwords. If the daemon is not running, MCP calls fail with `connection refused` and the agent must tell the user to run `klw start`. **Tool dispatch flow:** ``` [Agent host] ──MCP/stdio──► [klw mcp] │ │ (delegates to daemon over loopback IPC) ▼ [klw daemon @ 127.0.0.1:7723] │ │ (signs PolicyWindow with user's Ed25519 key) ▼ [{{API_URL}}] ◄── enforces policy server-side │ ▼ [Card network: RDP / Lithic / Visa / Mastercard] ``` **Common error symptoms (and what to tell the user):** | Symptom | Cause | Tell the user | |------------------------------------|-------------------------------------------------|-------------------------------------------------------| | `connection refused` on any tool | Daemon not running | "Please run `klw start` in your terminal." | | `key not loaded` / `wrong password`| Daemon hasn't unlocked the keystore | "Restart `klw start` — wrong KLW_PASSWORD?" | | `card frozen` | No active PolicyWindow on this card | (Agent action) call `kleepay_authorize` to create one | | `signature invalid` | Version drift between klw daemon and KleePay API| "Reinstall klw via {{INSTALL_URL}}" | | `kyc_not_complete` | KYC not approved | "Complete identity verification at {{DASHBOARD_URL}}" | | `insufficient_balance` | Card or wallet underfunded | (Agent action) `kleepay_wallet_allocate` to top up | ## MCP tools 26 tools total. Source of truth: `src/mcp/tools.rs::all_tool_defs()` in the klw repo. ### Info - `kleepay_version` — get klw version + capabilities. Always call first to confirm the daemon is reachable. ### Cards (read) - `kleepay_list_cards` — list cards with `card_id`, `last_four`, `label`, `status`, `balance`. Never returns PAN/CVV. - `kleepay_get_merchant_auth` — query pre-authorized cards for a merchant domain. - `kleepay_check_tx` — query transaction status by `policy_id` or `card_id`. - `kleepay_list_policies` — list active PolicyWindows (optionally filtered by `card_id`). - `kleepay_card_transactions` — provider-side transaction history for a card (auths, settles, refunds). - `kleepay_reveal_card` — trigger user-driven PAN/CVV reveal flow. Returns a dashboard URL the user opens; PAN/CVV is **never** sent to the agent. ### Cards (write — Ed25519-signed) - `kleepay_authorize` (alias `kleepay_pay`) — create a one-time charge PolicyWindow (default TTL 15 min). - `kleepay_merchant_bind` — create a $2-cap merchant verification window (30 min) so a new merchant can run a $0/$1 card-validation auth. - `kleepay_recurring` — create a recurring subscription window (`schedule_day`, `max_uses`, e.g. Netflix on the 1st for 12 months). - `kleepay_freeze` — manually freeze a card. (Cards auto-freeze on PW expiry; only use this for emergencies.) - `kleepay_unfreeze` — unfreeze a manually-frozen card. Prefer `kleepay_authorize` for spending — it scopes the unfreeze to the policy. - `kleepay_cancel_policy` — cancel an active PolicyWindow before it expires. ### Card lifecycle - `kleepay_create_card` — provision a new virtual card (signed). - `kleepay_bind_card` — bind a card to a merchant after the first successful auth (records the binding for `kleepay_get_merchant_auth`). - `kleepay_unbind_card` — remove a card-merchant binding. ### Wallet - `kleepay_wallet_balance` — wallet available / held / total. - `kleepay_deposit_address` — get a crypto deposit address (default USDT) for funding the wallet. - `kleepay_wallet_pay` — pay directly from wallet (signed). Optional `card_id` routes through a card. - `kleepay_wallet_allocate` — move funds wallet → card (signed, idempotent). - `kleepay_recall` — move funds card → wallet (signed, idempotent). - `kleepay_wallet_history` — wallet-level transaction history. - `kleepay_budget_status` — agent budget usage + remaining limits. ### Webhooks - `kleepay_webhook_list` — list outbound webhook subscriptions. - `kleepay_webhook_create` — create a webhook (HTTPS only). The HMAC secret is returned **only on creation** — store it. - `kleepay_webhook_delete` — delete a webhook by id. (No update endpoint; delete + create to change URL.) ## CLI reference For humans + scripts. Run `klw --help` for full flags. ### Onboarding | Command | Purpose | |------------------------|-------------------------------------------------------------------| | `klw setup ` | First-time bind: validate setup token, import key bundle, write config | | `klw import ` | Import a downloaded `.kleepay` bundle file directly | | `klw uninstall` | Stop daemon, wipe keys + config, clear OS keychain entry | ### Daemon | Command | Purpose | |-----------------|------------------------------------------------------| | `klw start` | Start signing daemon (prompts for keystore password) | | `klw stop` | Stop the daemon | | `klw status` | Show daemon status, loaded keys, listening port | | `klw remove ` | Securely wipe a single imported key | ### Cards | Command | Purpose | |------------------------------------------|-----------------------------------------------------------| | `klw list-cards` | List cards (balance + status) | | `klw create-card [PRODUCT_ID]` | Provision a new virtual card (default product if omitted) | | `klw authorize ` | Create one-time charge PolicyWindow (alias: `klw pay`) | | `klw merchant-bind ` | Create $2-cap verification window | | `klw recurring --schedule-day N` | Create recurring window | | `klw freeze ` | Freeze a card | | `klw unfreeze ` | Unfreeze a card | | `klw reveal ` | Reveal PAN/CVV/expiry (requires keystore unlock) | | `klw fill-card --url ` | Auto-fill card details into a Chrome payment form | | `klw card-transactions ` | Provider-side auth/settle/refund history | | `klw card history ` | PolicyWindow timeline (past + active + scheduled) | | `klw bind ` | Bind a card to a merchant (persistent record) | | `klw unbind ` | Remove card-merchant binding | ### Wallet & Policies | Command | Purpose | |------------------------------------|---------------------------------------------------------| | `klw wallet balance` | Show wallet balance | | `klw wallet deposit` | Get a deposit address | | `klw wallet allocate ` | Move funds wallet → card | | `klw wallet recall ` | Move funds card → wallet | | `klw wallet history` | Wallet transaction history | | `klw policies list` | List active PolicyWindows | | `klw policies cancel ` | Cancel an active PolicyWindow | ### Interface | Command | Purpose | |-------------------|--------------------------------------------------------------| | `klw tui` | Interactive terminal UI | | `klw mcp` | Run as an MCP server on stdio (for AI agent integration) | | `klw mcp-install` | Auto-configure detected AI agents (Claude Code, Codex, etc.) | | `klw skill install` | Write this skill file into detected agent skill directories | | `klw skill print` | Print the rendered skill file to stdout | ### Info | Command | Purpose | |-----------------|----------------------------------| | `klw version` | Version + build info | | `klw help` | Top-level help | ## Quick examples (common flows) ### "Pay $50 to one merchant" ``` → kleepay_list_cards() ← [{ card_id: "c_abc", label: "Shopping", balance_usd: 200.00 }, ...] → kleepay_authorize({ card_id: "c_abc", amount: 50.00, currency: "USD", merchant_domain: "amazon.com" }) ← { policy_id: "pol_xyz", status: "active", expires_at: "...(15 min)" } → kleepay_check_tx({ policy_id: "pol_xyz" }) ← { status: "settled", amount: 50.00, merchant: "amazon.com" } ``` ### "Set up a Netflix subscription" ``` → kleepay_merchant_bind({ card_id: "c_abc", merchant_domain: "netflix.com" }) ← { policy_id: "pol_bind", type: "merchant_bind", max_amount: 2.00 } # Netflix runs a $0/$1 verification → window expires → card refreezes → kleepay_recurring({ card_id: "c_abc", amount: 15.99, merchant_domain: "netflix.com", schedule_day: 1 }) ← { policy_id: "pol_rec", type: "recurring", schedule_day: 1, max_uses: 12 } # Every 1st of the month: card unfreezes → Netflix charges $15.99 → refreezes ``` ### "Pre-bind a new merchant" ``` → kleepay_merchant_bind({ card_id: "c_abc", merchant_domain: "uber.com" }) ← { policy_id: "pol_bind2", max_amount: 2.00, expires_at: "...(30 min)" } # Use the 30-min window to enter PAN at Uber's checkout — they'll do a # $0 hold → window expires → card refreezes ``` ### "Reveal a card to enter PAN/CVV at checkout" ``` → kleepay_reveal_card({ card_id: "c_abc" }) ← { reveal_url: "{{DASHBOARD_URL}}/cards/c_abc/reveal?session=..." } # Per security policy, PAN/CVV NEVER reach the agent. The agent tells the # user to open that URL, enter MFA, and copy the details to the merchant. # When done, the agent calls kleepay_bind_card to record the binding. ``` ### "Read wallet balance, allocate $20 to a card" ``` → kleepay_wallet_balance() ← { available: "120.00", held: "0.00", currency: "USD" } → kleepay_wallet_allocate({ card_id: "c_abc", amount: "20.00", currency: "USDC", idempotency_key: "..." }) ← { success: true, new_card_balance: "70.00", new_wallet_balance: "100.00" } ``` ## Failure modes & what to tell the user | Error | Cause | Action / what to say | |-----------------------------|--------------------------------------------------|-------------------------------------------------------| | `connection refused` | klw daemon not running | "Run `klw start` and enter your keystore password." | | `key not loaded` | Daemon started but didn't unlock keystore | "Restart `klw start` — KLW_PASSWORD may be wrong." | | `card frozen` | No active PolicyWindow | Agent: call `kleepay_authorize` first. | | `insufficient_balance` | Card or wallet underfunded | Agent: `kleepay_wallet_allocate` more to the card. | | `kyc_not_complete` | KYC not approved | "Complete KYC at {{DASHBOARD_URL}}/identity" | | `billing_address_required` | Card needs a billing address | "Set billing address on the card creation page." | | `card_provisioning` | Provider still provisioning the card | "Wait 30 seconds and retry." | | `policy_expired` | PW TTL elapsed | Agent: re-create with `kleepay_authorize`. | | `policy_limit_reached` | Too many active policies on the card | Agent: cancel an old one with `kleepay_cancel_policy`.| | `monthly_limit_exceeded` | Card monthly cap hit | Use a different card or wait until next month. | | `daily_limit_exceeded` | Card daily cap hit | Use a different card or wait until tomorrow. | | `single_limit_exceeded` | Amount > per-transaction cap | Reduce amount or top up + raise cap. | | `signature_invalid` | Key revoked or version drift | "Add a new device at {{DASHBOARD_URL}}/cards or reinstall klw from {{INSTALL_URL}}." | | `all_keys_revoked` | Every signing key was revoked | "Add a new device at {{DASHBOARD_URL}}/cards." | ## HTTP API (alternative to MCP) If MCP is unavailable, agents can call the daemon directly: - Endpoint: `http://127.0.0.1:7723` - Auth: `Authorization: Bearer ` where `` is read from `~/.kleepay/daemon_token` (mode 0600, written when `klw start` runs). - `GET /health` — daemon status (no auth needed). - `GET /cards` — list cards (Bearer required). - `POST /authorize` — create a PolicyWindow (Bearer required). The MCP server is the supported integration path; the HTTP API is for non-MCP environments (CI scripts, custom integrations). ## Onboarding a new user (full flow) The HUMAN must do these (browser / terminal): 1. Register at **{{DASHBOARD_URL}}** and complete **KYC**. 2. Deposit USDT/USDC to their wallet. 3. From the dashboard → Cards → Create Card. The dashboard returns a one-time install command including a `SETUP_TOKEN`. 4. Paste the install command into a terminal: ``` curl -fsSL {{INSTALL_URL}} | SETUP_TOKEN= sh ``` 5. Set a local keystore password when prompted. 6. The installer auto-detects MCP-capable agents and (with the user's confirmation) writes their config + this skill file. The agent CANNOT do steps 1–6 (they require browser + terminal + the user's password). After setup completes, the agent CAN create more cards, allocate funds, and authorize spends through MCP tools. ## Reference URLs - Dashboard: **{{DASHBOARD_URL}}** - API base: **{{API_URL}}** - klw installer: **{{INSTALL_URL}}** - This skill (latest): **{{SKILL_URL}}** - Source: This skill file ships embedded inside the klw binary; the URLs above are substituted at runtime so that stag binaries point at stag.kleepay.ai and prod binaries at kleepay.ai. Run `klw skill print` to see the rendered copy and `klw skill install` to write it into your agents' skill directories.