Skip to content

docs(agentic-payments): production patterns for x402 + MPP - #97

Open
Eras256 wants to merge 1 commit into
stellar:mainfrom
Eras256:agentic-payments-production-patterns
Open

docs(agentic-payments): production patterns for x402 + MPP#97
Eras256 wants to merge 1 commit into
stellar:mainfrom
Eras256:agentic-payments-production-patterns

Conversation

@Eras256

@Eras256 Eras256 commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Fresh proposal per Kaan's note closing #14: that PR targeted files removed in the #17 restructure, so it couldn't be rebased. He confirmed the current skills/agentic-payments/SKILL.md doesn't yet cover four of the patterns from the old PR, and invited a fresh PR proposing them individually. This is that — re-verified against a service that's been running x402 and MPP Charge in production, not copied from the old diff.

Landing against x402.md and mpp.md (the detail files SKILL.md routes to), not SKILL.md itself, since it's a decision table and these are implementation patterns.

What changed and why each one still holds up (re-checked today, not assumed from the old PR):

  • Multi-route pricing with paymentMiddlewareFromConfig (x402.md) — the seller example in the skill prices a single route. This documents the config-object form for pricing several routes behind one middleware call, with the route-keyed shape and scheme/facilitator wiring spelled out. Matches what's running behind a production endpoint pricing three routes at three different amounts, cited with its first on-chain settlement.

  • Recipient resolution that fails open (mpp.md) — a server that throws at import time because STELLAR_RECIPIENT is unset breaks CI and any environment without secrets provisioned yet. Included is a specific recovery case worth calling out on its own: a secret key (S...) landing in the public-key env var, which a platform's env UI can make easy to do by accident — recovered with a loud warning instead of a cryptic downstream throw.

  • Optional dual-intent server (mpp.md) — reframed from the old PR, not copied. The old version implied running Charge and Session together in production; that's not accurate today. What is true and worth documenting: each intent gets its own SDK instance, gated independently by its own env vars, with route middleware no-op'ing (not throwing) when its instance is null. That's a real, useful pattern regardless of which intents a given deployment actually turns on.

  • /info discovery endpoint (mpp.md) — reports which intents are actually live by reading the same runtime state the middleware checks (e.g. !!chargeInstance), so it doubles as a health check instead of a static claim that can drift from reality.

Verified: pnpm lint:ts, pnpm lint, pnpm sync:skills, and pnpm generate:llms-txt all pass clean against the new content.

Happy to split this into separate PRs per pattern if that's easier to review — bundled them here since the recipient-resolution section is referenced from the pricing section via anchor link, but they don't otherwise depend on each other.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

Adds three patterns verified against a service that has been billing
real USDC over MPP Charge and x402 in production:

- Multi-route pricing with paymentMiddlewareFromConfig (x402.md)
- Recipient resolution that fails open instead of crashing on missing
  or misconfigured STELLAR_RECIPIENT, including recovery when a secret
  key lands in the public-key env var (mpp.md)
- Optional dual-intent server: Charge and Session gated independently
  by their own env vars, each middleware no-op'ing rather than
  throwing when its intent isn't configured (mpp.md)
- A runtime-accurate /info discovery endpoint reporting which intents
  are actually live, not a static capability list (mpp.md)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings August 15, 2026 01:52
@kaankacar

Copy link
Copy Markdown
Contributor

🤖 Automated message from Kaan's Automated Triage Bot.

👀 Picked this up — a review will follow shortly.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds practical documentation for configuring paid routes with x402 and for running MPP Charge/Session together in production without crashing on missing/mis-set secrets.

Changes:

  • Document paymentMiddlewareFromConfig for pricing multiple x402 routes with per-route prices.
  • Add “Production patterns” guidance for MPP (fail-open recipient resolution, optional dual-intent setup, and an /info discovery endpoint).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
skills/agentic-payments/x402.md Adds multi-route pricing example using paymentMiddlewareFromConfig and guidance to fail open when recipient config is missing.
skills/agentic-payments/mpp.md Adds production-ready patterns and example code for resilient configuration and runtime discovery.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.


## Pricing multiple routes with `paymentMiddlewareFromConfig`

The seller example above prices a single route through `paymentMiddleware` +
Comment on lines 217 to 218
**Env vars (server):** `CHANNEL_CONTRACT`, `COMMITMENT_PUBKEY`, `MPP_SECRET_KEY`, `FEE_PAYER_SECRET`
**Env vars (client):** `COMMITMENT_SECRET`
Comment on lines +296 to +301
process.env.MPP_CHANNEL_CONTRACT &&
process.env.MPP_COMMITMENT_KEY &&
RECIPIENT &&
process.env.MPP_SECRET_KEY
)
? Mppx.create({ methods: [stellarChannel.channel({ channel: process.env.MPP_CHANNEL_CONTRACT, /* ... */ })] })
Comment on lines +291 to +302
const chargeMppx = (RECIPIENT && process.env.MPP_SECRET_KEY)
? Mppx.create({ methods: [stellar.charge({ recipient: RECIPIENT, /* ... */ })] })
: null;

const sessionMppx = (
process.env.MPP_CHANNEL_CONTRACT &&
process.env.MPP_COMMITMENT_KEY &&
RECIPIENT &&
process.env.MPP_SECRET_KEY
)
? Mppx.create({ methods: [stellarChannel.channel({ channel: process.env.MPP_CHANNEL_CONTRACT, /* ... */ })] })
: null;
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.

3 participants