AI doesn't assist the workflow — it drives it. Below is how the system is designed.
Next.js 16
App Router, API Routes, Middleware Auth
Auth Layer
NextAuth JWT, per-route validation, role hierarchy
AI Engine
Claude with tool_use — chat, single-shot, and multi-step runs
Tool Execution
11 tools: search, update, remind, note, query, policy lookup, email, documents
Supabase
Postgres, RLS, Storage, real-time
The AI agent uses tool_use to reason and act in a loop. Each iteration: the AI decides what to do, the system validates and executes the tool, then returns the result for the next reasoning step.
while (iterations < MAX_TOOL_CALLS) {
response = ai.messages.create(tools, messages)
if (no tool_use) return response.text
for (tool in response.tool_use) {
validate(tool.name) // reject hallucinated tools
result = executeTool(tool) // try/catch with error recovery
messages.push(tool_result)
}
}
The chat loop above is one entry point. The same tool surface also drives goal-directed runs, saved procedures, and reach into external systems — with a human in the loop on the decisions that matter.
Multi-step runs
lib/agent-runner.tsGive the agent a goal on a claim. It plans 3–8 steps, executes each through the same validated tool surface, and writes a live trace you can watch. High-stakes steps (settlement, denial) pause for human sign-off instead of auto-applying.
Operating procedures
app/aopsSaved, named procedures — a plain-English goal plus the conditions for when it applies. Run on demand, or fire automatically on matching new claims. Draft / Live / Paused, so a manager rolls one out without surprising the existing book.
External systems
app/portal/carrier-xThe agent reaches beyond its own DB: lookup_policy pulls coverage from a carrier portal; send_email_and_wait emails a claimant and blocks on their reply. Both shaped like real integrations, so swapping in a live adapter is a one-file change.
Email intake
lib/email-intake.tsThe claims@ inbox, triaged by the agent: each inbound email is classified and extracted by the model, then deterministic rules route it — create the claim, attach to the referenced claim, or park it as an exception with a stated reason. Low confidence never acts alone.
Forward-deployed: an agent operating a legacy carrier portal
The same external-systems idea, taken to the real case: an agent that reads and drives a legacy portal in a browser, no API, with a 3/3 eval scored against the system of record.
JWT Auth
Protected API routes validate the NextAuth token before processing; public demo routes have explicit gates, limits, and budgets
Zod Validation
Request bodies validated against strict schemas — rejects malformed input
Tool Whitelist
Agent can only call 11 predefined tools — hallucinated tool names are rejected
Field Whitelist
Only specific claim fields can be modified — no arbitrary DB writes
Injection Resistance
Untrusted text (operator goals, public intake) is delimited as data in agent prompts — instructions inside it are not followed
Spend Cap
Every Claude call is metered to a usage table; a global daily budget returns HTTP 429 before the bill runs away
Human Sign-off
High-stakes agent steps (settlements, denials) pause the run for review instead of auto-applying
Error Recovery
Tool failures return structured errors to the AI — agent recovers gracefully
Audit Trail
Every agent action logged with timestamp, tool name, and outcome
Eval Gate
CI runs the eval suite on every PR that touches an AI path — regressions block the merge
What I'd add before deploying to enterprise customers: