| <article class="doc" id="doc-00-overview" aria-hidden="true"><div class="strip"><span class="path">00-overview.md</span><span class="tag">Engineering, start here</span><span class="meta">~6 min read</span></div> |
| <h1>Travi AI Agent: System Overview</h1> |
| <p>This is the modular form of the MVP Software Architecture Specification. Same decisions, same numbers, reorganized so nobody has to read 47 pages to do one task.</p> |
| <h2 id="doc-README--h1">Layout</h2> |
| <pre><code>00-overview.md ← start here (10-minute plain-English read) |
| adr/ ← 18 one-page Architecture Decision Records |
| README.md ← register/index of all ADRs |
| ADR-001 … ADR-018.md |
| modules/ ← one brief per backend module (the unit of work) |
| identity-consent.md ingestion.md compiler.md episode.md |
| medication.md scheduling.md notification.md brief.md |
| agents.md admin.md analytics.md audit.md |
| reference/ ← cross-cutting contracts |
| platform.md (stack, repo layout, CI/CD, cloud, environments, actors) |
| data-model.md (entities, fields, invariants, indexing, outbox) |
| api.md (conventions + full endpoint catalog + payloads) |
| security.md (threat model → controls, crypto, compliance) |
| operations.md (alerts, dashboards, config keys, scheduled jobs) |
| testing.md (test layers, extraction thresholds, 12 golden scenarios) |
| nfr.md (the consolidated non-functional requirements table) |
| delivery-plan.md (team, 12 sprints, phase gates, DoD, partner ratification) |
| traceability.md (every PRD requirement → owning module → verifying test) |
| glossary.md |
| assets/architecture.png |
| spec/ ← the original 47-page master spec (PDF), retained in the private repo for §-references |
| </code></pre> |
| <p><strong>Cross-references:</strong> any <code>§N.N</code> you see points to the master spec (retained in the private repo), the modular files were generated from it and stay faithful to it. If the two ever disagree, the ADR files win (they are the decision log).</p> |
| <div style="background:var(--forest-pale);border:1px solid var(--border-dark);border-radius:10px;padding:12px 16px;margin:0 0 20px;font-size:13.5px;line-height:1.55;"><strong>Where does the work happen?</strong> This overview and the module/reference/ADR pages it describes are the <em>encyclopedia</em>. The <em>to-do list</em> is the <a href="#doc-engineering-start">14 development phases</a>, sequential, DoD-gated, and status-tracked. Build from the phases; consult these pages when a phase's deep-reference line points here.</div> |
| <h2 id="doc-README--h2">Reading paths</h2> |
| <div class="tbl-wrap"><table class="col-table"><colgroup><col class="col-auto"/><col class="col-lg"/></colgroup> |
| <thead> |
| <tr> |
| <th>You are…</th> |
| <th>Read</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td data-label="You are…">New engineer, day 1</td> |
| <td data-label="Read"><code>00-overview.md</code> → <code>reference/platform.md</code> → your module brief</td> |
| </tr> |
| <tr> |
| <td data-label="You are…">Implementing a feature</td> |
| <td data-label="Read">Module brief → <code>reference/data-model.md</code> + <code>reference/api.md</code> sections it names → the ADRs it lists</td> |
| </tr> |
| <tr> |
| <td data-label="You are…">Security / compliance reviewer</td> |
| <td data-label="Read"><code>reference/security.md</code> → <code>adr/ADR-017</code>, <code>ADR-018</code> → <code>reference/testing.md</code></td> |
| </tr> |
| <tr> |
| <td data-label="You are…">Design-partner (hospital) reviewer</td> |
| <td data-label="Read"><code>00-overview.md</code> → <code>adr/README.md</code> (the 7 GATED rows) → <code>reference/delivery-plan.md</code></td> |
| </tr> |
| </tbody> |
| </table></div> |
| <h2 id="doc-README--h3">Using this with AI coding agents (Claude Code, etc.)</h2> |
| <p>The set is deliberately sized so each file fits comfortably in a context window. Recipe per task:</p> |
| <ol> |
| <li><strong>Always include:</strong> <code>00-overview.md</code> (or pin it as project memory / <code>CLAUDE.md</code>, section 3 "five hard rules" is the part that must never fall out of context).</li> |
| <li><strong>Include the one module brief</strong> you're working in, it states the module's invariants, its data, its API surface, and which ADRs constrain it.</li> |
| <li><strong>Include only the named reference sections</strong> the brief points to (e.g., the <code>task_instance</code> table from <code>data-model.md</code>, not the whole file).</li> |
| <li><strong>Cite requirement IDs</strong> (e.g., <code>MED-006</code>) in commits/PRs, <code>reference/traceability.md</code> is the checklist that CI mirrors.</li> |
| <li><strong>Never let an agent edit an ADR</strong> to make a task easier. Amending an ADR is a human governance decision.</li> |
| </ol> |
| <h2 id="doc-README--h4">Provenance</h2> |
| <p>Generated July 2026 from <code>Travi AI Agent_MVP_Software_Architecture_Specification_v1_0</code> (retained in the private repo). Contents: Engineering Review + the Product Requirements Document + Investor Feasibility Plan, consolidated with all open decisions resolved to build defaults (see <code>adr/README.md</code> for which seven remain partner-gated).</p> |
| <p><em>The 10-minute read. Everything else in this doc set is detail behind this page.</em> |
| <em>Master spec: <code>spec/</code> (PDF). Cross-references like §14.4 point there.</em></p> |
| <hr> |
| <h2 id="doc-00-overview--h1">1. What this is</h2> |
| <p>Travi AI Agent is a hospital- or payer-sponsored platform that manages the <strong>30 days after a patient leaves the hospital</strong>, the window where heart-failure patients miss medications, skip follow-ups, and bounce back as readmissions.</p> |
| <p>The system reads the patient's final discharge paperwork, turns it into a simple day-by-day action plan, nudges the patient (or their caregiver) to complete each step, quietly fixes routine problems itself (calling the pharmacy, helping schedule a visit), and hands the outpatient doctor a one-screen summary right before the follow-up appointment.</p> |
| <p><strong>One sentence:</strong> it converts discharge <em>instructions</em> into completed <em>actions</em>, with almost zero new work for hospital staff or doctors.</p> |
| <h2 id="doc-00-overview--h2">2. Who touches it</h2> |
| <div class="tbl-wrap"><table class="col-table"><colgroup><col class="col-auto"/><col class="col-lg"/><col class="col-md"/></colgroup> |
| <thead> |
| <tr> |
| <th>Person</th> |
| <th>What they see</th> |
| <th>What they never see</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td data-label="Person"><strong>Patient</strong></td> |
| <td data-label="What they see">A "Today" screen with at most 3 actions, opened from a text message. No password, no app store.</td> |
| <td data-label="What they never see">Medical jargon, red alarms, the machinery underneath.</td> |
| </tr> |
| <tr> |
| <td data-label="Person"><strong>Caregiver</strong></td> |
| <td data-label="What they see">The same plan, if the patient invites them. Their own login, revocable anytime.</td> |
| <td data-label="What they never see">Anything the patient didn't grant.</td> |
| </tr> |
| <tr> |
| <td data-label="Person"><strong>Doctor (PCP)</strong></td> |
| <td data-label="What they see">A secure link → one screen: what changed, what the patient actually did, what needs a decision. Readable in 60 seconds.</td> |
| <td data-label="What they never see">A new portal, a dashboard to monitor, another inbox.</td> |
| </tr> |
| <tr> |
| <td data-label="Person"><strong>Hospital admin</strong></td> |
| <td data-label="What they see">Cohort setup, reports, kill switches.</td> |
| <td data-label="What they never see">A daily work queue. The system must not create routine labor.</td> |
| </tr> |
| </tbody> |
| </table></div> |
| <h2 id="doc-00-overview--h3">3. The five hard rules</h2> |
| <p>These are enforced in code and state machines, not just policy. Breaking any of them is a release-blocking bug.</p> |
| <ol> |
| <li><strong>AI never makes clinical decisions.</strong> No AI output can create, change, or stop a medication instruction. Only two things can: a fully validated extraction from a signed clinical document, or a doctor confirming with strong authentication.</li> |
| <li><strong>Every instruction traces to a source.</strong> Anything the patient or doctor sees links back to the exact sentence in the exact document it came from.</li> |
| <li><strong>Agents gather evidence; the engine decides.</strong> Automation (calling pharmacies, booking help) returns structured evidence. A deterministic workflow engine, never the agent, moves state.</li> |
| <li><strong>No PHI in notifications.</strong> Texts, pushes, and emails say "you have a new task" plus a link. Nothing medical on a lock screen.</li> |
| <li><strong>Never imply a doctor is watching.</strong> No message may suggest continuous clinician monitoring. Emergencies get approved 911/ED language, immediately.</li> |
| </ol> |
| <h2 id="doc-00-overview--h4">4. How an episode flows (day 0 → 30)</h2> |
| <ol> |
| <li><strong>Day 0, Discharge.</strong> Epic sends a discharge event. Within 15 minutes an episode exists; the patient gets an SMS link, proves who they are (date of birth + having the phone), consents, and lands on their Today screen. Under 2 minutes, no password.</li> |
| <li><strong>Day 0, Plan compilation.</strong> The pipeline parses the signed discharge documents, extracts medications/appointments/labs with an LLM, and runs every extracted fact through <strong>seven validation gates</strong> (schema, terminology, clinical sanity, verbatim source-span proof, similarity check…). Only facts that pass all seven become patient-visible tasks. Anything uncertain becomes a question for a human, never an instruction.</li> |
| <li><strong>Days 1–29, Execution.</strong> The patient answers simple prompts ("Were you able to pick up spironolactone?", done / not yet / can't do it / not sure). "Can't do it" triggers automation: the medication-access agent calls the pharmacy; the appointment agent helps schedule. Reminders escalate gently (push → SMS → voice → caregiver) and stop within 60 seconds of completion. A patient who goes silent 48 hours on a critical task triggers a caregiver alert; 72 hours escalates further.</li> |
| <li><strong>Before the follow-up visit.</strong> 24 hours before the PCP appointment, the system builds a snapshot brief and sends the doctor a secure link (email code, no account). If anything material changed since, the brief regenerates on open.</li> |
| <li><strong>After the visit.</strong> The doctor's new instructions (uploaded note/AVS) reprocess through the same pipeline and update the remaining plan. Old tasks are superseded, never deleted.</li> |
| <li><strong>Day 30, Close.</strong> A final handoff summary is generated; unresolved items are reported honestly; analytics freeze with fixed denominators (offered / activated / engaged / completed) so outcome numbers can't be gamed.</li> |
| </ol> |
| <h2 id="doc-00-overview--h5">5. The system in one picture</h2> |
| <p><img alt="Architecture" loading="lazy" src="assets/img/overview-architecture.png"/></p> |
| <p><strong>Stack in one paragraph:</strong> a single Python 3.12 / FastAPI backend (a <em>modular monolith</em>, 13 internal modules with enforced boundaries, one deployable) plus Celery background workers on Redis; PostgreSQL 16 as the only source of truth; S3 for documents; a React PWA for patients/caregivers/clinician briefs; AWS (ECS Fargate, three accounts, Terraform); LLM calls go through AWS Bedrock (Claude, version-pinned, temperature 0, zero data retention under BAA); Twilio for SMS/voice and SES for email.</p> |
| <h2 id="doc-00-overview--h6">6. The 13 modules</h2> |
| <div class="tbl-wrap"><table class="col-table"><colgroup><col class="col-auto"/><col class="col-lg"/></colgroup> |
| <thead> |
| <tr> |
| <th>Module</th> |
| <th>One-liner</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td data-label="Module"><code>identity</code> + <code>consent</code></td> |
| <td data-label="One-liner">Who you are, what you agreed to, every token and grant.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>ingestion</code></td> |
| <td data-label="One-liner">Everything in/out of Epic: discharge triggers, documents, the (later) summary export.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>compiler</code></td> |
| <td data-label="One-liner">Documents → validated facts → tasks. Owns the seven gates.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>episode</code></td> |
| <td data-label="One-liner">The state machines. The only thing allowed to change task/episode state.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>medication</code></td> |
| <td data-label="One-liner">The four separate truths about a med: ordered, sent, obtained, taken.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>scheduling</code></td> |
| <td data-label="One-liner">Follow-up <em>needs</em> vs actual <em>appointments</em>; assisted booking.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>notification</code></td> |
| <td data-label="One-liner">Channel ladders, quiet hours, the 60-second stop rule, silent-patient detector.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>brief</code></td> |
| <td data-label="One-liner">The doctor's one-screen snapshot and its staleness logic.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>agents</code></td> |
| <td data-label="One-liner">The six bounded agents and their policy envelopes + kill switches.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>admin</code></td> |
| <td data-label="One-liner">Tenant/cohort config, versioned publishes, kill-switch API.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>analytics</code></td> |
| <td data-label="One-liner">Honest denominators, execution reports, outcome coverage flags.</td> |
| </tr> |
| <tr> |
| <td data-label="Module"><code>audit</code></td> |
| <td data-label="One-liner">Append-only ledger of everything; 6-year WORM archive.</td> |
| </tr> |
| </tbody> |
| </table></div> |
| <p>Each has a brief in <code>modules/</code> written to be handed to a developer, or an AI coding agent, as the context for a task.</p> |
| <h2 id="doc-00-overview--h7">7. Ten decisions that matter most</h2> |
| <div class="tbl-wrap"><table class="col-table"><colgroup><col class="col-auto"/><col class="col-lg"/><col class="col-sm"/></colgroup> |
| <thead> |
| <tr> |
| <th>ADR</th> |
| <th>Decision (plain English)</th> |
| <th>Status</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td data-label="ADR">001</td> |
| <td data-label="Decision (plain English)">One deployable app with strict internal walls, not microservices.</td> |
| <td data-label="Status"><span class="pill p-d">Decided</span></td> |
| </tr> |
| <tr> |
| <td data-label="ADR">002/003</td> |
| <td data-label="Decision (plain English)">Python/FastAPI backend; React PWA frontend (launches from a text, works for elderly patients).</td> |
| <td data-label="Status"><span class="pill p-d">Decided</span></td> |
| </tr> |
| <tr> |
| <td data-label="ADR">006</td> |
| <td data-label="Decision (plain English)">LLM = Bedrock Claude, version-pinned, temp 0, no data retention. Swappable behind one gateway.</td> |
| <td data-label="Status"><span class="pill p-d">Decided</span></td> |
| </tr> |
| <tr> |
| <td data-label="ADR">007</td> |
| <td data-label="Decision (plain English)">Epic integration = real-time discharge feed (ADT) <strong>plus</strong> FHIR polling as backstop.</td> |
| <td data-label="Status">Default, partner ratifies</td> |
| </tr> |
| <tr> |
| <td data-label="ADR">008</td> |
| <td data-label="Decision (plain English)">Patient identity = date of birth + possession of the invited phone.</td> |
| <td data-label="Status">Default, partner ratifies</td> |
| </tr> |
| <tr> |
| <td data-label="ADR">009</td> |
| <td data-label="Decision (plain English)">Nine-level source hierarchy; signed documents always beat machine extraction.</td> |
| <td data-label="Status">Default, partner ratifies</td> |
| </tr> |
| <tr> |
| <td data-label="ADR">011</td> |
| <td data-label="Decision (plain English)">Unresolvable routine issues → weekly report (not a hospital queue), unless the contract buys Tier 2.</td> |
| <td data-label="Status">Default, partner ratifies</td> |
| </tr> |
| <tr> |
| <td data-label="ADR">012</td> |
| <td data-label="Decision (plain English)">Offline = encrypted "emergency card" cached on the phone (contact, 911 text, med list).</td> |
| <td data-label="Status"><span class="pill p-d">Decided</span></td> |
| </tr> |
| <tr> |
| <td data-label="ADR">013</td> |
| <td data-label="Decision (plain English)">Silent patient: 48 h → caregiver, 72 h → operations.</td> |
| <td data-label="Status">Default, partner ratifies</td> |
| </tr> |
| <tr> |
| <td data-label="ADR">018</td> |
| <td data-label="Decision (plain English)">Audit log is append-only in the database and write-once in S3 for 6 years.</td> |
| <td data-label="Status"><span class="pill p-d">Decided</span></td> |
| </tr> |
| </tbody> |
| </table></div> |
| <p>Full register with context and consequences: <code>adr/</code>.</p> |
| <h2 id="doc-00-overview--h8">8. Key numbers (the SLAs everything is built around)</h2> |
| <div class="tbl-wrap"><table class="col-table"><colgroup><col class="col-auto"/><col class="col-auto"/></colgroup> |
| <thead> |
| <tr> |
| <th>Thing</th> |
| <th>Number</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td data-label="Thing">Discharge → episode exists</td> |
| <td data-label="Number">≤ 15 min</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Activation, end-to-end</td> |
| <td data-label="Number">≤ 2 min</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Discharge → published plan</td> |
| <td data-label="Number">≤ 10 min p95</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Reminder stops after task completes</td> |
| <td data-label="Number">≤ 60 s</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Screens load</td> |
| <td data-label="Number">≤ 2 s p95</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Brief regenerates when stale</td> |
| <td data-label="Number">≤ 5 s p95</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Silent-patient triggers</td> |
| <td data-label="Number">48 h / 72 h</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Availability / RPO / RTO</td> |
| <td data-label="Number">99.9% / 15 min / 4 h</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Pilot scale</td> |
| <td data-label="Number">300–500 episodes, ~5,000 ceiling</td> |
| </tr> |
| <tr> |
| <td data-label="Thing">Human ops budget</td> |
| <td data-label="Number">≤ 10 min per episode</td> |
| </tr> |
| </tbody> |
| </table></div> |
| <h2 id="doc-00-overview--h9">9. Explicitly NOT in the MVP</h2> |
| <p>No open patient–doctor chat. No remote vital-sign monitoring. No autonomous triage or medication advice. No writing orders/medications into the EHR (only a static summary document, and even that ships later behind a flag). No booking at outside health systems. One condition (heart failure), one health system.</p> |
| <h2 id="doc-00-overview--h10">10. Where to go next</h2> |
| <ul> |
| <li><strong>New engineer:</strong> read this → <code>reference/platform.md</code> → your module's brief in <code>modules/</code>.</li> |
| <li><strong>Reviewer / security:</strong> <code>reference/security.md</code> → <code>adr/</code> → <code>reference/testing.md</code>.</li> |
| <li><strong>Clinical:</strong> <code>modules/compiler.md</code> (the gates) → <code>modules/notification.md</code> → <code>reference/testing.md</code> (golden scenarios).</li> |
| <li><strong>AI coding agent:</strong> see the recipe in <code>README.md</code>.</li> |
| </ul> |
| <div class="pn"><a class="pn-prev" href="#"></a><a class="pn-next" href="#"></a></div></hr></article> |
|
|