Skip to content

Add paid HTTP client command - #13

Open
ai-virtual-b wants to merge 5 commits into
mainfrom
paid-http-client
Open

Add paid HTTP client command#13
ai-virtual-b wants to merge 5 commits into
mainfrom
paid-http-client

Conversation

@ai-virtual-b

@ai-virtual-b ai-virtual-b commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add acp http <url> as a generic HTTP caller for agents, separate from ACP job lifecycle commands.
  • Default behavior is query-only: it sends one HTTP request and surfaces the response, including any 402 Payment Required.
  • Add --pay to explicitly opt into paying supported x402/MPP challenges with the active ACP agent wallet and retrying the request.
  • Support --protocol auto|x402|mpp, custom methods/headers, raw/file/JSON request bodies, response headers, output files, and JSON output.
  • Use official x402 client primitives for x402 typed-data payment payloads and official mppx client primitives for MPP Tempo push-mode credentials.

CLI Workflow

1. Query an endpoint without paying

acp http https://api.example.com/paid-resource

This makes a single request. If the endpoint is paid, the CLI returns the 402 response to the agent. No wallet signing, payment submission, retry, or saved payment state happens.

For JSON POST:

acp http -X POST --json-body '{"prompt":"hello"}' https://api.example.com/jobs

2. Decide whether to pay

The agent inspects the 402 response from step 1 and decides whether the price/protocol is acceptable.

If the agent decides not to pay, the workflow stops after step 1.

3. Pay and retry explicitly

acp http --pay https://api.example.com/paid-resource

This is a new CLI invocation. It does not reuse hidden state from the query command.

Internal flow for this --pay command:

  1. CLI sends the request.
  2. Endpoint returns a fresh 402 with x402 or MPP challenge details.
  3. CLI parses the challenge.
  4. CLI uses the active ACP agent wallet/signer to create the protocol payment credential.
  5. CLI retries the same request with the payment header.
  6. Endpoint returns the paid response.

For JSON POST:

acp http --pay -X POST --json-body '{"prompt":"hello"}' https://api.example.com/jobs

4. Force a protocol when the agent already knows it

acp http --protocol x402 https://api.example.com/x402-endpoint
acp http --protocol mpp https://api.example.com/mpp-endpoint

To pay:

acp http --pay --protocol x402 https://api.example.com/x402-endpoint
acp http --pay --protocol mpp https://api.example.com/mpp-endpoint

--protocol auto is the default. In query mode, auto/MPP requests include Accept-Payment: tempo/charge so MPP endpoints can return useful challenge details, but the CLI still does not pay unless --pay is present.

Payment Details

  • x402: parses x402 payment requirements from the 402, creates a payment payload through the x402 client, signs EIP-712 typed data using the active ACP agent wallet signer, then retries with the x402 payment header.
  • MPP: parses the MPP WWW-Authenticate: Payment ... challenge, creates an MPP credential through mppx, uses ACP wallet adapter calls for Tempo push-mode payment, then retries with the MPP Authorization credential.
  • No separate wallet/private key/SDK install is required for the caller beyond the configured ACP CLI agent wallet.

Tests

  • npx tsc --noEmit
  • npm run acp -- http --help
  • No-pay non-402 POST smoke test: request count = 1
  • No-pay 402 smoke test: returns status 402, request count = 1, no retry
  • --json HTTP 500 smoke test: exits with code 1

Notes

  • This PR does not fully prove live x402/MPP settlement end-to-end; that still requires funded wallets, supported chains, and real paid endpoints.
  • npm run build may fail in this local sandbox because TypeScript cannot create dist; npx tsc --noEmit passes.
Comment thread src/commands/http.ts
Comment thread src/commands/http.ts Outdated
Comment thread src/commands/http.ts Outdated
@ai-virtual-b

Copy link
Copy Markdown
Contributor Author

Bugbot follow-up fixes pushed in 41efadb:

  • Cached MPP viem client instances per chain so sendCalls/getCallsStatus share sentCalls state.
  • Reworked auto mode to reuse the first 402 response for x402/MPP credential creation instead of invoking wrappers that issue another unpaid probe.

Validation after the change:

  • npx tsc --noEmit
  • npm run acp -- http --help
  • local non-402 POST smoke test confirmed request count remains 1
  • local --json HTTP 500 smoke test exits with code 1

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 41efadb. Configure here.

Comment thread src/commands/http.ts Outdated
@ai-virtual-b

Copy link
Copy Markdown
Contributor Author

Latest Bugbot finding fixed in 8902193:

  • Auto-mode probes now include Accept-Payment: tempo/charge so MPP servers can return the same challenge shape as explicit --protocol mpp.
  • The first 402 response is still reused, so this does not reintroduce the duplicate unpaid probe.

Validation:

  • npx tsc --noEmit
  • npm run acp -- http --help
  • local auto-mode POST smoke test confirmed request count = 1 and Accept-Payment = tempo/charge
  • local --json HTTP 500 smoke test exits with code 1
@ai-virtual-b

Copy link
Copy Markdown
Contributor Author

Updated the CLI semantics in 4dc2124:

  • acp http <url> now makes a single query request and surfaces the response, including 402 challenges. It does not sign/pay/retry.
  • acp http --pay <url> opts into signing/paying supported x402/MPP challenges with the active agent wallet and retrying.
  • Query mode still sends Accept-Payment: tempo/charge for auto/MPP discovery so MPP endpoints can return useful 402 challenge details.

Validation:

  • npx tsc --noEmit
  • npm run acp -- http --help
  • no-pay non-402 POST: request count = 1
  • no-pay 402: returned status 402, request count = 1, no retry
  • JSON HTTP 500 still exits with code 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant