Case study · Real estate and applied AI

Automating lease, ID and invoice intake without letting a model write to the ledger

Leases, identity documents and supplier invoices arrived as scans, photos and PDFs, and every one was keyed in by hand before a tenant could be onboarded or a bill paid. The goal was to automate the routine documents and make the rest faster to check, while keeping the core system's data trustworthy.

Case studyReal estate · Property operatorSumanta Mukhopadhyay8 min read
#ai#llm#data#security#architecture
CASE STUDY · CASE STUDY · REAL ESTATE AND APPLIED AI28 Oct 2026 · 01:42 GST
At a glance
SectorReal estate · Property operator
My roleAI architect
EngagementArchitecture, build and hand-off
ScopeExtraction, validation, exception workflow, integration
What changed
  • Routine documents posted to the core system without manual keying
  • Every extracted field validated against a schema and business rules before posting
  • Exceptions handled in one queue with the document and the reason side by side
  • An audit trail from each posted value back to its source document and reviewer
Vision LLMStructured outputsJSON SchemaRules engineWorkflow enginePostgresObject storageReview UI

Anonymised composite. Client names, identifying details and confidential figures are withheld; public facts are cited in the references.

The situation

A property operator onboarded tenants and paid suppliers through a core property management system. Everything that fed it arrived as documents: signed leases, identity documents, proof of address, supplier invoices and service contracts. Each was opened, read and keyed by hand. Onboarding waited on the queue, keying errors surfaced later as billing disputes, and the team spent its time transcribing rather than checking.

Earlier attempts with template-based OCR had struggled because the documents varied too much: different lease templates, scanned and photographed IDs, and invoices in every layout a supplier could invent.

What had to be true

  • Every value validated before it reaches the core system, by rules the business can read.
  • The model never writes: it proposes a record, and deterministic code decides what is posted.
  • Uncertain documents go to people, with the reason and the source region visible.
  • Personal data handled deliberately: limited access, defined retention and no identity documents in logs or prompts beyond what extraction needs.
  • Traceability from any posted value back to the page it came from.

Architecture

Each document type had a versioned JSON Schema describing its fields, types, formats and required properties1. The model was asked to return output conforming to that schema, and the same schema validated the response, so a malformed answer failed loudly instead of slipping through. More on the pattern in structured outputs for reliable LLM integration.

Capture
Tenant portaluploadsShared mailboxinvoicesBranch scanningsigned leases
Classify
Document classifiertype and pagesObject storageoriginal, immutablePII controlsaccess and retention
Extract
Vision LLMschema-constrained outputSchema registryversioned per typeSource regionspage and box per field
Validate
Rules and cross-checkstotals, dates, referencesConfidence scoringper fieldException queuereason-coded
Post
Workflow engineidempotent stepsCore system APIservice accountAudit storePostgres
Layered architecture: the model extracts, rules decide, and only deterministic code holds the credentials to post.

The data flow, end to end

  1. ReceiveStore the original unchanged; record channel, uploader and checksum
  2. ClassifyIdentify document type and split multi-document uploads
  3. ExtractVision model returns a schema-shaped record with a source region for each field
  4. ValidateSchema check, business rules, and cross-checks against tenant, unit and supplier data
  5. RouteAuto-post when every field passes thresholds; otherwise queue with reason codes
  6. PostWorkflow engine writes to the core system once, with an idempotency key, and logs lineage
Each step is recorded, so a disputed value can be traced to the document, model version and reviewer.

The audit and staging tables in Postgres carried their own check, not-null and foreign key constraints, so invalid states were rejected by the database as well as by the application3. Retries were safe because posting was idempotent, the same discipline described in idempotent payment and order pipelines.

The hard part: confidence you can act on

Extraction quality was rarely the blocker. Deciding when to trust it was. A model's own statement of certainty is not a reliable signal, so confidence was built from evidence instead:

  • Arithmetic and consistency checks: invoice lines must sum to totals, lease dates must be in order, rent schedules must match the term.
  • Reference checks: the unit, tenant or supplier must exist and match what the document claims.
  • Field-level thresholds set per document type from a labelled sample, with stricter rules on fields that move money or identify people.
  • Reason codes on every exception, so the team could see which rule or field caused most reviews and fix the cause.

Documents are also untrusted input. Text inside an uploaded file can carry instructions aimed at the model, a form of indirect prompt injection2. The defence was architectural: the extraction model had no tools and no credentials, its output was confined to the schema, and posting was done by code that ignored anything outside defined fields. See prompt injection defence.

The model is the least trusted component in the pipeline. Design so that the worst it can do is produce a record that fails validation.

How the engagement ran

Pipeline
  1. Classify and extract
  2. Validate and score
  3. Auto-post or queue
Operations reviewer
  1. Open queued document
  2. Correct highlighted fields
  3. Approve for posting
Process owner
  1. Review reason-code trends
  2. Adjust rules and thresholds
  3. Approve schema changes
Corrections feed the evaluation set; reason-code trends feed the rules.
Phase 1Discover
  • Document inventory
  • Field and rule catalogue
  • Data protection review
Phase 2One document type
  • Schema and extraction
  • Labelled sample
  • Review UI
Phase 3Harden
  • Cross-checks and thresholds
  • Idempotent posting
  • Monitoring
Phase 4Extend and hand off
  • Further document types
  • Runbooks
  • Change process for schemas
Phased delivery: start with one high-volume document type and add others on the same rails.

Ongoing monitoring of exception rates, corrections and drift by document type followed the measure-and-manage approach of the NIST AI Risk Management Framework4.

Key decisions and trade-offs

DecisionAlternativeWhy
Vision LLM with schemasTemplate OCR per layoutHandles layout variety without a template for every supplier
Deterministic postingAgent with system accessModel holds no credentials; injection cannot cause writes
Evidence-based confidenceModel self-reported scoresThresholds grounded in checks and measured error rates
Reason-coded exceptionsGeneric review queueShows which rule or field to improve next
Versioned schemas per typeOne generic document schemaClear validation and safe, reviewable change

What I'd do again, and differently

Again: keep the model away from credentials and let validation, not the model, decide what is posted. Differently: build the labelled sample before the pipeline. Every threshold discussion went faster once there was a shared set of real documents to measure against.

If you're planning something similar, the AI architect page describes how I run these engagements, or analyse your challenge and bring the result to a call.

References
  1. 1
  2. 2
    LLM01:2025 Prompt InjectionOWASP Gen AI Security Project
  3. 3
    Constraints (PostgreSQL documentation)PostgreSQL Global Development Group
  4. 4
FAQ

Common questions

Can an LLM extract data from leases and invoices reliably?

It can extract most fields well, but reliability comes from what surrounds the model: a strict output schema, deterministic validation, cross-checks against known data and a review queue for anything uncertain.

Should the model post directly to the core system?

No. The model should only produce a candidate record. Deterministic code validates it and posts it, so the model never holds credentials or decides what is written.

How do you set confidence thresholds?

Measure against a labelled sample of real documents, per document type and per field, and set thresholds from observed error rates rather than the model's self-reported certainty.

Keep reading

Related

Open to advisory, fractional CTO & select builds

Let's talk about what you're building.

The fastest route is a free 30-minute call. Prefer to write? Send a message and I'll reply personally within two business days.

Start a conversation

How would you like to reach me?

Book a 30-min callFastest. Pick any open slot on my calendar.→ Write in GmailOpens a pre-filled draft in your browser.→ Use my email appOutlook, Apple Mail or your default client.→

I reply personally within two business days. Time zones from the Americas and Europe to the Middle East and Asia-Pacific.