Inspiration

Accounts payable automation works well when the data is clean.

The difficult part is what happens when it is not.

An invoice can look like a match while the price is outside tolerance. Two invoices can come from the same vendor, for the same amount, on the same day, yet only one may be legitimate. A posting-period issue may need to stop both payment and accounting, while another exception may only need to block payment.

In those cases, simply returning a match score or an approve / reject decision is not enough.

That led us to build Holdfast around a different principle:

Automation should stop before it guesses.

Holdfast focuses on the exceptions that should not be cleared automatically. Instead of forcing uncertain cases through the pipeline, it applies typed holds, assembles field-level evidence, and routes the next human action while preserving an auditable record of what happened.


What it does

Holdfast is an accounts-payable exception review and reconciliation system for the cases that automated matching cannot safely resolve.

The workflow is:

  1. Normalize and match financial records
  2. Detect conflicts and apply typed holds
  3. Rank the review queue by money at risk
  4. Show structured field-level evidence
  5. Let a human route the next action
  6. Govern hold release and tolerance changes
  7. Record every decision in the audit journal

The reviewer is not asked to approve or reject an AI answer.

Instead, the reviewer decides what happens next:

  • re_application
  • customer_outreach
  • internal_correction

Each case can include typed holds such as price variance, tax variance, duplicate candidate, missing reference, period deferral, and other reconciliation-specific conditions.

The hold model also distinguishes operational impact. For example, one exception may stop payment while another can block both payment and accounting.


Field-level evidence instead of model prose

We deliberately avoided making a language model's confidence the center of the interface.

For each case, Holdfast shows the underlying evidence directly:

  • observed value
  • reference value
  • delta
  • conflict state
  • evidence source
  • matching candidate breakdown

This gives the reviewer something inspectable instead of asking them to trust a generated explanation.

The model may propose.

Deterministic code verifies.


Governed decisions

Some actions should never happen silently.

Hold release and tolerance changes are treated as governed human decisions.

When an action can release affected holds, the backend returns a 428 human-approval-required preview. The interface presents that preview to the reviewer, requires explicit confirmation, and only then resubmits the action with the required human-approval header.

This means a tolerance change is not treated as an invisible configuration edit. It becomes a recorded financial-control decision.


Auditability

Every meaningful action is written to an append-only audit journal.

The journal can replay:

  • how the case was matched
  • which conflict was raised
  • which hold was applied
  • who routed the case
  • who released a hold
  • who changed a tolerance
  • what happened afterward

The backend also maintains verification data for the audit chain so the review history is not just UI decoration.


How we built it

Holdfast is split into a deterministic financial-control engine and a review workstation.

Backend and engine

The backend handles:

  • normalization
  • candidate matching
  • typed hold generation
  • reconciliation rules
  • case routing
  • governed decisions
  • tolerance changes
  • audit journaling
  • evaluation

The frozen backend exposes real endpoints for:

  • run summaries
  • exception queues
  • case dossiers
  • human decisions
  • tolerance changes
  • audit retrieval

Financial values are represented as integer paise, avoiding floating-point errors in money calculations.

Frontend

The frontend is a Next.js + TypeScript operations workstation.

It includes:

  • a run Overview
  • money-at-risk analysis
  • exception queue
  • detailed case review
  • evidence comparison
  • candidate breakdown
  • routing controls
  • hold governance
  • tolerance-change workflow
  • human-approval preview
  • audit history
  • responsive desktop/mobile layouts

The frontend has a strict adapter boundary so UI components do not directly depend on backend route implementations.

Mock mode uses backend-shaped snapshots rather than a separate invented frontend domain, while live mode fails explicitly instead of silently falling back to fixtures.


Evaluation

We wanted to measure more than how many cases the system could automate.

The more important question was:

How many unsafe cases does the system incorrectly clear?

On the frozen held-out evaluation:

  • 45% coverage
  • 100% precision
  • 0 false clears
  • ₹0 money at risk from false clears

A naive baseline reached higher coverage, but produced false clears and significant financial exposure.

That tradeoff is intentional.

We would rather leave a difficult case for human review than inflate automation coverage by clearing something the system cannot safely justify.

One of our own review agents also caught that an earlier coverage definition was counting holds that did not require human review. We corrected the metric, accepted the lower result, and kept the original evaluation floor unchanged rather than moving the target after seeing the data.


Challenges we faced

1. Defining the right product boundary

At first it was tempting to build another reconciliation dashboard with confidence scores and approve/reject buttons.

The more we studied the workflow, the clearer it became that the real value was in controlled uncertainty: knowing when automation should stop, what type of hold should be applied, and who should act next.

2. Keeping the frontend honest

Our early frontend used abstractions that did not perfectly match the backend domain.

Before finalizing the product, we reconciled the UI with the frozen backend contract, removed invented concepts, replaced confidence-oriented terminology, and implemented the real approval and audit flows end to end.

3. Human approval for governed actions

A normal success/error API pattern was not enough for actions like releasing holds.

We implemented an explicit preview-confirm-resubmit flow so the reviewer can see the consequence of a governed action before committing it.

4. Avoiding flattering metrics

The evaluation process produced an uncomfortable result: correcting the coverage definition made the headline number worse.

We kept the corrected number.

That became one of the most important lessons from the project: a trustworthy financial system should optimize for honest failure, not impressive-looking automation rates.


What we learned

The biggest lesson was that AI adoption in financial operations is not only about getting agents to perform more work.

It is also about building systems that can recognize when an automated result should not be trusted.

Generation is useful.

Verification, holds, human routing, and auditability are what make the system operationally safe.

That is the role Holdfast is designed to play.

Built With

Share this project:

Updates

Submission history