Your AI Agent Can Pay Anyone. Add a Check Before It Does
Spending caps answer how much, not who gets paid. Two Oct 7 posts show the fail-closed screening call and the policy layer agents still lack.

Your agent reads a payment address out of an HTTP response and sends money to it. You set a daily budget and a per-transaction cap, so you figure the blast radius is bounded. Two developer write-ups published on October 7 argue that the caps are the easy half, and show what the hard half looks like in code.
One covers screening a payee before an agent pays it. The other covers the broader version of the same gap: an agent that can reach a tool can execute it, and a token budget is not an execution budget. Both are vendor posts — the authors each ship a product in the space — so the architecture is worth more than the sales pitch, and that is what this piece sticks to.
The check your agent wallet probably doesn't do
In the x402 flow, an agent reads a payTo address from a 402 response and sends USDC to it. As the first author puts it: "Some agent wallets already let the owner set a daily budget, a per transaction limit and approved domains. A check on the address itself is a separate question: is the wallet you are about to pay on a sanctions list?"
That is a different class of control. A spending cap answers how much; an approved-domain list answers which service. Neither answers who receives the money, because the address arrives inside the response, at runtime, from the counterparty.
The pattern the author describes is a single screening call placed in front of the payment step. He reports it checks an address against four lists — OFAC SDN, UN Consolidated, EU and UK — and returns each list separately, matched or clear, with that list's version date. He prices his own service at 0.01 USDC per call, paid over x402 itself, on Base or Solana, with no account or API key. Treat the pricing and availability as the operator's description of his own service, not an independent benchmark.
The rule that actually matters: fail closed
The interesting engineering is not the lookup. It is what the code does when the lookup doesn't come back cleanly.
The response carries a headline verdict — clean, deny, or indeterminate_ofac_unavailable — plus an any_list_match flag covering all four lists. The headline verdict speaks only for OFAC, so the decision has to read both fields:
// illustrative example
export const decide = (status, d) =>
status === 200 && !!d && d.verdict === "clean" && d.any_list_match === false;
Everything that is not an explicit clean answer resolves to no: deny, indeterminate_ofac_unavailable, a 400, a 5xx, a timeout, or a body that isn't JSON. The author says his first draft got this backwards and paid when the OFAC feed was unavailable, which he calls the worst possible failure for a check like this. His summary is the line to steal: a check that cannot run must never turn into a yes.
The packaging detail is worth copying too. The scripts exit 0 for clean and non-zero for everything else, so the check drops in front of a payment step in an agent or a plain shell script without any integration work.
The trap that silently disables the check
This one comes from the author's own testing on a clean machine, and it fails in the quiet direction — the code runs, nothing errors, and the control does nothing. With @x402/axios, payment is triggered when the first 402 comes back as an error. Set validateStatus: () => true and the 402 counts as a success, so the client never pays and never screens. The working example uses validateStatus: s => s !== 402, which keeps 400 and 5xx throwing.
One limit the author states plainly, and you should repeat it to anyone who asks you for compliance cover: passing the rule means the address is not on those four lists at their stated version dates, nothing more. It says nothing about who controls the wallet or where its funds came from. He is explicit that it is not legal advice.
The general case: orchestration isn't authorization
Payments are the vivid example. The second post generalizes it, and the framing is the most portable idea in either piece.
"Agent frameworks are good at orchestrating models and tools," that author writes. "But orchestration isn't authorization. A framework can tell an agent: Here are the tools you can use. It doesn't necessarily answer: Should this specific action be allowed? If the agent can reach the tool, the action can happen."
He lists failure modes that will be familiar to anyone who has run an agent against production. An agent stuck in a loop keeps calling tools, and a token budget is not an execution budget, so a small loop becomes a large bill. Agents pass wrong parameters, misread tool results, or report success for an action that didn't happen. Agents also read content they did not author — documents, tickets, emails, web pages — and if that content changes behavior, only execution boundaries limit the damage.
The asymmetry he draws is the part worth writing on a whiteboard: agent behavior is probabilistic, authorization shouldn't be. The model can decide it wants to issue a refund. It should not be the thing that decides it is allowed to issue one.
What the policy layer evaluates
The proposed shape is a policy sitting between the agent and the tool, returning allow, block, or require-approval before the tool runs. What it evaluates is the concrete request, not the conversation:
// illustrative example
{ "tool": "issue_refund", "amount": 4000, "customer_id": "12345" }
Or, in his words: "The policy evaluates the actual action. Not the prompt. Not the agent's intentions. The action."
Two consequences follow. Approval has to be bound to the action rather than to a step in the workflow — reading data is not deleting it, and drafting a refund is not issuing one. And the decision itself needs recording, including blocked attempts: what was requested, with which parameters, which policy applied, whether it was allowed or blocked or approved, and what actually happened. He notes that logs are useful but that recording the execution decision is a different thing, and his company sells a product that does it — so take the product claim as his, and the record-the-decision requirement as the reusable part.
What to do before your next agent ships
Three steps, in rising order of effort:
- Write down every tool your agent can reach that changes state outside your process. Payments, refunds, deletes, infrastructure calls. That list is your actual blast radius, regardless of what the prompt says.
- For each one, decide what happens when the guard fails rather than when it passes. Timeouts and 5xx responses are where fail-open bugs live, and they will not show up in a happy-path test.
- Put the allow/block decision somewhere the model cannot write to, and log the decision alongside the outcome.
The thing to watch over the next few months is whether agent frameworks ship this boundary themselves or leave it to a layer you have to buy. Right now the people writing about it are mostly the people selling it, which is a reasonable signal that the frameworks haven't closed the gap yet.
More from DangMua