The three modes
Mode controls one thing: what the gateway does when a result is not a clean pass. The verification itself runs the same way in all three.
| Mode | On a clear fail | On uncertainty | Use it for |
|---|---|---|---|
| monitor | allow + log | allow + log | Zero-risk rollout. Watch agent traffic and build a record before you enforce. |
| standard | deny | review | The default posture. Turn away unverified agents, send edge cases to a human or async check. |
| strict | deny | deny | The tightest posture. Treat any unproven signal as a denial. |
Uncertainty is a real state, not a failure: a key directory you momentarily cannot reach, or an ACP session that needs a 3DS step-up. Standard mode routes those to review instead of guessing. Strict mode refuses them. Monitor mode records what it would have decided and lets the checkout through regardless.
Required layers
required_layers lists the layers that must pass for an allow. The default is [transport, mandate], and the reason is deliberate: transport (Web Bot Auth) proves which agent is calling, but it does not prove the agent may spend. Identity without authority is not enough to take an order, so the mandate layer is required alongside it.
{
"mode": "standard",
"required_layers": ["transport", "mandate"]
}
ACP-mode merchants typically require [transport, allowance] instead, proving identity plus a valid spending allowance. You can require all three. Whatever you choose, the next rule still applies.
The downgrade rule
A layer that is presented and fails will deny, even when it was not in required_layers. This closes an obvious attack: an agent that supplies a broken mandate cannot escape it by hoping the mandate was optional. If you send a signal, it has to be sound. Optionality controls what is mandatory to provide, never whether a bad value is forgiven.
Required layers say what must be present. The downgrade rule says nothing presented may be broken. Together they stop both under-supply and tampering.
Trusted agents
trusted_agents is an optional allow-list of agent directory URLs or key ids. Leave it empty and any agent with a valid signature and mandate can transact. Set it, and an agent whose signature verifies but who is not on the list is denied with transport.agent_untrusted. This is the equivalent of a curated list of agent providers you are willing to sell to.
Clock skew
max_clock_skew_seconds bounds the gap between the time a signature was created and the time your server received it, in both directions. The default is 60 seconds. A larger window tolerates clock drift; a smaller one narrows the replay surface. Exceeding it produces policy.clock_skew_exceeded.
Fail-open is separate from mode
One safety property does not live in policy mode at all. The store plugin defaults to fail-open: if the verification API cannot be reached, checkout is allowed and the event is logged, rather than blocked. So even in strict mode, an outage of the gateway never stops a sale. Mode governs how a completed verification is enforced; fail-open governs what happens when no verification could run.
Recommended rollout
-
Deploy in monitor
Install the plugin in monitor mode. It runs the full verification on every agent checkout and writes the decision it would have made to the log, while denying nothing. Human checkout is untouched and no sale is at risk.
-
Watch the log
Let real agent traffic accumulate. Confirm that legitimate agents resolve to allow and that the deny cases are the ones you would want stopped. You are validating on your own evidence, not a vendor's promise.
-
Promote to standard
Switch to standard mode. Now unverified agents are turned away with a reason code and authorized ones check out normally. Edge cases go to review rather than a blind allow or deny.
-
Tighten only if you need to
Most stores stay on standard. Move to strict only when your risk tolerance calls for denying every unproven signal, accepting that some recoverable edge cases will be refused instead of reviewed.