feat(payments): add MPP, x402 upto, and Quick Create support - #643
Merged
Conversation
Add MPP alongside the existing x402 protocol in ProcessPayment. MPP servers
answer 402 with WWW-Authenticate: Payment challenges; the SDK selects the one
challenge the payment instrument can satisfy and mints an Authorization header.
Core:
- mpp.py: parse WWW-Authenticate challenges and select one (charge intent,
unexpired, method the instrument satisfies: evm/tempo->ETHEREUM,
solana->SOLANA; ordered by NETWORK_PREFERENCES, tiebroken on soonest expiry
then server order). The selected challenge is forwarded verbatim so the
challenge HMAC stays valid, and unknown auth-params are preserved per the
spec's "unknown parameters must be ignored by clients" rule.
- generate_payment_header auto-detects the protocol from the 402 and returns
{"Authorization": "Payment <token>"} for MPP; the x402 path is unchanged.
When a 402 advertises both protocols and no MPP challenge is satisfiable, it
falls back to a usable x402 requirement rather than failing the payment. The
fallback is limited to selection failures (pre-submission); a failure after
the payment was submitted propagates, so a buyer is never charged twice.
- Optional buyer_pays_gas_fees passthrough (MPP buyerPaysGasFees). Requires None
or an actual bool and forwards it unchanged — values are not coerced, since
bool("false") is True and would silently authorize wallet charges.
Integrations:
- Strands plugin and LangGraph middleware detect MPP 402s (WWW-Authenticate) and
settle them; buyer_pays_gas_fees is exposed on the shared config.
- has_mpp_challenge delegates to the parser so detection and parsing cannot
disagree (a prefix check missed "Bearer ..., Payment ..." and falsely matched
a hypothetical PaymentXYZ scheme).
Notes:
- Submitting MPP requires a botocore release that models the MPP ProcessPayment
shapes. On an older release botocore rejects the request client-side with
'Unknown parameter in paymentInput: "mpp"'. The integ tests surface this
dependency explicitly so it is diagnosed as an out-of-date botocore rather
than an SDK bug.
- Solana localnet is intentionally not aliased to solana-testnet: it is a
distinct local RPC/Surfpool environment, and aliasing let a local-only
challenge outrank a payable devnet challenge. Unmapped networks are unranked
rather than misranked — still selectable when they are the only option.
Tests: unit coverage for parsing, selection, manager routing, dual-protocol
fallback, gas-fee validation, and both integrations; integ tests gated on TEST_*
env vars, including live checks against the mpp.dev endpoint.
Verified against the live mpp.dev 402 and prod ProcessPayment (request shape
accepted; end-to-end settlement pending account MPP entitlement).
Co-authored-by: Raju Ansari <ansraju@amazon.com>
Adds an opt-in permit2_allowance_limit knob so the Strands plugin and LangGraph middleware can grant a Permit2 allowance for the x402 "upto" scheme. When set, ProcessPayment submits the one-time on-chain approve to the Permit2 contract before signing; when unset (default), the exact-scheme flow is unchanged. - manager.generate_payment_header: new optional permit2_allowance_limit param, injected at the cryptoX402 level (sibling of version/payload) only when set. - integrations config: new permit2_allowance_limit field (decimal string in the asset's smallest denomination) with positive-integer validation in __post_init__; None by default. - Strands plugin + LangGraph middleware: thread config.permit2_allowance_limit into generate_payment_header. - Tests: manager injection + omission cases; config validation (valid 1 USDC / uint256-max unlimited, reject 0/-1/1.5/abc/empty/non-string). upto + permit2AllowanceLimit are already merged on the service and public model mainline. This mirrors the buyer_pays_gas_fees config-knob pattern.
Contributor
✅ No Breaking Changes DetectedNo public API breaking changes found in this PR. |
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
requested a deployment
to
manual-approval
August 17, 2026 14:42 — with
GitHub Actions
Waiting
aidandaly24
had a problem deploying
to
auto-approve
August 17, 2026 16:35 — with
GitHub Actions
Failure
aidandaly24
had a problem deploying
to
auto-approve
August 17, 2026 16:35 — with
GitHub Actions
Failure
Contributor
|
Claude Security Review: no high-confidence findings. (run) |
…onnector Thread a provision_mode arg through PaymentClient.create_payment_connector to the CreatePaymentConnector request (provisionMode), and surface the authorizationUrl the service returns for a QUICK_CREATE connector in PENDING_AUTHENTICATION. Add the PaymentConnectorProvisionMode enum (MANUAL/QUICK_CREATE) and the QUICK_CREATE connector statuses (PENDING_AUTHENTICATION, PROVISIONING, AUTHENTICATION_EXPIRED, AUTHENTICATION_FAILED) to constants, exported from the package. MANUAL behaviour is unchanged: provisionMode is omitted from the request when provision_mode is not supplied, and authorizationUrl is only added to the result when present. Signed-off-by: ykas11 <vikas.k.walunj@gmail.com>
Contributor
|
Claude Security Review: no high-confidence findings. (run) |
jariy17
previously approved these changes
Aug 18, 2026
Contributor
|
Claude Security Review: no high-confidence findings. (run) |
jariy17
approved these changes
Aug 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds three incremental payment capabilities to the AgentCore Python SDK.
Machine Payments Protocol (MPP)
WWW-Authenticate: Paymentchallenges and selects one compatible with the configured payment instrument.ProcessPaymentand returnsAuthorization: Payment <credential>.buyer_pays_gas_fees.x402
uptopermit2_allowance_limitintegration setting.cryptoX402.permit2AllowanceLimitonly for a selecteduptorequirement.PaymentConnector Quick Create
PaymentConnectorProvisionModewithMANUALandQUICK_CREATE.PaymentClient.create_payment_connector.authorizationUrlfrom create and get responses while the connector isPENDING_AUTHENTICATION.wait_for_ready=Truefor Quick Create because user consent must happen before the connector can become ready.PENDING_AUTHENTICATION,PROVISIONING,AUTHENTICATION_EXPIRED, andAUTHENTICATION_FAILED.provisionModewhen it is not supplied.Release Dependencies
This change requires
boto3>=1.43.72andbotocore>=1.43.72, the first published model release containing:permit2AllowanceLimit.provisionMode, Quick Create statuses, andauthorizationUrl.The package dependency floor and lockfile enforce that requirement.
Verification
495 passed.901 passed, 9 skipped.3360 passed, 10 skipped, 4 xpassed.mpp.devdetection/header-preservation tests passed.8 passed, 6 resource-dependent skipped.uv buildproduced the wheel and source distribution.1.43.72versions.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.