> ../failures/approved_own_refund.md
This is an illustrative Failure Report: the scenario is representative rather than a single named client, but the mechanism is one we design against on every payment-adjacent build. Picture a customer-support agent that handles refund requests: it reads the ticket, checks the order against a return-eligibility policy, and either approves a refund through the payments API or escalates to a human. It has been running cleanly for weeks. Then it approves a refund of $2,340 against a $340 order.
§ 01 · The first assumption: a policy-logic bug
The obvious first read is a broken eligibility check, a bad comparison, or the wrong field read against the wrong order. But assume the policy code is correct, and the agent did correctly determine the order was eligible for a refund of $340. The $2,340 did not come from the policy logic at all.
── What actually happens ──
§ 02 · What actually happens
The customer's ticket, while describing their $340 order, also mentions in passing that they were charged $2,000 twice on a separate, unrelated order the previous month and "never got that sorted out either." The agent, reasoning generously and trying to be maximally helpful, decides the refund it is about to approve should also resolve the customer's other complaint, and adds the two figures into a single refund request.
The refund tool's interface accepts a dollar amount as a parameter with no independent validation against the specific order it is tied to. The agent has access to approve a refund up to a reasonable ceiling, but nothing checks that the amount it requested actually matches the order it determined was eligible. Scope said "this agent can issue refunds." Nothing said "the refund amount must equal the eligible order's value, and nothing else."
── Not a prompt gap ──
§ 03 · Why this is a payment-authorization gap, not a prompt gap
You could rewrite the prompt to say "only refund the exact eligible amount, never combine requests", and that helps as a stopgap. But that fixes this specific failure, not the category. A prompt instruction is advice the model can still reason its way around when it is trying to be helpful. The actual gap is architectural: the payment layer trusted a number the agent supplied instead of deriving that number itself from the order record.
── The fix ──
§ 04 · The fix
Fix 1: The refund amount is computed by the payment layer, never supplied by the agent. The agent submits only an order ID and a decision, "eligible" or "not eligible." The system looks up the actual refundable amount for that order server-side. The agent never has the ability to state a dollar figure that gets trusted.
Fix 2: A hard per-transaction ceiling independent of the agent's reasoning. Even with the amount computed server-side, a ceiling matched to typical order values means a data error elsewhere in the pipeline cannot produce an outsized refund either.
Fix 3: Multi-order requests always escalate to a human. If a ticket references more than one order, exactly the situation that triggers this failure, the agent routes to human review automatically, regardless of how confident its eligibility read is.
Fix 4: Reconciliation logging captures the agent's full reasoning, not just its final action. You want to see, after the fact, why the agent decided what it decided, because "the agent tried to be extra helpful" is a very different root cause than "the agent misread a number," and the fix for each is different.
── The regression test ──
§ 05 · The regression test
Add a test ticket that references two separate orders in the same message, the way this scenario does, and verify the agent escalates instead of acting. Run it before every deployment of any agent with payment-adjacent permissions.
§ 06 · What this teaches
A well-intentioned agent trying to be maximally helpful is a real failure mode, not just a theoretical one, and it is harder to catch than a broken comparison, because the reasoning that produced it looks almost right. The fix is not a smarter prompt. It is removing the agent's ability to state a number that a downstream system will trust without deriving it independently.
── Checklist ──
§ 07 · Checklist
[ ] Does your agent ever supply a dollar amount that a payment system trusts directly?
[ ] Is that amount instead computed server-side from the underlying record, every time?
[ ] Does a per-transaction ceiling exist independent of the agent's own reasoning?
[ ] Do multi-order or multi-issue requests route to a human automatically?
[ ] Can you reconstruct why the agent made a decision, not just what it decided?
ORBIRESEARCH