📘  Documentation

Deploy, scale & operate InsightXtract

InsightXtract runs entirely in your environment — your cloud, your data boundary, your choice of model. Start on a laptop with Docker Compose, then take the same containers to production on AWS, Azure, GCP, or OCI with Terraform. This is how.

InsightXtract is a self-hosted, container-native platform. Everything — the API, the console, the agentic extraction workers, the datastore, and the vector index — ships as containers you run inside your own network. Nothing leaves your boundary unless you point it at a hosted model, and even the model is your choice.

Architecture at a glance

InsightXtract is a small number of stateless services around a metadata database, an object store, and a vector index. The services scale horizontally; state lives in managed data services you already trust.

flowchart TB U["Users · Console
(browser)"] --> LB[Load balancer / CDN] API_CLIENTS["Your apps
(REST API · webhooks)"] --> LB LB --> WEB["Web / Console
(static, nginx)"] LB --> API["API service
(FastAPI · stateless)"] API --> WK["Extraction workers
(agentic · LangGraph · autoscaled)"] API --> DB[("Metadata DB
MySQL 8")] WK --> DB WK --> OBJ[("Object store
S3 / Blob / GCS / OCI")] WK --> VEC[("Vector index
RAG")] WK --> LLM["LLM provider
Claude · OpenAI · Bedrock ·
Vertex · Azure OpenAI · custom"] API --> IDP["Identity provider
OIDC / SAML"]

Everything is stateless except the datastores. The API and workers hold no local state, so you scale them by adding replicas. Durability lives in the database, the object store, and the vector index — all of which you can run as managed cloud services with backups and replication.

Components

ComponentWhat it isScales byState
Web / ConsoleStatic React app served by nginxReplicas behind the LB / CDNStateless
API serviceFastAPI — auth, projects, documents, REST APIHorizontal replicasStateless
Extraction workersAgentic LangGraph runners (classify, extract, resolve)Autoscale on queue depth / CPUStateless
Metadata DBMySQL 8 — projects, classes, results, auditVertical + read replicasDurable
Object storeDocuments & run artifacts (S3/Blob/GCS/OCI)Elastic (managed)Durable
Vector indexEmbeddings for RAG / semantic lookupManaged or self-hostedDurable
LLM providerYour chosen model endpointProvider concurrencyExternal
Identity providerOIDC/SAML (Okta, Entra ID, etc.)ManagedExternal

Clouds & models — bring your own

Each pluggable dependency has a native option on every major cloud. Set a few environment variables and InsightXtract uses the managed service you already run.

DependencyAWSAzureGCPOCI
ComputeECS Fargate / EKSContainer Apps / AKSCloud Run / GKEContainer Instances / OKE
DatabaseRDS MySQL / AuroraAzure DB for MySQLCloud SQL MySQLMySQL HeatWave
Object storeS3Blob StorageCloud StorageObject Storage
LLM (managed)Bedrock (Claude)Azure OpenAIVertex AIOCI Generative AI
Load balancerALB + CloudFrontFront DoorCloud Load BalancingOCI Load Balancer
SecretsSecrets ManagerKey VaultSecret ManagerOCI Vault

Models are provider-agnostic: point the API at Anthropic Claude (direct or via Bedrock/Vertex), OpenAI (direct or Azure OpenAI), or any custom/self-hosted OpenAI-compatible endpoint. The extraction agents are written against a provider interface, so switching is a config change, not a rebuild.

Configuration reference (core)

Every deployment is driven by environment variables. These are the essentials; the deployment guides list the full set.

VariablePurpose
DATABASE_URLMySQL connection string (host, db, user, password).
OBJECT_STORE_*Bucket/container name, region, and credentials (or workload identity).
LLM_PROVIDERanthropic · openai · bedrock · vertex · azure_openai · custom.
LLM_MODEL / *_API_KEYModel id and provider credentials (or cloud IAM role).
OIDC_*Issuer, client id/secret for SSO (Okta, Entra ID, etc.).
WORKER_CONCURRENCYParallel extractions per worker replica.

Document understanding & models

Two layers do the reading, and both are pluggable. The document layer turns a page into text, structure and geometry — where every value sits, which label owns it, and which box is ticked. The reasoning layer decides what those values mean. Keeping them separate is why the same agent configuration runs unchanged on a different cloud, and why an air-gapped deployment is a configuration rather than a fork.

Document layer — OCR & form understanding

A submission is not prose. A quarter of a typical application is tick boxes, and the printed text of a question lists every option whether or not it is selected — so text alone cannot answer it. The document layer returns selection state, key/value pairing and bounding boxes, which is what makes a checkbox answerable and a citation clickable.

EngineWhere it runsWhat it gives the agent
Amazon TextractAWSKey/value pairs with the printed label beside each value, SELECTION_ELEMENT state for every checkbox, table cells, and per-word bounding boxes with page numbers.
Azure AI Document IntelligenceAzurePrebuilt and custom form models, key/value pairs, selection marks, table structure, and polygons per field.
Google Document AIGCPForm Parser entities, checkbox state, table extraction, and normalised values with layout anchors.
Tesseract / PaddleOCRIn-cluster, no egressWord-level text and geometry for air-gapped or sovereign deployments where no managed service may be called.
Native text layerAnywhereFor digital PDFs and Office files, the embedded text is read directly — layout preserved, no OCR cost at all.

The agent asks the document layer for what it needs rather than receiving a fixed parcel: the whole page, one page again, a search across the submission, a worksheet as rows, or the form’s key/value pairs. Engines are selected per document class, so a scanned loss run and a digital exposure workbook in the same submission take different paths.

Reasoning layer — bring your own model

Model choice is a deployment decision, not a product one. The provider interface is narrow — text, vision, document, and tool-calling — so a model is swapped by configuration and the extraction agents, schemas and rules are untouched.

FamilyReached viaTypical use
Anthropic ClaudeAmazon Bedrock · Google Vertex AI · Azure · Anthropic APIDefault for extraction and agentic reading — long context, native document input, strong tool use.
Google GeminiVertex AI · Gemini APINative multimodal reading of long, image-heavy submissions.
OpenAI GPTAzure OpenAI · OpenAI APIWhere an enterprise has standardised on Azure OpenAI.
Open weightsBedrock · Vertex · vLLM in your clusterLlama, Mistral and similar — for air-gapped deployments, or cheap high-volume classification.

Models are chosen per task, not per deployment: a small fast model for the structural pass and classification, a stronger one for extraction, and an optional escalation model that is only reached when the first attempt cannot return usable output. Every call records the model, token counts and cost against the run.

Domain models — fine-tuned insurance SLMs

A generalist model has to be told what a retention is, what an ACORD 125 contains, and which of five names on a loss run is the claimant. A model fine-tuned on your own policies, forms and claim notes has absorbed it. InsightXtract serves both, and chooses between them per task rather than per deployment — because the tasks in a run are not alike.

TaskShapeRuns well on
PerceptionOne call per document: what kind of document is this, where are its sections and schedules. High volume, tightly bounded.A domain SLM, in your VPC
ClassificationOne call per document, choosing from a closed list of document classes, with the quote that settles it.A domain SLM, in your VPC
ExtractionFill a 60–120 field schema with citations, evidence and confidence, as strict JSON. Long structured output.A frontier LLM, or a domain model tuned on your forms
EscalationReached only when the primary model cannot return usable output. Rare by design.The strongest model you have

Set per document class, so a line of business is tuned without touching a schema:

document-class.yaml
ai_configuration:
  perception_model:  insightdlm/pc-7b        # domain SLM, in-VPC, no egress
  classifier_model:  insightdlm/pc-7b        # domain SLM
  extraction_model:  bedrock/claude-sonnet   # frontier
  escalation_model:  bedrock/claude-opus     # only on failure

That is the common pattern: the high-volume, well-bounded work runs on a small domain model inside your network, and a frontier model is reached for the hard remainder. Escalation is measured, not assumed — every call records which model answered, what it cost, and whether it was a first attempt or a retry, so the split between the two is a number you can see rather than a claim.

Domain models are served over any OpenAI-compatible endpoint — vLLM, SGLang, TGI or a managed deployment — so a model trained with InsightDLM on your own corpus is reached by pointing a base URL at it. Nothing about the agents, glossaries or post-processing rules changes; the model is a setting.

Training data you already have. Every extraction is written with its page, bounding box and the verbatim quote it was read from, and every human correction is captured with the reason it was made. Those are supervised examples with provenance attached — and the corrections are the highest-value ones, being exactly the cases the current model got wrong. Synthetic submissions can be generated from known data for a cold start, so a pilot can be scoped before any customer document is shared.

Deployment topologies

TopologyWhat it meansChosen when
Single-tenant SaaSWe run it, in an account dedicated to you. Your documents, database and object store are yours alone.You want the fastest start and have no requirement to hold the infrastructure.
Your cloud, your VPCTerraform into your account. Private subnets, workload identity instead of static keys, model reached over a private endpoint — no credential and no document leaves your network.The common enterprise choice, and the one the deployment guides are written for.
Air-gapped / sovereignNo egress at all: in-cluster OCR, open-weight models served locally, container images mirrored to an internal registry. The same agents and rules run unchanged.Data residency or classification rules forbid calling a managed service.

Deploying: see cloud deployment with Terraform for the managed-service mapping on AWS, Azure, GCP and OCI, or Docker Compose to run the whole stack locally first.

Extraction configuration

The settings above stand the platform up. These decide how it reads — and they are set per document class in the console, not in code, so an underwriting team can tune a line of business without a release. Defaults below are the ones we ship; where a default looks conservative, it is because measuring the alternative changed our mind.

How a document is read

SettingValuesDefaultWhat it does
extraction_modevision · textract_text · textvisionPage images, OCR text with coordinates, or plain text. On our benchmark corpus the text path was ~11% cheaper and 8% faster — less than the input-token difference suggests, because these workloads are output-bound — but it misread a broker’s identity from a carrier letterhead. Worth choosing for text-heavy sets with few tables.
layout_texttrue / falsefalseKeeps a PDF’s columns instead of reflowing it. A two-column coverage block flattens to Limit 1,000,000 Limit 1,000,000 / Premium $21,875 Premium $0.00, with nothing saying which column a figure belongs to. Turn it on for form-heavy classes.
enable_visiontrue / falsetrueForces a text-only path and skips page rendering entirely.
image_dpi · max_pagesinteger150 · 10Render fidelity against cost.
perception_modelmodel ida fast modelThe cheap structural pass that runs before extraction.

What gets verified

Both of these can only ever empty a field, so both ship off. A blank is recoverable; a confident wrong number is not.

SettingValuesDefaultWhat it does
label_checkoff · warn · strictoffChecks each value against the label the form prints beside it, using the key/value pairing OCR already produces — no extra model call. A figure sitting under “Premium” is not a retention. We recommend warn: it annotates and lowers confidence. Run strict during development first — on our own corpus an early, broader version of this check cleared ten correct values to catch one wrong one, which is why it narrowed to genuine conflicts and why clearing is not the default.
min_confidence0 – 10Empties any value the run itself is not confident in. Makes the precision/coverage trade explicit rather than leaving it to whatever the model happened to emit.

What gets computed

Anything derivable from data already extracted should be computed, not read. Repeatedly, a field description telling a model that two figures are different did not stop it copying one into the other — counting the rows did. Fourteen rule kinds run after extraction:

RulePurpose
standardize · format · lookup_codeGlossary and reference-table normalisation; dates, money and codes to a house standard.
derived_fieldsHeader figures computed from a table — count, count_distinct, sum, avg, min, max, first. A claim count that disagrees with the claims beneath it cannot be trusted on their value either.
derived_tables · project_tableBuild a schedule by rolling up or projecting another — a rating schedule assembled from whichever sheet in the submission carries class codes.
inferThirteen named inferences, each deterministic and each recording why it fired: parse_labelled_amount (one line stating several coverages’ figures), distinct_from, not_equal_to, not_before, absent_means_no, year_from_years, date_offset, compose_from_row, modal_column, legal_suffix, years_since, first_present, join_column.
merge_rows · dedupe_rowsFold rows describing the same thing. The same benefit plan named slightly differently on two forms is one plan — read as two, the fiduciary exposure doubles on paper.
map_column · copy_column · select_columnReconcile the header a workbook happens to use with the column your schema declares.
validateCross-field invariants — a policy period ends after it begins; a per-claim limit is not the aggregate.

Spreadsheets

Submission workbooks open with a title banner, so the header is rarely row 1, and one logical schedule is often split across regional tabs. EXCEL_CODEGEN (on by default) reasons about each sheet’s layout, writes code against what it finds, and caches that reader by sheet shape — so a workbook seen before is read by the same code every time, which is what makes two uploads of one file give one answer.

Everything is versioned

Each setting above lives in the document class or agent configuration, is versioned with it, and is visible in the run trace alongside the value it produced. A record shows not only what was extracted but which rules touched it — which is the difference between an answer and an auditable one.

Ask a folder — chat over a submission or a claim

Extraction answers the questions you knew to ask. An underwriter looking at a new submission, or an adjuster opening a first notice of loss, also has the other kind — is there a prior act exclusion in here, who signed the application and when, what did the broker actually say about the tower. Point at a folder in Drive, press Ask, and put those questions to the documents directly.

flowchart LR F["Folder
(submission or claim)"] --> P["Prepare · once
no model call"] P --> D[("Digest
page text · form key/values ·
ticked boxes · sheet shapes ·
word geometry")] D --> S["Cached prompt prefix"] Q["Question"] --> AG["Answer loop"] S --> AG AG -->|digest not enough| T["Tools · search across docs ·
read a page · read a sheet ·
read form key/values"] T --> AG AG --> A["Answer + verbatim quotes
+ table / chart + follow-ups"] A --> C["Citation opens the page,
words boxed"]
The Ask this folder panel — an answer with its citations and suggested follow-up questions, over a submission folder in Drive
Ask a folder from Drive — every answer carries the words it was read from.

Prepared once, then cheap

Preparing a folder is deterministic reading — no model is called — so it takes seconds and its only cost is OCR, paid once and stored. The digest then sits in the cached part of the prompt, ahead of the question. That placement is the whole cost story: with the folder behind the cache point, a question is a couple of pence; in front of it, the same question re-sends the entire folder as fresh input every time and costs roughly ten times more.

It will not answer without a quote

Every factual claim comes back with the verbatim words it rests on, the file, and the page. If the documents do not state something, the answer says exactly that rather than inferring a figure or filling the gap from general knowledge of insurance. An underwriter acting on a confident, unsupported sentence is the failure the whole platform exists to avoid.

Where the folder has already been extracted, questions the audited record answers are served from that record — instantly, at no cost, and in agreement with the record by construction. Re-reading the PDF to answer them again risks producing a different number than the one already reviewed, which is worse than not answering at all.

Citations you can open

A citation an underwriter cannot check is a claim, not evidence. Click one and the document opens at the page with the quoted words boxed. The rectangle comes from the document’s own word geometry — the quote is matched back against the page, never plotted from coordinates a model invented. Scanned pages are highlighted from the OCR geometry captured at prepare time. Where the exact words cannot be located, the page still opens and the viewer says so; a highlight over the wrong paragraph is worse than no highlight.

Tables, charts, and where to go next

When a comparison is the point — losses by policy year, expenses by function, revenue against expenses across years — the answer carries a chart alongside the prose, and every number in it is cited like any other figure. Longer answers come back as a table rather than a paragraph of pipes. Each answer also offers two or three follow-ups that this folder can actually answer, grounded in what was read rather than in what a question generator imagined.

Where the documents live

Nothing has to be uploaded anywhere new. A folder is whatever your storage location already points at — the same connectors extraction runs against, so a submission mailbox, a broker’s SharePoint site, or a bucket in your own account is askable the moment it is registered.

Location typeTypical use
SharePoint · OneDriveThe broker or agency site a submission arrives on, and the claim folder an adjuster works out of. Sites, drives and document libraries are browsed in place.
Outlook · TeamsSubmission mailboxes and channels — the email body and its attachments read together as one folder.
S3 · Azure Blob · Google Cloud Storage · OCI Object StorageYour own bucket, in your own account and region. Documents are read with your credentials and never copied outside your perimeter.

It answers with the permissions of whoever asked

Chat is not a back door round your document security. The folder is reached through the same registered location and the same credentials the rest of the platform uses, and the question runs under the asking user’s role — admin, builder, operator, reviewer or viewer. Someone who cannot open a folder in Drive cannot ask questions of it either, and a quote can only cite a document that user is entitled to read. Every question, the documents it read, and the answer it gave are recorded against the user, so “who asked what of this claim file” is answerable after the fact.

The same chat from your own applications

Everything the console does here is a REST call, so an underwriting workstation, a claims desktop, or an internal insights tool can offer the same interactive exploration inside its own screens — including the tables and charts, which come back as data rather than as pictures, ready to render in your own component library.

EndpointWhat it does
POST /folder-chat/prepareReads the folder and streams progress per document, so your UI can show the file being read rather than a spinner. Idempotent — a prepared folder returns immediately.
POST /folder-chat/askOne question plus the conversation so far. Returns the answer, its citations (file, page, verbatim quote and the rectangle on the page), an optional table, an optional chart as labels and series, suggested follow-ups, and what the call cost.
POST /folder-chat/forgetDrops the prepared copy and its digest — for a folder whose documents have changed.

Calls authenticate with a scoped API key, and usage is tracked per key, so an embedded assistant in another product is metered and governed like any other consumer of the platform.

Settings

SettingDefaultWhat it does
FOLDER_DIGEST_DIR/tmp/insightxtract/digestsWhere prepared digests are kept. Point it at a persistent volume so a restart does not re-read folders.
FOLDER_CHAT_STAGE/tmp/insightxtract/folder-chatStaging directory for the documents themselves, reused across questions so a follow-up does not re-download.
max_iterations8How many searches or reads one question may make before it must answer with what it has. Raise it for large folders.
Digest budget90,000 charsHow much of the folder is carried in the cached prefix. Beyond it the agent reads on demand through the tools.
Modelplatform defaultAny configured provider — the chat uses the same model routing as extraction.

Scale note. The digest carries a bounded slice of each document; beyond it, the agent searches and reads on demand. That fits targeted questions well — a limit, a date, a signature, what a form says. Very long documents (a few hundred pages of policy wording) and sweeping questions (“summarise every exclusion”) need more lookups than one question is given, so plan those as extraction jobs against a schema rather than as chat.

Next: stand it up locally with Docker Compose, or go straight to a production cloud deployment with Terraform.