Skip to content

Add post-payment delivery validation without retrying possible spend #651

Open

Description

@epistemedeus

Is your feature request related to a problem? Please describe.

The AgentCore Payments LangGraph middleware and Strands plugin can detect a
payment challenge, obtain a credential, retry the tool, and return the paid
result. There is no opt-in application-output gate between that paid retry and
result promotion.

That leaves a buyer unable to reject malformed or contract-invalid application
output while preserving two facts: a payment credential may already have spent,
and the middleware must not automatically pay or retry again.

A credential-free reproduction uses a fake PaymentManager and a local tool:

  1. The first tool call returns an x402 or MPP payment challenge.
  2. The fake manager returns one payment credential.
  3. The paid retry returns HTTP 200 with malformed application output.
  4. The current middleware returns that output through LangGraph sync,
    LangGraph async, or Strands without a buyer-owned validation hook.

No AWS account, wallet, signature, or live payment is needed to reproduce the
control-flow gap.

Describe the solution you'd like

Add an optional post-payment delivery callback to the existing integrations.
When configured, it should:

  • receive the raw paid result plus an immutable snapshot of the selected
    payment requirement or challenge;
  • run after exactly one credential generation and one paid retry;
  • preserve the original paid result and explicit possible-spend evidence when
    validation rejects or raises;
  • return a deterministic failure through the native LangGraph or Strands path;
  • set native retry behavior so the same result cannot trigger another automatic
    payment attempt; and
  • leave current behavior unchanged when the callback is absent.

Protocol-native evidence should retain its authority label. An x402 Payment
Response or MPP Receipt can be exposed as observed, unverified evidence. Calling
settlement verified should require a separate protocol-specific verifier that
reconciles the native transaction or reference against the frozen payment
terms.

The three public integration paths should share the same semantics:

  • LangGraph wrap_tool_call
  • LangGraph awrap_tool_call
  • Strands after_tool_call

Describe alternatives you've considered

  • Tool-specific wrappers duplicate payment middleware and can lose the selected
    challenge and possible-spend context.
  • LLM inspection after the result returns is not a fail-closed output contract.
  • Requiring a seller to echo protocol, network, scheme, challenge or offer ID,
    amount, asset, payee, credential digest, and transaction in one custom bag is
    not portable. Standard x402 settlement responses and MPP receipts do not echo
    that complete set, and seller-authored echoes are not independent settlement
    verification.

Additional context

Current source references:

The repository's current contribution policy asks external users to report
problems and request features rather than submit code pull requests, so this is
intentionally a feature request without an external patch.

Activity

  1. rajuans commented on Aug 27, 2026

    @rajuans
    Contributor

    Thanks for opening the issue. Here is my comment.

    There is no opt-in application-output gate between that paid retry and
    result promotion.

    Result promotion is not in the control of the payments plugin/middleware. Agents tool infrastructure crafts the response. Developer can put post-processing handler to ignore or modify the response after the tool call.

    I think what would be helpful here is to have a callback before payment processing where developer can put the logic to skip the payment processing completely for invalid application. This will also avoid doing unnecessary payment processing (and incurring cost) if developer doesn't want to pay to a specific endpoint.

  2. epistemedeus commented on Aug 27, 2026

    @epistemedeus
    Author

    Thanks, this direction leaves a concrete residual in the payment integrations. I implemented and replayed a credential-free prototype across the three exported paths, without opening a pull request because the repository's contribution policy currently asks external users to file feature requests.

    The proposed contract is one optional on_before_payment callback after 402 extraction and before credential generation, automatic session creation, or a paid retry. It receives a copied challenge and tool-input snapshot. None or PROCEED continues, SKIP preserves the original unpaid 402, and exceptions or unsupported returns propagate without becoming payment authority.

    The exact signed prototype is c264aeb. It exercises LangGraph sync, LangGraph async, and Strands. The accepted replay is 51 focused callback and documentation probes plus 952 payment-package tests with nine testnet-environment skips. Ruff, format, bounded mypy, and Bandit pass. It called no AWS service, wallet, seller, or paid route.

    One review detail was important: the endpoint examples parse the URL and require an exact normalized HTTPS hostname, rather than using substring matching that could accept an attacker-controlled hostname.

    If this API shape matches the maintainer intent, I can recut it into a pull request or a narrower patch.

  3. TheAliphant commented on Sep 26, 2026

    @TheAliphant

    MACH Base is live x402 infrastructure for Base-chain reads with no signup or API key. We are trying to verify the cleanest caller-pays integration path for your agent/runtime. A live compatibility call is GET https://api.mach.gallery/api/base/block-number ($0.005 USDC on Base); discovery: https://api.mach.gallery/.well-known/x402 ; OpenAPI: https://api.mach.gallery/openapi.json . If this fits your stack, one real paid call is enough to validate it. If not, a short note on the blocking integration/policy is useful. MACH conversation=95f56594b3944ead32a0388c.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions