# AIPAY for AI agents (human-readable guide)

This page is for the human who runs an agent. The machine-readable versions are
[`/llms.txt`](../llms.txt), [`/agent.json`](../../agent.json) and the
[skill file](../../skills/aipay/SKILL.md); this one explains the same thing in prose.

## What the agent surface is — and is not

AIPAY's web app is for people: it holds a browser wallet and shows payment pages.
The **agent surface** is a separate, local process with its **own** wallet:

- a stdio MCP server (`agent/mcp-server.mjs`) and a CLI (`agent/cli.mjs`),
- state and keys under `AIPAY_AGENT_HOME` (default `~/.aipay/agent`),
- a local spending-policy engine, enforced by that process — **not** by a chain.

It is not a hosted API. `aipay.im` serves static files; it cannot sign, pay or
store anything for you. If a tool is missing, the correct behaviour is to say so,
not to guess an endpoint.

## Install

The runtime is published as a sanitized, allowlisted tarball:

- public repo: <https://github.com/aipayim/aipay-agent>
- current version, sha256 and file list: <https://aipay.im/downloads/agent-latest.json>

```bash
curl -fsSLO https://raw.githubusercontent.com/aipayim/aipay-agent/main/install.sh
AIPAY_AGENT_VERSION=<version> bash install.sh
```

The script verifies the tarball's sha256 (aipay.im, then the GitHub release) before
extracting, then installs the runtime dependencies. Nothing else is downloaded.

Requirements: **Node.js ≥ 22.18**. The runtime is the agent tool registry plus the
`src/lib` closure it imports; it contains no keys, no state, no docs and no web app
code, and the build fails if a published file matches a credential shape.

## First run

```bash
export AIPAY_AGENT_HOME="$HOME/.aipay/agent"
export AIPAY_AGENT_PASSPHRASE='a strong passphrase'

node ~/.aipay/agent-dist/package/agent/cli.mjs keystore init --generate  # prints the phrase once
node ~/.aipay/agent-dist/package/agent/cli.mjs address
node ~/.aipay/agent-dist/package/agent/cli.mjs config
```

Read-only tools work before any wallet exists; anything that signs fails with
`credentials_unavailable` until the keystore is unlocked.

## Connect it to your agent host

```json
{
  "mcpServers": {
    "aipay": {
      "command": "node",
      "args": ["/home/you/.aipay/agent-dist/package/agent/mcp-server.mjs"],
      "env": { "AIPAY_AGENT_HOME": "/home/you/.aipay/agent", "AIPAY_AGENT_PASSPHRASE": "…" }
    }
  }
}
```

Tool failures come back as results with `isError: true` and
`structuredContent: { code, nextAction, retryable }`. Branch on those, never on prose.

## What the agent may spend

Nothing, until a human grants a **capability**: scope (chains / assets / recipients /
merchants), budget (per payment, per window, lifetime), expiry, and an approval mode
(`auto`, `escalate`, `human`).

The human's approval key is a separate key that can only sign approvals and grants:

```bash
node agent/cli.mjs approval keygen                 # address = the capability issuer
node agent/cli.mjs capabilities grant \
  --issuer 0x… --holder 0x…the-agent-wallet \
  --chain base --asset USDC --to 0x…merchant \
  --per-payment 25 --per-window 100 --window-seconds 86400 --total 500 \
  --expiry 2026-12-31T00:00:00Z --approval-mode escalate --escalate-above 25
```

`--holder` names the address allowed to spend *and delegate*. A holder can hand out a
narrower child capability (`aipay_capability_delegate`): same issuer (the human), same
subject, only smaller scope/expiry/budget, one level deep. Delegating never transfers
approval authority — an escalated payment still needs the human's key.

`policy` (and `aipay_policy_status`) also lists lifecycle `warnings[]`:
`kill_switch_on`, `capability_revoked`, `capability_expired`,
`capability_expiring`, `delegation_expiring` (a child dies with the earlier of
itself and its parent) and `budget_exhausted` (per asset). The "expiring soon"
horizon is seven days by default and parameterisable (`expiringWithinSeconds`).
A warning never changes a decision; the engine stays the only authority.

The kill switch (`aipay_spending_kill`) denies every payment immediately, and both
directions are audited with `actor: human | agent`.

Migrating or handing over an agent is one file, and it grants nothing new:

```bash
node agent/cli.mjs capabilities export --all --out bundles/agent-a.json
node agent/cli.mjs capabilities import --bundle bundles/agent-a.json
```

The bundle (`aipay-grant-bundle-v1`) carries the same signed `aipay-grant-v1`
envelopes, verified on both sides, parents before children. Revoked capabilities
are skipped and reported; re-imports are idempotent.

## Operating rules that prevent loss

- **Quote first.** `aipay_quote` reports the policy verdict for exactly that payment.
- **Pay once.** Always pass `idempotencyKey`; a retry with the same key returns the
  first result instead of paying twice.
- **Do not re-create requests.** `merchantOrderId` makes creation idempotent; the same
  id with different parameters is a conflict, and an expired id is terminal.
- **Confirmed is not delivered.** A chain-verified confirmation proves the payment;
  `Order.delivery` is always `not_tracked`.
- **Never print keys or phrases.** The keystore is encrypted with scrypt + AES-GCM and
  written with mode 0600.

## Troubleshooting

| Symptom | Cause | What to do |
|---|---|---|
| `credentials_unavailable` | no keystore / wrong passphrase | `keystore init` or set `AIPAY_AGENT_PASSPHRASE` |
| `policy_denied` | outside every granted capability | ask the human to widen the grant (it cannot be done by the agent) |
| `policy_escalated` | inside scope but needs sign-off | get the single-use `approvalToken` from the human, then pay once |
| `idempotency_conflict` | same key, different payment | keep the original; check `aipay_orders_get` |
| `unknown_chain` | wrong `chainKey` | read `aipay_chains_list` first |
| MSG missing from `aipay_chains_list` | MSG is not enabled | expected: `msg-config.json` ships `enabled: false` |

## Where to read more

- Skill file (step-by-step for the agent): [`/skills/aipay/SKILL.md`](../../skills/aipay/SKILL.md)
- Machine surface: [`/agent.json`](../../agent.json) and [`/llms.txt`](../llms.txt)
- Web planner / signer: [`/en/agent`](https://aipay.im/en/agent)
- Distribution repo: <https://github.com/aipayim/aipay-agent>
