Skip to content

fix(x402): never settle for a disconnected buyer + expose agent maxConcurrentRuns - #743

Closed
bussyjd wants to merge 2 commits into
mainfrom
fix/zombie-settle-and-max-concurrent-runs
Closed

fix(x402): never settle for a disconnected buyer + expose agent maxConcurrentRuns#743
bussyjd wants to merge 2 commits into
mainfrom
fix/zombie-settle-and-max-concurrent-runs

Conversation

@bussyjd

@bussyjd bussyjd commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Closes #742.

What

Two config/verifier-side fixes for the paid-agent path (no hermes upstream changes), root-caused from the Bankr bot's failed paid calls and validated live on base mainnet:

  1. Agent.spec.maxConcurrentRuns — rendered as gateway.api_server.max_concurrent_runs in the agent's config.yaml. Nil omits the block (Hermes internal default, 10); 0 disables the in-process cap so edge concurrency middleware is the single gate. Existing agents render byte-identical (confighash suite untouched and green).
  2. x402 verifier settle-guard — skip settlement when the buyer's request context is already canceled at settle time. A disconnected buyer must never be debited for a response nobody receives. Reason client_disconnected; the interceptor hijacks the write path so nothing is written to the dead socket.

Why (see #742 for the full trace)

  • The buyer-charged-for-nothing case was proven on-chain: a client abort that doesn't propagate past cloudflared leaves the agent run completing "successfully" → verifier settles → buyer debited, response undelivered. This is exactly Bankr's "payment made but no completion" report.
  • The agent's in-process cap (default 10) was not settable from the CR at all, while the Traefik inFlightReq middleware was the actually-binding external gate — two inconsistent numbers on the same path.

Validation

  • go build ./... + full test run: internal/monetizeapi, internal/serviceoffercontroller, internal/x402, internal/embed all green (493 PASS); new tests: TestRenderHermesConfig_MaxConcurrentRunsZero, ...NilOmitsGateway, TestForwardAuth_NoSettleOnClientDisconnect (guard fires: verifyCalled=1, settleCalled=0).
  • Live A/B on silvernuc3 (mainnet wallet, real settlements): pre-fix 12 concurrent paid requests → 4×200 + 8×429; post-fix (maxTurns 12 + cap 0 + edge 24) → 12×200, wallet −$0.12 exactly, zero spurious charges.

Note: until the controller image carrying this lands, the live hyperliquid-analyst cap-off is a hash-gated manual ConfigMap edit (flagged ConfigDrift) — any Agent CR spec change wipes it. After merge + controller roll: set spec.maxConcurrentRuns: 0 on the CR to make it durable.

https://claude.ai/code/session_014YjPMViNrZ7zBVgUQzwEKk

bussyjd added 2 commits July 14, 2026 10:05
Renders gateway.api_server.max_concurrent_runs into the agent's
config.yaml. Nil omits the gateway block (Hermes internal default, 10);
0 disables the in-process cap so edge concurrency middleware governs
instead. Existing agents render byte-identical.

Part of #742.

Claude-Session: https://claude.ai/code/session_014YjPMViNrZ7zBVgUQzwEKk
If the buyer's request context is already canceled when the upstream
handler succeeds, do not settle — the buyer would be debited for a
response nobody receives (proven on-chain against hyperliquid-analyst,
see #742). Reports failure reason client_disconnected; the interceptor
hijacks the write path so nothing reaches the dead socket.

Fixes the propagated-cancel leg of #742.

Claude-Session: https://claude.ai/code/session_014YjPMViNrZ7zBVgUQzwEKk
@bussyjd

bussyjd commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #749 (integration/v0.13.0-rc4) — this branch is merged into the integration branch verbatim (merge commits a02b62f/7d963125) and ships there. Validated by the fully green release smoke rc4-run7-20260714-171005 (18/18 flows incl. flow-13/14, on-chain receipts in #749).

@bussyjd bussyjd closed this Jul 14, 2026
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.

Paid agents: buyers charged for undelivered responses (zombie settlement) + inconsistent concurrency gates

1 participant