---
name: bags-cash
description: |
    Pay x402-protected APIs with a BAGS hosted agent wallet (USDC credits, server-side policies).
    Use when the user has a BAGS invite code, wants to call paid APIs via BAGS Cash / BAGS Wallet,
    or mentions bags wallet / bags cash / getbags / x402 micropayments.

    TRIGGERS: x402, paid API, bags wallet, bags cash, getbags, invite code, redeem, micropayment,
    agent wallet, check endpoint, wallet fetch
homepage: https://www.getbags.app/wallet/skill.md
metadata:
    version: 0.2
---

# BAGS Cash — Hosted Agent Wallet

> Hosted skill URL: https://www.getbags.app/wallet/skill.md  
> Human install guide: https://www.getbags.app/wallet/install  
> Onboard (humans): https://www.getbags.app/wallet/onboard  
> Staging: replace the host with `https://staging.getbags.app`.

Call x402-protected APIs with a **hosted** BAGS wallet. Redeem an invite (or mint a sandbox wallet), discover services, **check** the exact quote + schema, then `fetch`. No local private keys — the agent holds only a token (`bag_agent_sk_*`).

CLI examples below use `npx @getbags/cash …`. After a global install (`npm i -g @getbags/cash`), the `bags` binary is the same command.

## Why hosted (vs local-key wallets)

Local plaintext / keychain wallets break in ephemeral sandboxes (Claude Cowork, CI, short-lived VMs): the key dies with the machine. BAGS keeps custody + ledger server-side. Your agent only needs the token in `~/.bags/credentials.json` (or `Authorization: Bearer`). Policies (caps, allowlists, kill switch) are enforced on the server — the agent cannot bypass them by editing a local file.

## First-time setup (do in order)

1. **Get a token** — sandbox (no invite) or live invite:

```bash
npx @getbags/cash redeem --test
# or: npx @getbags/cash redeem <code>
```

`redeem --test` calls `POST /api/wallet/redeem` with `{"mode":"test"}`. That mints a test wallet with fake **$100,000** promo credit, restricted to **Base Sepolia + Solana devnet**, and burns **no** invite. Use a live invite (`redeem <code>`) only when you need mainnet spend.

2. **Register the wallet with your agent client:**

```bash
npx @getbags/cash init
```

Bare `init` writes **user-scope** config under `~` so the wallet is ambient on this machine (Cursor / Claude Code / Codex). Use `--scope project` to write **committable, repo-local** config (`.cursor/mcp.json`, `.mcp.json`, `AGENTS.md`, etc.) for a team. Other flags: `--dry-run`, `--client cursor|claude|codex` (force-create even without a marker directory).

3. **Restart the agent client** (Cursor / Claude Code / Codex) so it loads the new MCP server. MCP configs are not hot-reloaded — skipping this leaves the wallet invisible.

4. **Verify:**

```bash
npx @getbags/cash doctor
```

## Wallet

| Task                        | Command                           |
| --------------------------- | --------------------------------- |
| Sandbox wallet (no invite)  | `npx @getbags/cash redeem --test` |
| Redeem invite (saves token) | `npx @getbags/cash redeem <code>` |
| One-command agent setup     | `npx @getbags/cash init`          |
| Verify agent visibility     | `npx @getbags/cash doctor`        |
| Check balance + caps        | `npx @getbags/cash balance`       |

If there is no token yet, redeem (test or invite) first. If live balance is too low, ask for another invite.

## Workflow: balance → discover → check → fetch

Match AgentCash’s agent loop; prefer this order every time.

### 1. Balance

```bash
npx @getbags/cash balance
```

### 2. Discover or search

```bash
npx @getbags/cash discover                    # BAGS catalog (includes $0.01 /api/v1 showcase)
npx @getbags/cash discover weather forecast   # BAGS first, then open x402 index
npx @getbags/cash search "send physical mail" # NL search (catalog + ecosystem)
```

Bare `discover` lists BAGS’ own **$0.01** `GET /api/v1` showcase first — the natural first paid call for a new agent. Prefer `source: bags` results (refund-guaranteed on BAGS merchants when that guarantee is live). Then `source: bazaar`. Default table columns: `url`, `method`, `price`, `merchant`, `source`. Use `--format json` for the raw payload (includes schemas when present).

### 3. Check (exact quote, no payment)

