An approval workflow is a routing problem wearing a policy costume. Most of what a chain does is answer two questions: is this request allowed under the spend policy, and who is the right person to sign it. AI handles both well, as long as you keep it away from the one act it must never perform: approving the spend. The model reads and routes; a named human commits.
That distinction is the whole design. When someone submits a purchase request, a stack of decisions has to happen before it reaches an inbox. What category is this. Does it exceed a threshold that pulls in a second approver. Is there budget left in the cost center. Is the vendor onboarded and not on a hold list. Does the requester have delegated authority to raise it at all. Teams answer these by hand today, which is why a €4,000 laptop order can sit for six days waiting on someone who was never the right approver in the first place.
Where the controls actually live
Spend controls come in layers, and each layer has its own owner and its own failure mode. Before automating anything, we pull them apart, because collapsing them into one model call is how you end up with a system nobody can audit.
- Eligibility: can this requester raise this kind of request. This is delegation of authority, and it belongs in a matrix keyed by role, cost center, and amount band.
- Categorization: what is being bought. This drives everything downstream, and it is the layer where a model earns its keep because free-text requisitions are messy.
- Thresholds and escalation: how many signatures, and whose. A €900 software renewal and a €90,000 one follow different paths even when the category is identical.
- Budget and commitment: is there money left, counting open POs already committed against the line, not just booked actuals.
- Vendor and compliance state: onboarded, tax-validated, not sanctioned, not on a payment hold.
The model touches categorization heavily, eligibility and thresholds lightly, and budget and vendor state not at all. Those last two are deterministic lookups against the ERP and the vendor master. You do not want a language model estimating remaining budget. You want it to read the requisition, decide the category and the likely amount band, and then let hard queries do the arithmetic.
Routing that reads from versioned data
The old way to build a chain is a flowchart hard-coded into the procurement tool. It works until the org changes, and then it rots. Someone leaves, a threshold moves, a new legal entity comes online, and the flowchart lies for three weeks before anyone notices a stuck queue.
We model routing as data instead. The delegation-of-authority matrix, the reporting lines, and the threshold table are versioned records with effective dates. The router reads the version that was live when the request was raised and pins to it. This matters for point-in-time correctness: an approval that happened in March must be explainable against March’s policy, not July’s. When an auditor asks why a request went to a particular VP, the answer is a matrix version and a row, not a guess about what the code did that day.
The classification model sits in front of this. It reads the requisition text, any attached quote, and the requester’s context, then produces a category, an amount band, and a confidence score. Low confidence does not fail open. It routes to the stricter path and flags for review, because the cost of an unnecessary second approval is minutes and the cost of a missed one is a control gap. That is a deliberate false-positive budget: we accept some over-escalation to keep under-escalation near zero.
A few things we insist on in the routing layer:
- Every decision writes a full record: input, matrix version, category, confidence, chosen approver, and why. This is the audit trail, and it is written before the notification goes out, not reconstructed later.
- Entity resolution runs on requester and approver identity so a reorg or a name collision does not misroute. People change teams; the router keys on stable identifiers, not display names.
- In-flight requests hold their matrix version. Changing policy should never silently reroute something already moving through the chain.
Enforcement without stalling the business
Most spend-control projects fail from the opposite direction you would expect. The controls end up so rigid that the business quietly routes around them, which is worse than having none, because now the shadow process is invisible. The point of automating routing is to make the compliant path the fast one.
Straight-through processing is the target for the low-risk majority. A request under threshold, in-budget, from an eligible requester, against an onboarded vendor, in a clean category, does not need a human reading it at all beyond the single required signature. We measure what fraction clears without a queue and treat that number as the health metric. When it drops, something upstream drifted: a category the model started mishandling, a vendor master that went stale, a threshold set too tight for a team’s normal spend.
Enforcement then concentrates human attention where it belongs. The exceptions that surface are the ones that genuinely need judgment: an off-contract vendor, an amount that jumped bands late in the approval, a split that looks like it is dodging a threshold. We watch for that last one specifically. Two €9,000 POs to the same vendor in the same week, when the threshold is €10,000, is a pattern the router can flag even though each request is individually clean. Detecting it needs the commitment history, not the single request, which is why routing reads state rather than treating each requisition as isolated.
None of this removes the approver. It removes the six days of the request sitting in the wrong place. The person who signs still signs, still owns the decision, and now does it against a request that arrived correctly categorized, correctly routed, with budget and vendor state already checked, and a record of every step behind it.
FAQ
How do you keep an AI router from approving spend it should escalate?
The model never approves. It classifies the request, resolves the correct approver from the delegation-of-authority matrix, and routes. Approval stays a human action recorded against a named person, and any low-confidence classification defaults to the stricter path.
What happens when the org chart or DOA changes mid-quarter?
Routing reads the authority matrix and reporting lines as versioned data with effective dates, not as logic baked into the model. A reorg or a raised threshold is a data change that takes effect on its date, and in-flight requests keep the matrix version they started under.
Can this run without ripping out our ERP or procurement tool?
Yes. The router sits beside the system of record and writes decisions back through its API or approval hooks. The ERP stays the book of record for the PO and the audit trail; the AI layer handles classification and routing on top of it.