Repository navigation
Conversation
✅ Preview approved@artugrande approved a Mintlify preview for commit |
artugrande
left a comment
There was a problem hiding this comment.
Verdict: REQUEST-CHANGES
Reviewed at head 6b5c33ea (re-checked against the API right before drafting; the branch is 0 commits behind main). Checked against @celo/buy@0.8.5, which is still npm latest (published 2026-10-28; no newer version). Locally, all five steps of the Documentation Validation job pass at 6b5c33e with the CI-pinned mintlify@4.2.920: validate, broken-links --check-redirects, check-orphans.sh, redirect unit tests (25/25), and check_redirects.py. I rendered the page with mint dev at 1440px and 375px, and neither width scrolls horizontally. I ran --help for every documented command, plus quote against the real gateway (sandbox and mainnet). I also ran CLI and MCP paid calls against a local buy gate --mock paywall, using a throwaway unfunded file-backend wallet in an isolated BUY_HOME. I did not run any paid call, including the sandbox one.
Tiered as new surface: a page that tells agent developers how to spend money. This round should be targeted fixes; the page does not need a rethink.
Findings
1. High · build/agents/buy.mdx:67: the MCP spending cap is optional, but the page says it is always applied.
The page says: "Every paid call over MCP carries a maxAmount and is refused before signing when the quote is above it." In 0.8.5, maxAmount is an optional input of buy_curl/buy_fetch (@celo/buy-mcp/dist/tools/pay-curl.js:24-27). It is applied only when the agent passes one (:107, ...(maxAmount ? { maxAmount: BigInt(maxAmount) } : {})), and it is in atomic units (6 decimals), not the decimal amount the CLI flag takes. If the account has no daily cap (none by default: buy-keystore/dist/spend-ledger.js:146, if (!account.dailySpendCap) return undefined), nothing bounds the call.
Runtime, against a local 0.05 USDC paywall:
buy_curl {maxAmount:"20000"}→Challenge amount 0.05 USDC exceeds cap 0.02 USDC (error code: amount_exceeds_max)buy_curl {}→ gets past the cap check and stops only atinsufficient_balancebecause the test wallet is empty. A funded wallet would have paid.
Failure scenario: an agent developer installs the MCP server and trusts the docs that a cap is always enforced. Their agent then calls buy_curl without maxAmount and pays whatever the 402 asks.
Fix (one sentence): "Pass maxAmount on every paid call: it is optional, in atomic units (20000 = 0.02 USDC), and without it the call is capped only by the account's daily cap, if you set one with buy account cap <name> <amount>."
2. High · build/agents/overview.mdx:61 and :63: the overview repeats the cap claim, and the next paragraph no longer reads correctly.
Line 61 says buy pays "with a spending cap on every call". That has the same problem as finding 1: the CLI applies the cap only when --max-amount is passed (buy/dist/commands/curl.js:37-38,147), and the MCP tool applies it only when maxAmount is passed. The next line, 63, still starts "Both settle on-chain in seconds…", but it now follows three bullets, and buy is a client, not something that settles.
Fix: reword line 61 to "…with a per-call spending cap you set (--max-amount)", and change "Both" to "x402 and MPP" (or move the buy bullet below that paragraph).
3. Medium · build/agents/buy.mdx:67: the steps for enabling buy_send are incomplete.
The page says buy_send "stays off unless you enable it with a budget or an allowlist". In 0.8.5 the tool is registered only when all of the following are set (buy-mcp/dist/server.js:12-21,32-38,66-74): BUY_MCP_ENABLE_SEND=1, BUY_MCP_SEND_ACCOUNT, and BUY_MCP_SEND_BUDGET or BUY_MCP_SEND_ALLOWLIST. Runtime: with ENABLE_SEND=1 and SEND_BUDGET=1 but no account, the server prints buy: NOT registering buy_send — no source account — set BUY_MCP_SEND_ACCOUNT… and the tool list has no buy_send.
Failure scenario: a reader sets a budget as the page says, and buy_send never shows up. Nothing on the page explains why.
Fix: name the three environment variables in that sentence.
4. Low · build/agents/buy.mdx:61-65: mcp install --client all registers buy only with Claude Code and Codex, not with every MCP client.
--client accepts claude | codex | all, and all means ['claude', 'codex'] (buy/dist/commands/mcp.js:17). The page says "Install the buy MCP server in your MCP clients".
Fix: "Register the buy MCP server with Claude Code and Codex. For other clients, configure npx --yes @celo/buy@0.8.5 mcp serve as a stdio server."
5. Low · build/agents/buy.mdx:54: the mainnet example does not run as written (AGENTS.md §5).
<paid-endpoint-url> is a placeholder. The page already uses a real paid route. buy quote shows that route offering 0.005 USDC/USD₮/USA₮ on celo, so this works and stays under the cap:
npx --yes @celo/buy@0.8.5 curl --max-amount 0.01 https://gateway.usebuy.ai/v1/social/x/posts/search \
-X POST -H 'content-type: application/json' -d '{"query":"celo"}'6. Low · build/agents/buy.mdx:77-81: the Troubleshooting table leaves out the two errors the page's own advice leads to (AGENTS.md §8.4).
A reader who follows "always set --max-amount" or "fund the printed address" will see these errors, which are observed verbatim above:
amount_exceeds_max(challenge amount 0.05 USDC exceeds cap 0.02 USDC). Nothing was signed. Raise--max-amountonly if the price is expected.insufficient_balance(Not enough to pay: this needs … but 0x… holds 0 USDC). Nothing was signed. Fund the account.
Not a finding, but must happen before merge
- CI has not run on this PR.
Documentation Validationfor6b5c33eisaction_requiredbecause a maintainer must approve workflows from a fork. So the PR body's statement "mint broken-links: not run locally; CI runs it on this PR" has not come true yet. My local run above passes. The workflow still needs approving so the check runs on GitHub. - The Mintlify fork preview check is
NEUTRALand is waiting for approval from someone with write access.
Verified good
npx --yes @celo/buy@0.8.5: 0.8.5 is stilllatest. Node.js 22+ matches the README.--sandboxis a global flag placed beforecurl. That is correct, because everything aftercurlis forwarded to curl. Sandboxquoteon the X search route shows acelo-sepoliaoffer of 0.005 USDC, which is inside the 1 USDC/day faucet grant (README). Chain IDs 11142220 and 42220 are right.setup --name <name>: the default network ismainnet.curl --max-amountrefuses before signing when the price is above the cap (runtime:challenge amount 0.05 USDC exceeds cap 0.02 USDC, exit 1).--tokenacceptsUSDC|USDT|USATand defaults to USDC.quotetakes curl arguments, needs no wallet, and prints token, price, network and recipient, thenNothing was signed or paid. A route that does not return 402 givesunexpected_response(observed with--json).receipts --resolveandreceipts --account <name>both exist. The meanings of500 provision_failed,500 settle_uncertain,4xxand503match the README.- MCP tools
buy_pay_quote,buy_curl,buy_balanceandbuy_whoamiall exist.buy_sendis off by default (runtime tool list). npx skills add celo-org/buy-skillmatches that repo's README, which ships four skills.- The Beta warning matches the npm README.
- Wiring:
build/agents/buysits in the Agents group right aftermpp, and the sidebar shows "buy (agent payments)". It is listed onai-resourcesunder "Celo tooling for agents" and onoverview, as AGENTS.md §8.9 requires. There is nollms.txtin the repo: Mintlify generates it from navigation plusdescription. The live file hasmppin that format, and the new page has both inputs.mint devdoes not servellms.txt, so I did not see the new line rendered. - Page anatomy follows AGENTS.md §3 for a guide: frontmatter, section order, a
Resourcestable, and aRelatedlist. - Writing USD₮ in prose follows the maintainer instruction on #2415 and 10 other pages. The stale rule is in AGENTS.md §7; it is tracked separately in #2427 so it does not block this PR.
- The
overview.mdxpunctuation edits are fine to keep. The "Real-World" heading slug staysagentic-activity-with-real-world-utility, and no page links to that anchor.
What the PR got right
It fills a real gap, and every command is pinned to an exact version. The sandbox-first structure means readers can try buy without risking money. The page describes the "do not retry on settle_uncertain" rule correctly, and the PR body says plainly what was and was not run.
Merge-order hazard
#2420 touches the same three files (docs.json Agents group, overview.mdx x402/MPP bullets, ai-resources.mdx). Its overview.mdx hunk changes line 59, right next to this PR's edits on lines 60-61, so whichever PR merges second will probably need a small rebase.
Follow-up issue (filed with this review)
- #2427: AGENTS.md §7 still says to write
USDT, notUSD₮, in prose, which contradicts #2415 and the current pages.
🤖 Generated with Claude Code
viral-sangani
left a comment
There was a problem hiding this comment.
+1 to Artu's points, esp the cap ones: maxAmount is optional and in atomic units, and the overview's 'spending cap on every call' isn't true. same for the buy_send env vars and --client all only meaning Claude Code + Codex
build/agents/buy.mdx:81: 'A 4xx or 503 response: refused before settlement, so nothing was charged' is too broad. our gateway settles before proxying, and a 503 relayed from the upstream is charged. third-party sellers settle however they want too. would say: check whether a payment receipt came back, or run buy receipts --resolve, before assuming nothing was charged, and don't auto-retry
|
@benibauer3, FYI: the review above is REQUEST-CHANGES at 🤖 Generated with Claude Code |
|
@szapelao, FYI: Artu's review above is REQUEST-CHANGES at |
|
Correction to my review: @viral-sangani is right about In Finding 7 · Medium · The verdict stays REQUEST-CHANGES. There are now 7 findings at 🤖 Generated with Claude Code |
|
@szapelao, here is a patch that applies the 7 findings from Artu's and Viral's reviews at What it changes:
diff --git a/build/agents/buy.mdx b/build/agents/buy.mdx
index f567b44..0736c1e 100644
--- a/build/agents/buy.mdx
+++ b/build/agents/buy.mdx
@@ -50,21 +50,24 @@ Fund the printed address with a small amount of USDC, USD₮, or USA₮ on Celo
Every paid call should carry `--max-amount`. buy refuses to sign when the quote is above it:
```bash
-# Celo mainnet (42220), pays at most 0.02 USDC
-npx --yes @celo/buy@0.8.5 curl --max-amount 0.02 <paid-endpoint-url>
+# Celo mainnet (42220), pays at most 0.01 USDC
+npx --yes @celo/buy@0.8.5 curl --max-amount 0.01 https://gateway.usebuy.ai/v1/social/x/posts/search \
+ -X POST -H 'content-type: application/json' -d '{"query":"celo"}'
```
USDC is the default token. Add `--token USDT` or `--token USAT` to pay in one of those instead; the service must offer that token in its `402` response.
## Give an agent payment tools
-Install the buy MCP server in your MCP clients:
+Register the buy MCP server with Claude Code and Codex:
```bash
npx --yes @celo/buy@0.8.5 mcp install --client all
```
-The agent gets tools such as `buy_pay_quote`, `buy_curl`, `buy_balance` and `buy_whoami`. Every paid call over MCP carries a `maxAmount` and is refused before signing when the quote is above it. `buy_send`, which moves money directly, stays off unless you enable it with a budget or an allowlist.
+For any other MCP client, configure `npx --yes @celo/buy@0.8.5 mcp serve` as a stdio server.
+
+The agent gets tools such as `buy_pay_quote`, `buy_curl`, `buy_balance` and `buy_whoami`. Pass `maxAmount` on every paid call: it is optional, in atomic units (`20000` is 0.02 USDC), and without it the call is capped only by the account's daily cap, if you set one with `buy account cap <name> <amount>`. `buy_send`, which moves money directly, is off by default. To turn it on, set `BUY_MCP_ENABLE_SEND=1`, `BUY_MCP_SEND_ACCOUNT`, and either `BUY_MCP_SEND_BUDGET` or `BUY_MCP_SEND_ALLOWLIST`.
The MCP server gives an agent the ability to pay. The [buy skills](https://github.com/celo-org/buy-skill) teach it how to use that safely: read the free catalog, quote the exact request, get your approval for the price, pay once, and report the transaction hash.
@@ -78,7 +81,9 @@ npx skills add celo-org/buy-skill
|-------|------------|
| `500 provision_failed` or `500 settle_uncertain` | Do not retry automatically: the payment may already have settled. Run `buy receipts --resolve` to ask the token contract whether it did. |
| `unexpected_response` from `buy quote` | The route answered with something other than `402`, so it is not a paid endpoint. Check the URL. |
-| A `4xx` or `503` response | The service refused the request before settlement, so nothing was charged. |
+| `amount_exceeds_max` | The quote is above your `--max-amount` (or `maxAmount`). Nothing was signed. Raise the cap only if the price is expected. |
+| `insufficient_balance` | The wallet holds less than the price. Nothing was signed. Fund the account. |
+| A `4xx` or `503` response | With `paymentSettled: false` in the body, or no `X-PAYMENT-RESPONSE` header, the request was refused before settlement. Otherwise it may have been charged: check for a receipt, or run `buy receipts --resolve`, before retrying, and do not retry automatically. |
`buy receipts --account <name>` lists your local payment history, including each settlement transaction.
diff --git a/build/agents/overview.mdx b/build/agents/overview.mdx
index b848eca..a308994 100644
--- a/build/agents/overview.mdx
+++ b/build/agents/overview.mdx
@@ -58,9 +58,9 @@ Agents on Celo can charge and pay for services over plain HTTP, settling in stab
- **[x402](/build/agents/x402)** gives meaning to the HTTP `402 Payment Required` status code, letting an agent settle a stablecoin micropayment inline with the request.
- **[MPP (Machine Payments Protocol)](/build/agents/mpp)** is a separate protocol that uses the same `402` flow, so any service can charge USDC per request. On Celo, it settles through the same hosted facilitator as x402 — the buyer pays no gas.
-- **[buy](/build/agents/buy)** is Celo's x402 payment client: it lets an agent or a script pay for paid HTTP APIs in stablecoins, with a spending cap on every call.
+- **[buy](/build/agents/buy)** is Celo's x402 payment client: it lets an agent or a script pay for paid HTTP APIs in stablecoins, with a per-call spending cap you set (`--max-amount`).
-Both settle on-chain in seconds, making them well-suited to paid APIs, pay-per-use tools, and agent-to-agent commerce. A paid API, MCP server, or bot can also carry its own ERC-8004 identity, so agents can discover it and rate it — see [Register a service](/build/agents/8004#register-a-service).
+x402 and MPP settle on-chain in seconds, making them well-suited to paid APIs, pay-per-use tools, and agent-to-agent commerce. A paid API, MCP server, or bot can also carry its own ERC-8004 identity, so agents can discover it and rate it — see [Register a service](/build/agents/8004#register-a-service).
## Giving an agent a wallet
|
Adds a page for buy (@celo/buy), Celo's x402 payment client, which had no page in the docs and was missing from llms.txt. buy was only mentioned on x402-get-discovered, as a catalog for sellers.
What this does:
What this does NOT do:
Verification:
buy created sandbox account 0x5d5674DF7F6A9229cC74417335Be6A6613f7d828 on celo-sepolia (test funds only)
buy sandbox: funded 0x5d5674DF7F6A9229cC74417335Be6A6613f7d828 with 1 USDC (tx 0x3ceeeef2decd0caa9e33e9c2fdcc47b9166f9ff23c5f7ab60dc022164164a6bf)
Judgement calls:
@artugrande could you review for accuracy against the current buy release?