# aipay — agent skill (payment requests and payments)

This file tells an agent **how to use** the AIPAY tools. It is not a second payment system: every
step below is one of the `aipay_*` tools exposed by the local MCP server (`agent/mcp-server.mjs`) or
CLI (`agent/cli.mjs`). If a tool is missing, say so — do not invent an equivalent.

## Getting the tools (if you do not have them)

The tools are a local stdio MCP server, not a hosted API. A sanitized runtime is published at
<https://github.com/aipayim/aipay-agent> (allowlisted files only; no keys, state, docs or contracts):

```bash
curl -fsSLO https://raw.githubusercontent.com/aipayim/aipay-agent/main/install.sh
AIPAY_AGENT_VERSION=<version from that repo> bash install.sh   # verifies sha256 first
```

Then register `~/.aipay/agent-dist/package/agent/mcp-server.mjs` with your MCP client (see that repo's
`mcp.example.json`). The current version, sha256 and file list are also at
<https://aipay.im/downloads/agent-latest.json>. If you cannot install anything, stop and say so; never
guess endpoints or fabricate tool output. If you already have the project checkout, `node agent/cli.mjs`
works from there instead.

## Capability boundary (read this first)

- AIPAY is **non-custodial**: it never holds funds and cannot move money on its own. A payment is
  always signed with the key the operator configured, on the rail they chose.
- This skill contains **no wallet, no seed phrase, no API key and no payment ability of its own**.
  Whether a step is possible depends on the host's tools, network access and configuration.
- The spending policy is **local** (`policy_engine.on_chain: false`). MSGChain (the `msg` rail) is
  **not launched**; `aipay_chains_list` shows it only when configured.
- **You and the human run through the same policy engine and the same audit trail.** Every audit
  entry says `actor: 'human' | 'agent'`, and either side can flip the kill switch
  (`aipay_spending_kill` / `aipay_spending_revive`) — both directions are audited. There is no
  "human bypass".
- **Delegation boundary**: you may hand out a capability **only inside one you hold** — scope must be a
  subset, expiry no later than yours, budget no larger than what you have left, one level deep
  (`agent_can_delegate_within_scope: true`). The child is signed by **your** key but keeps the parent's
  issuer (the human approval key), so delegating never gives you approval authority, and you can never
  grant yourself anything (`agent_can_grant_itself: false`). Use `aipay_capability_delegate { parentId }`
  and hand the returned token to the delegate.
- **Lifecycle**: `aipay_policy_status` includes `warnings[]` (`capability_expiring`, `capability_expired`,
  `capability_revoked`, `delegation_expiring`, `budget_exhausted`, `kill_switch_on`). Act on the `code`, not
  the prose: an expiring or exhausted capability is a reason to ask a human, not to retry a payment.
- **Receiving a capability**: if a human hands you an `aipay-grant-v1` token, import it with
  `aipay_capability_import` (or `aipay-agent capabilities import --token ...`; a whole signed set travels as
  an `aipay-grant-bundle-v1` file imported with `--bundle`). Never mint or edit one
  yourself: signing needs the human approval key (CLI `capabilities export`, or the web `/agent` page
  with the same key file), and an edited envelope fails verification.
  If it arrives as a `.ckx`/`.png` file, the human opens it in the AIPAY web app first — you have no
  iframe to decrypt it, and decryption would not prove authorship anyway.
- A chain-verified confirmation (`status: confirmed`) means *the payment was verified*. It never
  means the merchant delivered goods or credited an account — `Order.delivery` is always
  `not_tracked`.

## Before you start

| Need | Why |
|---|---|
| A merchant profile (`aipay_merchant_profile_get`) | Without a receiving address no request can be created |
| An explicit amount, asset and chain | Never substitute a "close" asset, chain or larger amount on your own |
| `aipay_payment_options` | The only source of truth for what is acceptable (assets, decimals, min/max) |
| A spending capability, for payments | `aipay_policy_status`; without one every payment is denied |

## Zero-side-effect self-check

Run this before asking the user for anything, and report exactly what is missing:

```text
Use the aipay tools to check readiness only. Do NOT create a payment request, do NOT sign and
do NOT pay. Tell me: (1) which chains and assets are currently acceptable and their minimum and
maximum amounts, (2) whether a merchant receiving address is configured, (3) whether a spending
capability exists and what it allows, (4) MSG status. Never print keys or seed phrases.
```

