Commands
agent-commerce doctor
Diagnose config, gateway, backend, protocol and payment health — against the live gateway.
agent-commerce doctor [--config <path>] [--env-file <path>] [--gateway <url>] [--json]Options
--config <path>Path to the config.
--env-file <path>Load environment variables before reading the config. Variables already set in the environment take precedence.
--gateway <url>default: derived from config, else http://localhost:8080The running gateway to check against.
--jsondefault: falseMachine-readable JSON instead of the formatted report.
Output
$ npm run agent-commerce -- doctor --config config-demo.yaml
PASS Config valid: 2 resource(s), merchant "Demo Data Store" (using local chain manifest .deploy/local.json for X402_ASSET, X402_ASSET_NAME, X402_ASSET_VERSION, X402_ASSET_DECIMALS, MERCHANT_WALLET, X402_FACILITATOR_PRIVATE_KEY)
PASS Gateway healthy and ready at http://127.0.0.1:8080
PASS Backend 2/2 backend host(s) reachable
PASS Protocols http=on mcp=on (/mcp) a2a=off acp=off
INFO A2A disabled
INFO ACP disabled
INFO AP2 disabled
PASS Payments x402 v2 (scheme=exact) enabled - LOCAL dev chain (eip155:31337), destination=0x7099…79C8, facilitator=local (in-process), paymentFlow=authorization
INFO Payments (MPP) MPP not configured
PASS Storage sqlite schema v5 writable; receipts=2
PASS Transactions none unresolved
PASS Protocol versions reported by gateway /.well-known/agent-commerce
Score: 8/8 checks passeddoctor compares the live gateway with your resolved config for each rail and resource with its own offers: offer order, network, token, payee and transfer method, plus decimals and payment flows when published. Any mismatch fails the check.
Checks
| Check | Looks at |
|---|---|
| Config | the same validation as validate |
| Gateway | health and readiness at the gateway URL. A 403 from /ready fails the check because the gateway rejected the probe's hostname. The URL comes from --gateway or, when omitted, server.host and the configured port; wildcard bind addresses use loopback |
| Backend | whether each backend host is reachable |
| Protocols | which surfaces are on, and their mounts |
| A2A · ACP · AP2 | status and pinned spec, plus enabled-feature checks: A2A unsupported; ACP auth, idempotency, checkout mapping and unsupported; AP2 trust (issuers/key counts), replay store, resources and unsupported. The ACP idempotency and AP2 replay lines include legacy import status (below) |
| Payments | x402 rail, deployment mode, each offer's network and destination, facilitator and payment flow, compared with the live gateway |
| Payments (offers) | health of each published offer, naming failures; reasons appear in the gateway's debug log. Shown for multiple rail offers or resource overrides |
| Payments (MPP) | the same for MPP, with its recipient and pinned drafts; INFO when MPP is not configured |
| Payments (quotes) | whether local config and the gateway agree on enabling ERC-8409 quotes, and whether the published issuer matches the address derived from quote.signerPrivateKey. On a mismatch, check the gateway's config and restart it if the key was rotated |
| Mainnet safety, Mainnet safety (MPP) | mainnet safeguards for each offered network, including anonymous facilitator access and accepted assets: x402 allows the network's USDC or another EVM token with full metadata; MPP requires its canonical asset |
| Storage | schema, writability, receipt count and nonzero undelivered/uncertain counts. Warns below schema v5, which start migrates |
| Transactions | unresolved journal entries by state, WARN when any remain; see GET /api/transactions?unresolved=true or run reconcile |
| Authorization holds | WARN: reserved AP2 holds over 15 minutes old without payment attempts; reconcile releases them with AP2 enabled |
| ACP claims | INFO: unresolved ACP claims; same-key retries get 409 idempotency_unresolved |
| Payment retry keys | INFO: unexpired unresolved payment retry keys from idempotency.redelivery; matching retries on enabled resources get 409 payment_identifier_unresolved |
| Protocol versions | pins reported by /.well-known/agent-commerce, or local pins if unreachable |
doctor reads the receipt database without migration, imports or ACP claim recovery. It can run beside a live gateway, including version 2.5.
Deprecated store files
For enabled AP2 or ACP, the AP2 replay store and ACP idempotency lines check authorization.ap2.replay.path and protocols.acp.idempotency.path against the import records in the receipt database:
| Status | When |
|---|---|
PASS | the key is unset, with no import needed or an import already recorded |
WARN | the key remains set: its file awaits import, was imported, is missing or is :memory:. Remove the key after the import/check is recorded |
FAIL | start would refuse a changed import path, an unwritable unimported file, or an unset/missing source with evidence of past feature use but no recorded import/check |
| Status | Meaning | Scored |
|---|---|---|
PASS | healthy | yes |
WARN | working, with a caveat — e.g. an unauthenticated mainnet facilitator | yes |
FAIL | broken; the run exits 1 | yes |
INFO | context only, e.g. a disabled adapter | no |
JSON output
{
"checks": [
{ "name": "Config", "status": "PASS", "detail": "valid: 2 resource(s), merchant "Demo Data Store" …" },
{ "name": "Gateway", "status": "PASS", "detail": "healthy and ready at http://127.0.0.1:8080" },
{ "name": "A2A", "status": "INFO", "detail": "disabled" }
],
"score": { "passed": 8, "total": 8 },
"exitCode": 0
}Run
agent-commerce doctor --json after every deploy: it exits non-zero on any FAIL.