Vendor Payment Reconciliation
Bank statement to AP ledger matching. Distinct from AP Invoice Reconciliation because the data is messier: bank descriptions rarely match vendor names cleanly, payments are often consolidated, and timing gaps are wider. Fuzzy matching and date windows do the heavy lifting.
What Gets Automated
Matching bank transactions to AP ledger entries despite format mismatches. Investigating consolidated payments, timing differences, partial payments, and unknown transactions. The agent prepares an evidence-backed recommendation for review.
What Humans Still Own
Unidentified transactions after AI investigation. Month-end reconciliation sign-off. Bank fee disputes and error corrections.
Pipeline
This template includes a schedule block: it runs automatically every day at 6 AM Eastern. Remove or adjust the schedule for manual execution.
{
"name": "vendor_payment_reconciliation",
"definition": {
"schedule": {
"every": "1d",
"at": "06:00",
"timezone": "America/New_York"
},
"actions": [
{
"type": "matcher",
"properties": {
"left": "@input.bank_transactions",
"right": "@input.ap_ledger",
"matchOn": ["reference_number"],
"tolerance": 25,
"dateWindowDays": 7,
"fuzzyThreshold": 75,
"descriptionKey": "description",
"outputMatched": "cleared",
"outputUnmatchedLeft": "unmatched_bank",
"outputUnmatchedRight": "outstanding_payments"
}
},
{
"type": "loop",
"filter": {
"condition": {
"greaterThan": [{ "length": "@unmatched_bank" }, 0]
}
},
"properties": {
"mode": "foreach",
"items_path": "@unmatched_bank",
"item_variable_name": "txn",
"actions_to_execute": [
{
"type": "custom-table",
"properties": {
"table": "payment_reconciliation_cases",
"operation": "upsert",
"key_fields": ["run_id", "transaction_id"],
"keys": ["run_id", "transaction_id", "description", "amount", "transaction_date", "status"],
"values": ["@__run_id", "@txn.transaction_id", "@txn.description", "@txn.amount", "@txn.date", "pending_review"]
}
}
],
"max_concurrency": 5,
"failure_strategy": "fail_fast",
"collect_results": false,
"result_key": "payment_case_writes"
}
},
{
"type": "loop",
"filter": {
"condition": {
"greaterThan": [{ "length": "@unmatched_bank" }, 0]
}
},
"properties": {
"mode": "react",
"objective": "Read the current run's unmatched payment cases. Investigate whether each transaction is a consolidated payment, a timing difference, a vendor-name mismatch, or a bank fee. Cite the records returned by the declared tools and recommend the next action. Do not post an accounting entry.",
"tools": [
{ "type": "action", "name": "read_payment_reconciliation_cases" },
{ "type": "action", "name": "search_ap_by_amount" },
{ "type": "action", "name": "search_ap_by_date_range" },
{ "type": "action", "name": "search_ap_by_vendor" },
{ "type": "action", "name": "get_known_bank_fees" }
],
"max_iterations": 12,
"on_stuck": {
"iterations": 3,
"action": "retry_with_hint",
"hint": "If the evidence is insufficient, complete with a recommendation for manual review."
},
"result_key": "bank_investigations"
}
},
{
"type": "PbotApproval",
"filter": {
"condition": {
"greaterThan": [{ "length": "@unmatched_bank" }, 0]
}
},
"properties": {
"comment": "Bank reconciliation: {{cleared.length}} auto-cleared, {{unmatched_bank.length}} investigated. Review findings and approve close entries.",
"request_payload": {
"cleared_count": "@cleared.length",
"outstanding_count": "@outstanding_payments.length",
"investigations": "@bank_investigations"
}
}
},
{
"type": "custom-table",
"properties": {
"table": "bank_reconciliation_log",
"operation": "write",
"keys": ["run_id", "reconciliation_date"],
"values": ["@__run_id", "@now"],
"fields": {
"bank_transactions": "@input.bank_transactions.length",
"auto_cleared": "@cleared.length",
"investigated": "@unmatched_bank.length",
"outstanding_payments": "@outstanding_payments.length",
"status": "completed"
}
}
}
]
}
}
Required Registered Actions
| Action | Kind | Purpose |
|---|---|---|
search_ap_by_amount |
db | Find AP entries matching an amount or sum of amounts |
search_ap_by_date_range |
db | Find AP entries within a date window |
search_ap_by_vendor |
db | Fuzzy search AP entries by vendor/payee name |
get_known_bank_fees |
db | Retrieve known fee patterns for the bank account |
read_payment_reconciliation_cases |
custom-table | Read the current run's persisted exception rows |
The workflow writes unmatched bank transactions to payment_reconciliation_cases, keyed by run_id and transaction_id. Bind read_payment_reconciliation_cases to that table with operation: "read" and where: { "run_id": "@__run_id" }. This gives the agent a fixed, read-only batch view before approval.
Customization Notes
Fuzzy threshold. 75 is lower than other templates because bank descriptions are notoriously messy ("WIRE TRF ACME" vs. "Acme Corporation"). Lower to 65 if your bank formats are especially terse; raise to 85 if descriptions are reasonably clean.
Date window. 7 days covers typical bank clearing delays. Extend to 10-14 days for international wires or ACH batches that clear slowly.
Consolidated payment detection. The search_ap_by_amount action should support sum-matching: finding multiple AP entries whose amounts sum to the bank transaction amount. This is the most common exception type in bank reconciliation.
Bank fee patterns. The get_known_bank_fees action returns known fee types and amounts for the bank account. Preloading common patterns (monthly maintenance fees, wire fees, etc.) lets the agent quickly classify these without investigation.