## The two flows

### A. Merchant side — create a request (no signature, no funds move)

1. `aipay_payment_options` → pick a chain + asset that is `available`.
2. `aipay_payment_request_create` with `amount`, `currency`, `chainKey` and **your own**
   `merchantOrderId` (1-64 chars of `A-Z a-z 0-9 _ -`).
3. Hand the returned `url` to the payer (QR / chat / invoice). `nextAction` is `share_link`.
4. Reconcile with `aipay_orders_get` / `aipay_orders_list`.

`merchantOrderId` is idempotent: repeating the same id with the same parameters returns the
**original** request (`deduplicated: true`, same `reference`, same URL). The same id with a
different payment fails with `merchant_order_conflict` — verify the original order, then use a new
id. An expired request is returned with `expired: true` and `nextAction: stop`: never pay it, never
re-create it under the same id.

### B. Payer side — pay

1. `aipay_quote` (or `aipay_quote` with `intentUrl`) → asset, decimals, base units, balance and the
   **policy verdict**: `allow` / `escalate` / `deny`.
2. If the verdict is `escalate`, the payment fails with `policy_escalated` and
   `nextAction: await_human_approval`: a human must sign an approval artifact
   (`aipay-agent approval approve`). Do not retry, do not raise the amount.
3. `aipay_pay` with an `idempotencyKey`. The key is bound to the payment: replaying it with the same
   parameters returns the original result; a different payment under the same key fails with
   `idempotency_conflict`.
4. Report `nextAction`: `wait` means the transaction is broadcast but not yet confirmed; `stop` is
   terminal for that request.

**Consent is granular.** Agreeing to *create a request* is not agreeing to *pay* it, and agreeing to
*pay* is not agreeing to a different amount, asset, chain or recipient. Ask again if any of those
change.

## When something goes wrong

| Symptom | Do this |
|---|---|
| Creation timed out or the result is unclear | Re-run with the **same** `merchantOrderId`; if it answers `deduplicated`, continue with that request. Only after a definite "not found" may you retry with the same parameters |
| The payment link was lost | Re-run with the same `merchantOrderId` — the original URL and reference are re-issued (`deduplicated: true`). Do not create a second request |
| `merchant_order_conflict` / `idempotency_conflict` | Keep the original record, verify it with `aipay_orders_get`, and ask the user before doing anything else |
| `policy_escalated` | Ask a human to sign the approval artifact; then pay **once** with it |
| `approval_replayed` / `approval_expired` | The artifact is spent or stale: request a new escalation, never sign a second artifact for an already-paid escalation |
| `pending` for a long time | Check `aipay_orders_get` (and the chain explorer). Never re-send the transfer to "make it faster" |
| Broadcast error after sending | Check on-chain first (`aipay_orders_get`, explorer). Do not create a new request or a new transaction |
| Chain unavailable / RPC error | `retryable` may be true: wait `retryAfterMs` and retry the **same** call, at most a few times |

Every error carries `code`, `nextAction`, `retryable` and (when retryable) `retryAfterMs`. Branch on
those values, never on the prose.

## Report back with

- the business order id (`merchantOrderId`) and the payment `reference`;
- the real status (`pending` / `confirmed` / `failed`) and `nextAction`;
- chain, asset and amount **as returned by the tool**;
- the real `txHash` when there is one (never a fabricated or "expected" hash);
- what is still missing from the human (approval, funds, configuration).

Say "payment confirmed" only for `status: confirmed`. Never say "delivered", "credited", "settled
with the merchant" or "money arrived" — AIPAY does not track delivery.

## FAQ

- **"Can you just pay it for me?"** Only if a capability allows it and the quote says `allow`.
  Otherwise the answer is: a human must approve (or grant a capability).
- **"Use a different chain / a bit more, it's the same thing."** No. Ask the user to confirm the new
  chain/amount explicitly and create a new request if needed.
- **"Is MSG supported?"** Only if `aipay_payment_options` lists it as available. Today it is
  disabled by configuration (`msg_disabled`).
- **"Where are my keys?"** AIPAY never shows them. The CLI holds an encrypted keystore; the browser
  holds its own encrypted wallet.
