AI
EstimateIQ uses AI for three jobs in the revision loop: parsing auditor notes, writing a next-best-action brief, and powering semantic search. Language-model calls run through an authenticated Cloudflare AI Gateway to Claude; if the gateway or a key is unavailable a deterministic fallback keeps every feature working with zero keys.
How inference is routed
Model calls go to the account’s authenticated AI Gateway (derekdavis) at its OpenAI-compatible
/compat/chat/completions endpoint. The model is expressed as <provider>/<model> (default
anthropic/claude-sonnet-4-6), the provider key authorizes the call, and CF_AIG_TOKEN
authenticates the gateway — giving centralized logging, caching, and rate control over every request.
If no gateway (or provider key) is configured, EstimateIQ falls back — first to a direct Claude call,
finally to a deterministic rule-based parser and templated brief. The output is structurally
identical, so downstream code never branches on which path produced it. Each response reports its
provider (gateway, claude, or deterministic).
Task 1 — Parse the auditor note
When a carrier returns an estimate with a desk-audit note (logged from the
deal detail page or pushed via the
XactAnalysis webhook), parseAuditorNote turns the free text into structured
data:
{ "reasonCodes": ["DEPRECIATION", "PRICING"], "disputedItems": [{ "code": "...", "desc": "...", "issue": "..." }], "summary": "..."}Reason codes come from a fixed taxonomy: OP_DISPUTE, DEPRECIATION, CODE_VERIFICATION, PRICING,
DOCUMENTATION, DUPLICATE_LINE, SCOPE, QUANTITY, MISSED_ITEM, DEDUCTIBLE.
The parsed result drives the rest of the revision handling:
- The revision leg stores the reason codes + disputed items on the swimlane.
- Disputed line items are flagged
challengedby code. - The per-carrier rules engine evaluates the reason codes, delta, round, loss type, and phase — firing priority overrides, SLA overrides, assignments, and follow-ups.
- The estimate’s
nextActionand the auto-generated respond follow-up are set from the summary.
The deterministic fallback matches the note against a regex table for reason codes and extracts Xactimate-style code tokens for disputed items — so parsing always returns usable structure.
Task 2 — Next-best-action brief
Given an estimate’s state and history (carrier, status, ball, round, days held vs budget, last note,
reason codes), EstimateIQ writes a 2–3 sentence recommendation of the single next move. The brief is
persisted to R2 (ai/brief/:id.json) so it stays stable between views; Refresh from model on
the detail page recomputes and re-saves it. Without a model, a deterministic brief is composed from
the ball and aging (e.g. “Carrier has held round 3 for 8d, past the ~5d desk-audit window — call the
desk adjuster.”).
Task 3 — Semantic search
Search is embedding-based. Workers AI (bge-base-en-v1.5) embeds the full content of every
estimate — header, carrier, every revision/auditor note, line items, and follow-ups — into the
Vectorize index; a query is embedded and matched against it, with results cached in KV. See
Search for the operator view and Data loading for
POST /api/admin/reindex.
Tuning AI in-app
GET /api/ai/config returns the current model + prompts, the built-in defaults, and any env
overrides (AI_GATEWAY_MODEL, AI_GATEWAY_URL). Saving writes PUT /api/settings/aiConfig.
Endpoints
GET /api/ai/config # current model + prompts (+ defaults + env)POST /api/ai/parse-revision # parse an auditor note → reason codes + disputed itemsPOST /api/ai/next-best-action/:id # compute a brief for a specific estimateGET /api/ai-brief/:id # read the persisted brief (from R2)POST /api/ai-brief/:id # recompute + persist the brief (from R2)GET /api/search?q=... # semantic search (Workers AI + Vectorize, KV-cached)POST /api/admin/reindex # re-embed every estimate into Vectorize (admin)See the API reference for the full surface.