A multi-agent prior-authorization triage system — a small, self-hostable homage to Cognizant's 2025–2026 healthcare-AI announcements (TriZetto Unify's agent-ready Electronic Prior Authorization, the Neuro AI Multi-Agent Accelerator, and Neuro AI Trust). A pipeline of specialized agents triages synthetic prior-auth requests, auto-approves only clear-cut cases, pends everything else to a human reviewer with machine-readable reasons, never auto-denies, and a guardian layer scores the pipeline's own trustworthiness.
100% synthetic data. No real PHI, ever. Every member, provider, and clinical answer comes from the deterministic seed generator (
python -m app.seed). Service codes (S1001…) are illustrative placeholders, not real CPT — CPT is AMA-licensed and isn't reproduced here. ICD-10 prefixes are real and public via CMS.
┌───────────────────────── ORCHESTRATOR (sequential state machine) ─────────────────────────┐
PA request → │ IntakeAgent → EligibilityAgent → PolicyAgent → ClinicalDocAgent → DecisionAgent │ → APPROVED
(JSON) └──────┬─────────────┬─────────────────┬──────────────────┬────────────────┬────────────────┘ or PENDED → human queue
▼ ▼ ▼ ▼ ▼
AUDIT LOG (per step: agent, input digest, output JSON, confidence, latency ms, adapter used)
▲
GuardianAgent (post-hoc): re-checks decision vs. evidence, flags anomalies, emits trust score
Rules run first; the LLM (mockable) only evaluates policy criteria and is
always schema-validated — an unparseable or ambiguous answer fails safe to
unclear, which pends the case. Every step writes an audit row before the
next one runs, so the trace is complete even when a step fails.
cp .env.example .env
make install
make demo
make devThen open http://localhost:5173. Everything above runs with
MOCK_MODE=true (the default) — no Anthropic API key required.
If make isn't available (e.g. plain Windows without WSL), run the
equivalent commands directly: python -m venv backend/.venv +
pip install -e "backend[dev]", npm install in frontend/, then
python -m app.demo and python -m uvicorn app.main:app --port 8000 +
npm run dev from their respective directories.
Seeding 60 requests with --seed 42 and batch-processing in MOCK_MODE
produces:
| Outcome | Count |
|---|---|
| APPROVED | 22 (37%) |
| PENDED | 38 (63%) |
| Reason code | Count |
|---|---|
| LOW_CONFIDENCE | 34 |
| ELIG_FAIL | 19 |
| DUPLICATE | 7 |
| CRITERION_UNMET | 4 |
| CRITERION_UNCLEAR | 4 |
| DOCS_MISSING | 4 |
(LOW_CONFIDENCE mostly co-occurs with another reason — see Decisions below
for how aggregate confidence is computed.) Guardian trust score averages
100/100 on this dataset since every pipeline run completes cleanly in mock
mode.
| AuthPilot feature | Cognizant thing it mirrors |
|---|---|
| Prior authorization as the use case | TriZetto Unify's first agent-ready solution is Electronic Prior Authorization (May 2026) |
| Specialized agents + one orchestrator | Neuro AI Multi-Agent Accelerator |
| GuardianAgent, trust score, full trace | Neuro AI Trust — guardian agents, observability, trust scoring |
| Approve-or-pend, never auto-deny | Their principle: agents take administrative friction; clinical decisions stay with humans |
| Policy-governed decisions + audit log | TriZetto's agent access is policy-governed and auditable by design |
| MOCK_MODE + strict schema validation of LLM output | Production mindset: cost control, and never trusting raw model output in a regulated workflow |
Judgment calls made where the spec was ambiguous, instead of gold-plating:
- Aggregate confidence = min() of the four upstream agents' confidences, not an average — a single weak link (e.g. an unclear criterion) should drag the whole case below the auto-approve threshold, not get diluted.
- "Service category covered by plan" lives in EligibilityAgent, per its
own spec description — an unmatched service code fails eligibility
(
ELIG_FAIL) rather than needing a new reason code. - IntakeAgent failures map to
PIPELINE_ERROR. The API layer already enforces the request schema via Pydantic, so a failure here is a defensive safety net, not a routine pend path — no seed defect exercises it. - Guardian's latency bounds are generous (10s/step, 30s total) since the pipeline runs in-process against rules/mock data; a real LLM call would still fit comfortably under them.
- No React Router. Four pages don't justify a new dependency — plain
useStatenavigation inApp.tsxcovers it. - Policy markdown gets a ~15-line hand-rolled renderer (headings, lists, inline bold) instead of a markdown-parser dependency, since the five policy files are the only content it ever needs to handle.
- Seed collision avoidance: clean requests are generated with a
retry loop so they don't accidentally land inside the duplicate-detection
window by chance — only the deliberate
duplicate_submissiondefect should triggerDUPLICATE.
make test runs the full backend suite (pytest). Coverage focuses on
app/engine/: table-driven rule tests, mock-mode agent tests, the full
orchestrator over the seeded 60, and the safety invariants that must never
be deleted — the Outcome enum is exactly {APPROVED, PENDED}, no
APPROVED decision ever contains an unmet/unclear criterion, and review
without a rationale is rejected with 422.
User accounts/auth, Kubernetes, message queues, vector databases, and microservices are deliberately not part of this project — the scope is the feature, and TriZetto's real prior-auth agents run at a scale none of that would meaningfully demonstrate here anyway.
MCP server exposing submit_prior_auth / get_case_status /
list_pending_cases, FHIR-shaped ingest, a reviewer-feedback threshold
suggestion, and Docker packaging — see the original design doc for details.