Construction Operations · ERP Automation Case study

AI-Assisted Sage Intacct Automation

Reis Contracting / Agent.Press

AI-assisted automation for construction operations running through Sage Intacct.

Reis Contracting / Agent.Press

AI-Assisted Sage Intacct Automation AI-Assisted ERP Automation

Senior Full-Stack AI Engineer · Architecture & Delivery

System map · Workflow

Verified proof

  • ~1 hour → minutes Project-level processing
  • Nearly 99% Successful transaction processing

Automation flow

  1. Input

    • Estimates
    • Subcontracts
    • Change orders
    • Change requests
    • Subcontract invoices
  2. Validation

    ERP lookup before extraction

  3. Orchestration

    Declared tools, then a human approval gate

  4. Sage Intacct

    External system · one write path

  5. Result

    A posted record, attributable to a document

Retry · fallback · rejection reported per field

Engineering

AI-assisted workflows · Tool calling · Validation · Sage Intacct · Load testing

Named with approval · Proprietary implementation omitted

Role
Senior Full-Stack AI Engineer · Architecture & Delivery
Disclosure
Named with approval · Proprietary implementation omitted

The problem

What the system had to solve.

Manual construction and accounting workflows around Sage Intacct required significant project-level processing time across connected operational records.

What I owned

The responsibility behind the work.

Architected and delivered the AI-assisted automation platform covering Estimates, Subcontracts, Change Orders, Change Requests and Subcontract Invoices, from the Sage Intacct integration through extraction, validation and the production failure paths.

Built on the Agent.Press platform: the extraction and lookup tools that confirm a record against the ERP before anything is written, the validation ahead of every write, and the retry and fallback behaviour behind them.

Engineering approach

How it was built.

Built the workflow automation, external-system integration, validation and production error handling, with lookup tools that confirm a record against the ERP before anything is extracted or written, and a load-testing suite to check the paths under concurrency.

Automation flow

  1. Input
  2. Validation
  3. Orchestration
  4. ERP
  5. Result

Why ERP automation is different

The write is the whole problem.

Most AI features fail softly. A summary is a bit off, a suggestion is ignored, and a user moves on. Writing into an accounting system is not that. A wrong subcontract, a duplicated invoice or an estimate posted against the wrong project is a financial record that someone has to find, understand and reverse.

So the interesting engineering here is not extraction. It is everything arranged around the extraction to make sure a write is correct, expected, and traceable to a document a human approved.

Record types handled

  • Estimates
  • Subcontracts
  • Change requests
  • Subcontract invoices

Every one of these has downstream financial consequences. None of them is a good candidate for a model writing directly into an ERP.

From document to posted record

The order of operations is the safety model.

A document does not go straight to extraction. It is classified, the records it refers to are confirmed to exist in the ERP, and only then is anything extracted from it. Extraction produces structured data, which is checked and mapped, and which a person approves before any write is attempted.

Processing pipeline

  1. Document received
  2. Classification Which kind of record is this
  3. ERP lookup Confirm project, vendor or estimate exists
  4. Structured extraction Per document type
  5. Validation and field mapping
  6. Human approval
  7. Write to the ERP
Lookup precedes extraction, and approval precedes the write. Both orderings are deliberate.

Confirming the record first means extraction is anchored to something real. A document referring to a project that does not exist fails at lookup, cheaply, instead of producing a confident extraction that cannot be posted.

Tools, not prompts

What the agent is actually allowed to do.

The agent has no direct access to the ERP. It has a set of declared tools, each with a schema and a single job, executed by the runtime. Reading and writing are separate tools, and the difference between them is enforced by which tools exist rather than by instruction.

The tool surface

Read and confirm

  • Classify document
  • Look up project
  • Look up vendor
  • Look up estimate
  • Resolve file reference

Extract

  • Estimate
  • Subcontract
  • Subcontract invoice
  • Change request

Write

  • Approve and submit extracted data

One write tool, reached only after the read and extract tools have done their work.

A separate extraction tool per record type is more code than one general extractor, and worth it: each document type has its own shape, its own required fields and its own failure modes.

The approval gate

Nothing reaches the ERP unreviewed.

Extraction produces a structured result held against an identifier. It is not posted. A person reviews what was extracted and approves it, and only that approval triggers submission. The gate is a step in the pipeline rather than a convention someone might skip.

Two submission modes

All or nothing

The default.

  • Every line must resolve in the ERP
  • One unresolvable line fails the submission
  • Nothing partial is posted
  • Used when the record must be complete to be meaningful

Partial submission

