Skip to content

Add --x402-max-amount local spend limit for x402 sessions - #372

Open
jancurn wants to merge 6 commits into
mainfrom
claude/pr-369-review-ujpqzu
Open

jancurn wants to merge 6 commits into
mainfrom
claude/pr-369-review-ujpqzu

Conversation

@jancurn

@jancurn jancurn commented Aug 14, 2026 •

Copy link
Copy Markdown
Member

An x402 session currently pays whatever a tool call turns out to cost. --x402-max-amount <usd> caps every single payment — a payment above the cap is refused locally, before anything is signed, and the call fails with the amount that was asked for.

  • checked in signPayment(), the one choke point all three payment paths share (proactive _meta.x402 signing, HTTP 402 challenges, payment-required tool results)
  • set per session on connect, stored in sessions.json and restored on restart
  • tools-call --x402-max-amount replaces it for one call, higher or lower — so the session value is a default rather than a ceiling, as the help text says. It travels in async context, since the limit is read when a 402 comes back and calls can overlap.
  • for upto, caps the maximum authorization you sign; a refusal is never swallowed as "signing failed", so a call can't quietly go out unpaid

Refs #369, which proposed the same local guard bundled with a hardcoded third-party payment-approval service. This is the local half only: no network call, no vendor, no extra payment per tool call.

https://claude.ai/code/session_011DCnYpi347tXWKMrhmVgLB

An x402 session currently pays whatever a tool call turns out to cost.
--x402-max-amount <usd> caps every single payment: the amount is checked in
signPayment(), the one choke point all three payment paths go through
(proactive _meta.x402 signing, HTTP 402 challenges, and payment-required tool
results), so a payment over the cap is refused before anything is signed and
the call fails with the amount that was asked for.

The cap is stored in sessions.json and restored on reconnect and restart, so a
crashed session comes back capped rather than uncapped.

Refs #369, which proposed the same local guard alongside a hardcoded
third-party payment-approval service. This is the local half only: no network
call, no vendor, no extra payment per tool call.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011DCnYpi347tXWKMrhmVgLB
jancurn and others added 5 commits September 14, 2026 16:01
Resolves the SKILL.md conflict between the --x402-max-amount note and the
settlement-receipt note from #399 by keeping both.

Refs #369

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011DCnYpi347tXWKMrhmVgLB
Resolves the CHANGELOG conflict by keeping the --x402-max-amount entry
alongside the MCP Skills extension entries from #401.

Refs #369

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011DCnYpi347tXWKMrhmVgLB
The session's --x402-max-amount applies to every payment it makes, so a script
that wants a tighter cap on one risky call — or a higher one for a single
expensive tool — had to close the session and reconnect.

tools-call --x402-max-amount <usd> now replaces the session's limit for that
call, higher or lower, and works on a session that set no limit of its own. The
refusal message names which of the two limits applied, so the caller knows
whether to change the flag or reconnect.

The limit travels in async context rather than on a shared bridge field: it is
read when a 402 comes back inside the fetch middleware, long after the call
starts and concurrently with other calls, so a field would hand one call's limit
to another. (The --timeout override next to it can use a plain field precisely
because the client reads it synchronously as the request starts.)

Since the per-call value may also raise the session's, the session limit is a
default rather than a ceiling — the help text says so.

Refs #369

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011DCnYpi347tXWKMrhmVgLB

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants