Metering & Payments

Every REST/MCP call is metered and attributed to its principal; paid calls are gated (x402 / MPP) or billed (Stripe). metering = metered? · payments = paid?

call attribute UsageEvent billable events → Stripe sink REST / MCP call + bearer token @agentback/metering · the “metered?” answer (also the rung-1 audit log) principal {user} / {client} authentication-oauth2 = billable identity MeteredRestServer .dispatch (REST seam) MeteredMCPServer .dispatchTool (MCP seam) Meter observe() status + latency + units CompositeUsageSink fan-out to N sinks InMemory dev/test JSONL audit log Redis shared QuotaService per-principal · metered? enforce metering / seam sink / quota payment rail (gate) identity external we don’t settle @agentback/payments · the “paid?” answer · we orchestrate, we don’t settle paymentMiddleware REST · PaymentRail.authorize x402 HTTP 402 USDC · L2 MPP pre-auth sessions X-MPP-SESSION PaidMCPServer MCP · dispatchTool gate tool error _meta: challenge (no 402) agent pays → retries StripeMeterSink a UsageSink — bills, does not gate status:'ok' → meter event Stripe Billing meter events → invoice (fiat) facilitator / processor (external) verifies + settles — injected, not us no/invalid payment → 402 + requirements

Metering — the “metered?” answer

  • MeteredRestServer / MeteredMCPServer wrap dispatch
  • Meter.observe() times the call → a UsageEvent
  • • Sinks: InMemory · JSONL (audit) · Redis · Composite fan-out
  • QuotaService enforces per-principal limits
  • • Attributed to the auth principal — the billable identity

Gating rails — the “paid?” answer

  • x402paymentMiddleware → HTTP 402, USDC/L2
  • MPP — pre-auth sessions (X-MPP-SESSION)
  • PaidMCPServer — no 402 over JSON-RPC, so the challenge rides back as a tool error in _meta; the agent pays and retries
  • • Settlement is delegated to an external facilitator/processor

Stripe — reports, doesn’t gate

  • StripeMeterSink is a UsageSink, not a rail
  • • Billable events → Stripe metered billing → invoice (fiat)
  • • Compose with the audit sink via CompositeUsageSink
  • • “Same units, different rail” — record once, bill from it