```bash
npx @getbags/cash check '<url>'
npx @getbags/cash check '<url>' -m POST -b '{"key":"value"}'
```

Returns HTTP status, whether payment is required, price in cents/USD, accept options (network/scheme), and input/output schemas when the endpoint advertises them. **Always check before an expensive or schema-sensitive fetch** to avoid 400s.

### 4. Fetch (pay + proxy)

```bash
npx @getbags/cash fetch '<url>'
npx @getbags/cash fetch '<url>' -m POST -b '{"key":"value"}'
npx @getbags/cash fetch '<url>' --max-price-cents 25
```

Payment receipt (amount, tx hash, network) → stderr; upstream body → stdout (pipe-friendly).

**Latency:** wallet fetch often takes **~30–60 seconds** (paid ~30s; free/SIWX ~40–50s). Set agent-framework HTTP timeouts accordingly — do not treat a slow response as a hang until well past 60s.

**Response envelope:** check top-level `status` / `code` first. `status: "success"` means the fetch completed as intended (including free/SIWX calls with `payment.paid: false`). A paid attempt that did not complete returns `status: "error"` with `PRE_PAYMENT_FAILED` or `NETWORK_NOT_ALLOWED` (nested `data.http_status` / `data.payment` keep the upstream diagnostic). Do not treat HTTP 200 alone as “paid OK” — and do not treat nested `http_status: 402` under `status: "success"` as a thing that happens anymore.

## Other commands

| Command                                                 | Purpose                             |
| ------------------------------------------------------- | ----------------------------------- |
| `transactions`                                          | Ledger / spend history              |
| `policies get` / `policies set --per-call-cap-cents=50` | Read/update spend caps              |
| `keys create\|list\|revoke`                             | Per-agent sub-keys                  |
| `register <origin>`                                     | Register origin into discover index |
| `mcp`                                                   | Serve wallet tools over stdio       |
| `doctor`                                                | Verify wallet visibility to agents  |

## Important rules

- **Hosted token only** — never invent or store user private keys for BAGS Cash.
- **Check before fetch** when price or request shape is unclear.
- **Prefer `source: bags`**, then bazaar, then any trusted x402 URL via `fetch`.
- **Failed pre-payment requests cost nothing.** If payment settled and upstream still errored, read the stderr receipt / `transactions`.
- **Do not invent endpoints.** Use `discover` / `search` / `check` or a URL the user provided.
- **Sandbox first.** Prefer `redeem --test` while integrating; switch to a live invite for mainnet.

## Troubleshooting

| Code                                | Fix                                                                                    |
| ----------------------------------- | -------------------------------------------------------------------------------------- |
| `INSUFFICIENT_BALANCE`              | `npx @getbags/cash balance` then redeem another invite (or use `redeem --test` to try) |
| `INVITE_INVALID` / `INVITE_EXPIRED` | Ask for a new invite code                                                              |
| `URL_BLOCKED`                       | Use a public `https` endpoint (SSRF gate)                                              |
| `CAP_EXCEEDED`                      | Wait, lower `--max-price-cents`, or `policies set`                                     |
| `WALLET_SUSPENDED`                  | Dashboard / support                                                                    |
| `WALLET_FETCH_DISABLED`             | Retry later (global kill switch)                                                       |
| `VALIDATION_FAILED`                 | Fix url/method/body JSON                                                               |
| `NOT_FOUND`                         | Route not live on this env — set `BAGS_API_URL` or upgrade                             |
| `UPSTREAM_ERROR` / `TIMEOUT`        | Retry; `npx @getbags/cash check <url>` for a fresh quote (fetch can take 30–60s)       |
| `NETWORK_NOT_ALLOWED`               | Test wallet vs mainnet (or vice versa) — use matching mode                             |
| `PRE_PAYMENT_FAILED`                | Payment did not broadcast; reservation reversed — fix quote / network / funds          |
| `AUTH_MISSING_CREDENTIALS`          | `npx @getbags/cash redeem --test` or `npx @getbags/cash redeem <code>`                 |

Env: `BAGS_API_URL` (default `https://www.getbags.app`; staging example `https://staging.getbags.app`).  
Token path: `~/.bags/credentials.json`.

MCP: wallet tools on `https://www.getbags.app/api/mcp/mcp` — pass `Authorization: Bearer bag_agent_sk_...` or a `wallet_token` argument on each tool.