Explicitly requested.

  • Valid lines are posted
  • Unresolvable lines are reported, not posted
  • Used when most of a document is actionable
  • The remainder is handled separately
The choice is explicit per submission, because the right answer depends on the document rather than on a global setting.

The default is the strict one. Partial submission is available because real documents are sometimes partly wrong, but it has to be asked for.

Talking to the ERP

An integration layer, not a client call.

Sage Intacct is reached through a dedicated integration layer rather than from the tools directly. That layer owns the transport, the per-record-type request construction, the mapping between extracted fields and ERP fields, and the interpretation of what comes back.

What the integration layer owns

  • Transport and session handling
  • A module per record type
  • Field mapping between extraction and ERP
  • Error response parsing
  • Shared types across the boundary

Error parsing earns its own module. An ERP does not fail with a clean status code; it returns structured errors describing which field on which line was rejected and why. Turning that into something a user can act on — rather than a stack trace or a generic failure — is most of the difference between an automation people trust and one they stop using.

Failure paths

What happens when it does not work.

Every stage has a way of going wrong that a person eventually has to understand: an unreadable document, a project that does not exist, an extraction missing a required field, a line item that does not resolve, an ERP that rejects a write. Each fails at its own stage with the reason attached rather than surfacing as a generic error at the end.

Where a document can stop

  1. Document in progress
    1. Classification fails Unrecognised document type
    1. Lookup fails Referenced record not in the ERP
    1. Extraction incomplete Required fields missing
    1. Mapping fails Line items do not resolve
    1. ERP rejects the write Parsed and reported per field
Failing early and specifically is cheaper than failing late and vaguely — for the system and for the person who has to resolve it.

Retry and fallback sit behind these paths, but the first requirement is that a failure is attributable. An automation that fails without saying where is worse than no automation, because someone still has to check the work.

Built on the platform, not beside it

Why this is not a standalone application.

The automation is delivered on the Agent.Press platform: it depends on the published runtime, tool contract and console rather than carrying a private copy of them. The client-specific work is the tools, the ERP integration and the document handling. The agent loop, conversation state, retrieval and observability come from the platform.

What belongs where

From the platform

  • Agent runtime and model loop
  • Tool execution and validation
  • Conversation state
  • Console and surfaces
  • Tracing

Client-specific

  • ERP integration layer
  • Per-record extraction tools
  • Lookup and approval tools
  • Field mappings
  • Document classification
A platform fix reaches this system without a port, and this system’s ERP specifics never leak into the platform.

Behaviour under concurrency

Testing the paths that write.

The transaction paths were exercised under concurrency with a dedicated load-testing suite. The question being asked is not throughput. It is whether the same document processed twice produces one record, whether concurrent submissions against the same project stay correct, and whether failures under load stay attributable.

What load testing was for

  • Duplicate submission behaviour
  • Concurrent writes against one project
  • Failure attribution under load
  • Integration behaviour at rate

Engineering scope

What I worked on.

  1. Workflow automation across connected operational records
  2. Sage Intacct integration and record lookup
  3. Extraction tools that confirm a record before writing to it
  4. Validation ahead of downstream writes
  5. Production error handling, retry and fallback
  6. Load testing of the transaction paths under concurrency

Why these decisions mattered

The trade-offs behind the automation.

  • Lookup before extraction

    Decision
    Confirm the referenced record exists in the ERP first.
    Why
    Anchors extraction to something real, and fails cheaply when a document refers to nothing.
  • A human approval gate

    Decision
    Extraction is held for review; approval triggers the write.
    Why
    Financial records are not a place for an unreviewed model output, however good the extraction is.
  • Strict submission by default

    Decision
    All lines must resolve unless partial submission is requested.
    Why
    A half-posted estimate is harder to detect and fix than a rejected one.
  • One extraction tool per record type

    Decision
    Separate tools for estimates, subcontracts, invoices and change requests.
    Why
    Each has its own required fields and failure modes; one general extractor hides all of them.
  • A dedicated integration layer

    Decision
    The ERP is reached through its own module, not from tools directly.
    Why
    Transport, mapping and error interpretation are one concern, and change together.
  • Delivered on the shared platform

    Decision
    Depend on published platform packages rather than forking.
    Why
    Runtime reliability improves for this client without this client paying for the work twice.

Impact

The verified result.

Reduced project-level processing from approximately one hour to a few minutes, with nearly 99% successful transaction processing.

Technology

The technical surface.

  • AI-assisted workflows
  • Sage Intacct
  • Tool calling
  • Validation
  • Integrations
  • Load testing

Next: Agent.Press

Back to all work Start a conversation