The approval agent that could move money—until we removed the payment tool
An operations team built an agent to prepare invoice approvals, then removed its payment tool, bound approval to invoice scope, and rehearsed timeout and duplicate outcomes.
DECISION TOPICField cases↗Read with one real task in mind, then complete the workbench. The lesson is done when another person can review what you made.
The first demo was impressive. The agent read an invoice, matched it to a purchase order, summarized the discrepancy, and recommended approval. Then someone asked whether it could also release the payment. The room paused. That pause was the most useful part of the demo.
The team kept the agent. It removed the payment tool. It also changed the approval from “the agent says yes” to a scoped human decision with an audit trail. This case describes the three decisions they separated and the drills that made the boundary real.
The demo approved an invoice; that was the warning
An approval looks like one action: say yes or no. In practice it contains at least three different decisions:
- Prepare. Read the invoice, find the purchase order, compare amounts, and collect evidence.
- Approve. Commit the company to pay, usually under a delegation-of-authority rule.
- Pay. Move money through a bank or payment provider, an irreversible external effect.
The demo collapsed all three into a chat response. The agent could “approve” because the interface had one button, not because it had the authority. That is a design flaw, not a model flaw.
The team’s first change was structural: the agent could prepare an approval packet, but the payment tool was removed from its tool list. The second change was procedural: every approval had to name the invoice, amount, vendor, and approver. The third change was a drill: what happens when the payment outcome is unknown?
Three decisions, not one
The workflow was rebuilt around a separation of duties:
| Stage | Agent may do | Human must do | Evidence produced |
|---|---|---|---|
| Prepare | Read invoice and PO, list mismatches, draft a recommendation | Confirm the vendor and the business reason | Invoice ID, PO ID, amount, source documents |
| Approve | Present the packet, highlight exceptions | Approve, narrow, or reject within delegated authority | Approver ID, scope, timestamp, decision |
| Pay | Nothing in this workflow | Release payment through the finance system | Payment reference, amount, status |
The agent could still be useful at the prepare stage. It could reduce the time spent hunting for the PO and comparing line items. It could not become the approver, and it could not become the payment rail.
The team also wrote the scope of an approval: a specific invoice, a specific amount, a specific vendor, and a time window. “Approve this vendor’s invoices” was not a valid scope. “Approve invoice INV-1042 for the stated amount before Friday” was.
Example: the duplicate invoice
The same invoice arrived twice. The PDFs had different file names and slightly different layouts, but the invoice number, vendor, amount, and date matched. The agent proposed both for approval.
A human reviewer caught it because the two packets were side by side. A production workflow cannot rely on a reviewer noticing a coincidence. The team added a duplicate check before the approval packet was created:
- normalize the vendor ID, invoice number, amount, and invoice date;
- search open and recently paid invoices for a match;
- if a match exists, mark the packet “possible duplicate” and require a human decision;
- never merge or delete the duplicate automatically.
The check is not perfect. A vendor may reissue an invoice with a new number, or a legitimate recurring charge may look identical. That is why the output is a flag, not an automatic rejection. The reviewer sees the matched records and decides.
The agent’s job is to make the duplicate visible before someone pays it. The finance system’s job is to enforce the final control. Neither job belongs to a model’s confidence score.
Counterexample: the timeout after payment
The team rehearsed a harder case: the payment request times out. The bank may have processed it, or it may not have. The agent sees an error and, like many retry loops, wants to send the request again.
A blind retry can pay twice. The team wrote a different rule:
- Do not retry the payment call.
- Query the payment provider or bank by the idempotency key and invoice reference.
- If the payment is confirmed, mark it paid and stop.
- If it is definitively not processed, a human may release a new attempt.
- If the state is unknown, pause and hand off to finance with the trace.
The idempotency key is not a magic wand. It works only if the payment provider supports it and the workflow reuses the same key across retries. The team stored the key with the approval record, not in the model’s conversation history. A model that forgets the key cannot safely retry.
The drill also exposed a reporting problem. The agent’s run status said “failed,” but the payment had succeeded. The dashboard counted a failure; the finance system counted a payment. The team added a separate external-effect status: confirmed, rejected, or unknown. Run status alone was not enough.
The permission ladder
The final design used five levels. The point is not the number; it is that each level has a different owner and a different evidence requirement.
| Level | Action | Who approves | Evidence | Reversible? |
|---|---|---|---|---|
| 0 | Read invoice and PO | No approval | Source document IDs | Yes |
| 1 | Draft an internal recommendation | AP clerk | Mismatch list and policy reference | Yes |
| 2 | Create an approval packet | AP clerk | Invoice, PO, vendor, amount, duplicate check | Yes |
| 3 | Approve within delegated authority | Human approver, named in the packet | Approver ID, scope, timestamp | Partly |
| 4 | Release payment | Finance system and authorized operator | Payment reference and reconciliation | No |
The agent stopped at level 2. Level 3 was a human action in the finance system. Level 4 was outside the agent’s tool list entirely.
This is a narrower workflow than the demo promised. It is also a workflow the team can audit. The value is not “the agent approves invoices.” The value is “the agent cuts the preparation time and makes exceptions visible before a human signs.”
The recovery drill
The team ran a 30-minute tabletop exercise with the AP clerk, the finance operator, and the engineer who owned the agent. No production access was needed.
- Normal invoice. The agent prepares a packet; the approver can see the PO match and approve.
- Duplicate. Two invoices with the same number; the packet is flagged; the approver rejects one and documents why.
- Timeout after payment. The payment status is unknown; the operator queries by idempotency key and reconciles.
- Wrong vendor bank details. The vendor record changed the day before; the approver pauses and calls the vendor through a known number.
- Partial approval. The invoice is split across cost centers; the agent’s packet must show the split, and the approver must approve each scope.
The pass condition was simple: every participant could answer “what do I do next?” from the record alone, without asking the engineer to read the agent’s logs. If they could not, the evidence was insufficient, and the workflow was not ready.
What the agent may never do
The team wrote a short, non-negotiable list:
- release a payment;
- change vendor bank details;
- approve its own recommendation;
- merge duplicate invoices;
- bypass the two-person rule for amounts above the delegated threshold;
- retry a payment call after an unknown outcome;
- hide a mismatch because the invoice “looks normal.”
The list is short because it is enforceable. A long policy document that nobody checks is weaker than five prohibitions wired into the tool list and the approval screen.
Boundary
This case fits accounts-payable preparation, invoice matching, and approval packet assembly where a human approver and a finance system already exist. It does not fit consumer payments, payroll, tax filings, or any workflow where the approver cannot see the source documents. It also does not fix a broken vendor master or a missing delegation-of-authority rule. If the finance team cannot reconcile an unknown payment outcome, the agent should not be anywhere near the payment tool. The correct design is a preparation assistant with a hard stop before money moves.
SOURCES CHECKED
Which first-party sources informed this guide?
Sources anchor definitions, risk boundaries, or operational facts. The decision framework and workbench are original to AI Vista.
- NIST AI Risk Management Framework — PlaybookChecked 2026-10-24
- OpenAI Agents SDK — DocumentationChecked 2026-10-24
- Temporal — Activity definition and idempotencyChecked 2026-10-24
- Stripe — Idempotent requestsChecked 2026-10-24
AI tools may assist with research, outlining, and language editing. Facts, cases, and final wording are reviewed by the editor. Report an error through the contact page.
TAKEAWAY TOOL
Five-level permission ladder
Assign authority to actions, not to the agent name.
- 01Describe the taskDescribe the result with a sanitized summary.
- 02Fill the decision fieldsRecord input categories, risk, evidence pointers, and handoff.
- 03Ask a colleague to reviewThe tool is ready when someone else can restate the decision.
LESSON READ
Finish the workbench, then mark it read.
The read state updates the syllabus and your course progress.
- 01Fields filled
- 02Case tested
- 03Reviewable
GUIDE PRACTICE NOTES
Leave a judgment you can review later.
The fictional examples below show the format. Your own notes stay in this browser. Record what worked, which boundary failed, or one question worth testing.
This guide has no example or local note yet. Record the first concrete observation.