AI Agents vs Automation: An Invoice Workflow Example
An invoice exceeds its purchase order by $40. Deterministic rules hold payment while a narrowly scoped model classifies the extra charge without gaining approval authority.
Khalil Ur Rehman
Author

AI Agents vs Traditional Automation: An Invoice Exception Workflow
A supplier sends an invoice for $1,240. The purchase order lists $1,200, and the invoice includes an additional $40 described as an environmental handling charge.
Should the system automatically approve it?
A traditional automation rule can compare the amounts, identify the mismatch, and place the invoice on hold. An AI model can interpret the description and suggest what kind of charge it represents.
Neither capability is sufficient to authorize payment.
The engineering decision is to keep financial controls in code and use the model only for a narrow classification task.
1. Define the workflow input
Assume an accounts-payable system receives this normalized invoice record:
{
"invoice_id": "INV-1042",
"supplier_id": "SUP-018",
"po_id": "PO-208",
"po_amount": "1200.00",
"invoice_amount": "1240.00",
"currency": "USD",
"extra_charge_description": "Environmental handling charge",
"supplier_bank_changed": false
}The system already has a matching purchase order. The invoice amount is $40 higher.
The workflow must determine whether the additional charge is a shipping fee, tax, handling fee, or something else.
It must not silently approve the difference.
2. Keep the financial rule in code
The purchase-order comparison is deterministic. There is no reason to ask a language model whether $1,240 equals $1,200.
from decimal import Decimal
def check_invoice(invoice):
po_amount = Decimal(invoice["po_amount"])
invoice_amount = Decimal(
invoice["invoice_amount"]
)
if invoice["supplier_bank_changed"]:
return "BANK_CHANGE_REVIEW"
if invoice_amount != po_amount:
return "AMOUNT_EXCEPTION"
return "MATCHED"For the example invoice, the rule returns:
AMOUNT_EXCEPTIONThat result should prevent automatic payment authorization.
The model may help explain the exception, but it must not override the rule.
3. Make one narrowly scoped model call
Instead of giving an AI agent unrestricted access to the accounts-payable system, send the model only the charge description.
The model's task is to return a classification.
Example model input:
{
"task": "classify_invoice_charge",
"description": "Environmental handling charge",
"allowed_categories": [
"SHIPPING",
"TAX",
"HANDLING",
"UNKNOWN"
]
}The model should return structured data, such as:
{
"category": "HANDLING"
}This is an illustrative model response, not an observed response from a specific model.
The classification can help route the invoice to the appropriate reviewer. It cannot establish that the charge is contractually valid.
4. Reject invalid model classifications
The application must validate the model output before using it.
ALLOWED_CATEGORIES = {
"SHIPPING",
"TAX",
"HANDLING",
"UNKNOWN",
}
def validate_classification(result):
if not isinstance(result, dict):
return "REJECTED"
if set(result.keys()) != {"category"}:
return "REJECTED"
category = result["category"]
if (
not isinstance(category, str)
or category not in ALLOWED_CATEGORIES
):
return "REJECTED"
return categoryFor example, suppose the model returns:
{
"category": "APPROVED"
}The validator returns:
REJECTEDThe model cannot create a new approval category.
It also cannot inject an additional field such as payment_authorized: true, because the validator rejects unexpected keys.
A valid category is not necessarily a correct category, however. If the model labels a handling charge as tax, the schema check will not detect that semantic error.
For that reason, the classification is only a routing suggestion. A human reviewer must confirm the actual charge against the purchase order and supplier agreement.
5. Define where the agent must stop
The workflow has two explicit stop conditions.
Amount mismatch: When the invoice amount differs from the purchase order, the system places the invoice on hold. The model may classify the charge, but cannot authorize payment.
Supplier bank change: When the supplier's bank details have changed, the workflow requires a separate verification process. The model must not determine whether the new account is legitimate.
These decisions are enforced by application permissions, not just prompt instructions.
The model-facing component should have no tool capable of releasing payments or modifying supplier bank records.
That separation matters because even a correctly classified invoice may contain an unauthorized charge.
6. What the workflow actually costs
The additional cost is not simply the price of an AI model subscription.
Every invoice with an amount exception may require a model request, structured-output validation, logging, and human review.
For planning, assume 10,000 invoices per month and a 6% amount-exception rate.
That produces 600 potential model classification requests per month.
If each request uses 500 input tokens and 100 output tokens, the monthly usage would be approximately:
300,000 input tokens
60,000 output tokens
600 classification operations
These are workload assumptions, not production measurements.
The actual model expense depends on the selected provider's current token pricing, retries, caching, and processing overhead.
The larger operational cost may be the human review queue.
If each exception takes five minutes to review, 600 exceptions represent approximately 50 staff-hours per month.
A model may reduce the time needed to identify the nature of an exception, but that saving must be measured. It should not be assumed.
7. The failure this design prevents
Consider a poorly designed agent that receives an invoice, classifies an additional charge as legitimate, and then automatically approves payment.
The classification could be wrong. The invoice could be fraudulent. The charge could violate the purchase order.
The failure is not merely an inaccurate AI answer. It is an unauthorized financial action caused by treating a model-generated classification as an approval decision.
The proposed design prevents that particular escalation by separating classification from authorization.
The deterministic amount check still places the invoice on hold, regardless of what the model returns.
A valid model classification can help a reviewer understand the exception, but it cannot release the payment.
8. What should be tested before deployment
A minimal test suite should demonstrate that:
A matching invoice with unchanged bank details passes the initial comparison.
A $40 amount difference creates an exception.
An unexpected model category is rejected.
A model response containing an extra approval field is rejected.
A supplier bank change requires independent review.
No model-accessible tool can approve payment.