# matiasmoram/prosperai-challenge architecture

> Architecture diagram of the GitHub repository matiasmoram/prosperai-challenge, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-26). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/matiasmoram/prosperai-challenge
- Repository: https://github.com/matiasmoram/prosperai-challenge

## Overview

1. **Overall shape**
   - The repo is organized around **three runtime processes**: the **voice bot** (`bot.py` / `src/prosper`), the **FastAPI EHR service** (`src/prosper/ehr`), and the optional **Operator Console** (`src/prosper/console`).
   - A fourth major boundary is the **eval/test harness** (`evals/`, `tester/`, `tests/`), which exercises the bot and EHR without being part of the live call path.

2. **Live call path**
   - The bot process connects the browser client to a conversational pipeline built on **Pipecat**, **ElevenLabs STT/TTS**, and **OpenAI chat models**.
   - User audio enters the voice pipeline, becomes text, is routed by the dispatcher, then the response is synthesized back to audio for the browser client.

3. **Conversation control layer**
   - `src/prosper/dispatcher.py`, `flows.py`, `prompts.py`, `tools.py`, and `speculation.py` implement the core control logic.
   - The design is a **hybrid finite-state machine** with **per-state tool whitelists**: the model can only call tools allowed by the current state.
   - Tool execution returns typed `Result[Ok, Err]` values; error codes are part of the public behavior and are asserted by tests/evals.

4. **Clinical workflow states**
   - The bot is not a generic chat assistant; it follows a scripted clinical flow for booking, canceling, rescheduling, triage, confirmation, and handoff.
   - The state machine is the main boundary between “free-form model reasoning” and “safe, bounded business actions.”

5. **EHR service boundary**
   - The EHR lives in a **separate FastAPI process** on port 8000 and is the authoritative system for patients, slots, and appointments.
   - It exposes patient lookup, availability, create appointment, cancel appointment, and health endpoints.
   - Persistence is via **SQLite + SQLAlchemy**; seeded slots and database constraints are used to enforce idempotency and prevent duplicate booking races.

6. **Data access inside the EHR**
   - The EHR is split into `models`, `schemas`, `repository`, `db`, and `api`, which cleanly separates transport, validation, and persistence.
   - This separation is important for the architecture diagram: the bot never talks to the database directly; it only goes through the EHR HTTP API via `src/prosper/ehr_client.py`.

7. **External integrations**
   - The bot depends on two external AI services: **ElevenLabs** for speech and **OpenAI** for the dispatcher LLM and eval judge.
   - `src/prosper/integrations/` contains auxiliary integrations and a routing layer; these appear to support additional side systems beyond the core EHR workflow, but they are not the primary booking path.

8. **Observability and audit**
   - `src/prosper/observability/` handles **timing** and **PII redaction**.
   - The console subsystem publishes an event stream and also writes an **append-only JSONL audit log** per session under `data/audit/`.
   - The audit boundary is intentionally redacted at event emission, so logs are safe to replay/share without a second scrub pass.

9. **Operator Console**
   - The console is a separate FastAPI/SSE surface on port 7861 that subscribes to live bot events.
   - It shows FSM state, tool calls, latencies, transcript, patient identity with PII masked, offered slots, and final outcome.
   - Architecturally, this is a **read-only monitoring plane** fed from the bot’s event bus, not a control plane.

10. **Evaluation system**
   - `evals/` is a first-class subsystem with scenario generation, scripted runs, a deterministic mock LLM, a judge, and trace replay.
   - Every eval checks both **state assertions** and an **LLM judge**, so correctness is not tied to only one validation strategy.
   - Live evals can mount the EHR in-process with `httpx.ASGITransport`, which keeps the harness hermetic while preserving the HTTP boundary semantics.

11. **Human-simulation and adversarial testing**
   - `tester/` provides persona models, noise injection, clarification behavior, and receipt-gate logic to simulate messy call behavior.
   - `tests/adversarial/` and the rest of `tests/` probe routing, redaction, invariants, concurrency, transport errors, and edge-case conversation behavior.
   - This repo is therefore test-driven around the architecture boundaries: dispatcher, EHR, observability, console, and eval harness.

12. **Deployment and operations**
   - The live system is typically run as **two local processes** (`make ehr` and `make bot`), or together via Docker Compose.
   - CI is built around linting, type checking, unit tests, and eval coverage, with a separate offline mock-eval path to avoid external API cost.
   - The main architectural takeaway is that the project is a **voice-agent orchestration system with a separate clinical backend**, plus an observability/eval layer designed to validate behavior end-to-end.

Main entry points: [`src/prosper/dispatcher.py`](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/dispatcher.py) (Dispatcher), [`src/prosper/bot.py`](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/bot.py) (Agent core), [`evals/runner.py`](https://github.com/matiasmoram/prosperai-challenge/blob/main/evals/runner.py) (Eval runner), [`src/prosper/ehr/api.py`](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/api.py) (EHR service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_g_live["Live call path"]
  node_bot_runtime["Bot runtime<br/>voice process<br/>[bot.py]"]
  node_bot_core["Agent core<br/>pipeline core<br/>[bot.py]"]
  node_dispatcher["Dispatcher<br/>fsm router<br/>[dispatcher.py]"]
  node_flows["Flows<br/>state flow<br/>[flows.py]"]
  node_prompts["Prompts<br/>prompt set<br/>[prompts.py]"]
  node_tools["Tools<br/>typed actions<br/>[tools.py]"]
  node_speculation["Speculation<br/>prefetch logic<br/>[speculation.py]"]
  node_ehr_client["EHR client<br/>http client<br/>[ehr_client.py]"]
end

subgraph group_g_ehr["Clinical backend"]
  node_ehr_service["EHR service<br/>fastapi app<br/>[api.py]"]
  node_ehr_repo["Repository<br/>persistence<br/>[repository.py]"]
  node_ehr_models[("Models<br/>[models.py]")]
  node_ehr_schemas["Schemas<br/>[schemas.py]"]
  node_ehr_db[("SQLite DB<br/>sqlite store<br/>[db.py]")]
end

subgraph group_g_console["Operator console"]
  node_console_server["Console server<br/>sse app<br/>[server.py]"]
  node_console_bus["Event bus<br/>pubsub stream<br/>[bus.py]"]
  node_console_audit["Audit log<br/>jsonl audit<br/>[audit.py]"]
end

subgraph group_g_eval["Eval and test harness"]
  node_eval_runner["Eval runner<br/>scenario harness<br/>[runner.py]"]
  node_eval_sim["Sim runner<br/>mock runtime<br/>[sim.py]"]
  node_eval_judge["Judge<br/>llm evaluator<br/>[judge.py]"]
  node_tester["Human sim<br/>persona/noise"]
end

subgraph group_g_support["Support systems"]
  node_llm["LLM adapter<br/>model access<br/>[llm.py]"]
  node_observability["Observability<br/>redact timing"]
  node_integrations["Integrations<br/>aux services"]
end

node_bot_runtime -->|"starts"| node_bot_core
node_bot_core -->|"uses"| node_dispatcher
node_dispatcher -->|"advances"| node_flows
node_dispatcher -->|"selects"| node_prompts
node_dispatcher -->|"permits"| node_tools
node_dispatcher -->|"prefetches"| node_speculation
node_dispatcher -->|"calls"| node_llm
node_tools -->|"invokes"| node_ehr_client
node_ehr_client -->|"requests"| node_ehr_service
node_ehr_service -->|"validates"| node_ehr_schemas
node_ehr_service -->|"delegates"| node_ehr_repo
node_ehr_repo -->|"persists"| node_ehr_models
node_ehr_repo -->|"stores"| node_ehr_db
node_bot_core -->|"emits events"| node_console_bus
node_console_bus -->|"streams"| node_console_server
node_console_bus -->|"records"| node_console_audit
node_console_server -->|"redacts"| node_observability
node_bot_core -->|"measures"| node_observability
node_eval_runner -->|"executes"| node_eval_sim
node_eval_runner -->|"scores"| node_eval_judge
node_eval_runner -->|"uses"| node_llm
node_tester -->|"feeds"| node_eval_sim
node_tester -.->|"stresses"| node_dispatcher
node_integrations -.->|"extends"| node_bot_core
node_integrations -.->|"logs"| node_observability

click node_bot_runtime "https://github.com/matiasmoram/prosperai-challenge/blob/main/bot.py"
click node_bot_core "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/bot.py"
click node_dispatcher "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/dispatcher.py"
click node_flows "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/flows.py"
click node_prompts "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/prompts.py"
click node_tools "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/tools.py"
click node_speculation "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/speculation.py"
click node_ehr_client "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr_client.py"
click node_llm "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/llm.py"
click node_observability "https://github.com/matiasmoram/prosperai-challenge/tree/main/src/prosper/observability"
click node_ehr_service "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/api.py"
click node_ehr_repo "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/repository.py"
click node_ehr_models "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/models.py"
click node_ehr_schemas "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/schemas.py"
click node_ehr_db "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/db.py"
click node_console_server "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/console/server.py"
click node_console_bus "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/console/bus.py"
click node_console_audit "https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/console/audit.py"
click node_eval_runner "https://github.com/matiasmoram/prosperai-challenge/blob/main/evals/runner.py"
click node_eval_sim "https://github.com/matiasmoram/prosperai-challenge/blob/main/evals/sim.py"
click node_eval_judge "https://github.com/matiasmoram/prosperai-challenge/blob/main/evals/judge.py"
click node_tester "https://github.com/matiasmoram/prosperai-challenge/tree/main/tester"
click node_integrations "https://github.com/matiasmoram/prosperai-challenge/tree/main/src/prosper/integrations"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_bot_runtime,node_bot_core,node_dispatcher,node_flows,node_prompts,node_tools,node_speculation,node_ehr_client toneBlue
class node_ehr_service,node_ehr_repo,node_ehr_models,node_ehr_schemas,node_ehr_db toneAmber
class node_console_server,node_console_bus,node_console_audit toneMint
class node_eval_runner,node_eval_sim,node_eval_judge,node_tester toneRose
class node_llm,node_observability,node_integrations toneIndigo
```

## Components

### Live call path

Runtime bot process that handles the browser voice call and conversation control.

- [Bot runtime](https://github.com/matiasmoram/prosperai-challenge/blob/main/bot.py): voice process · Entry process for the live voice agent; wires the conversation pipeline together. · `bot.py`
- [Agent core](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/bot.py): pipeline core · Main bot orchestration module used by the runtime. · `src/prosper/bot.py`
- [Dispatcher](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/dispatcher.py): fsm router · Hybrid finite-state routing and tool permissioning layer. · `src/prosper/dispatcher.py`
- [Flows](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/flows.py): state flow · Clinical workflow states and transitions for booking, triage, cancel, reschedule, and handoff. · `src/prosper/flows.py`
- [Prompts](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/prompts.py): prompt set · System and state-specific instructions for the model. · `src/prosper/prompts.py`
- [Tools](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/tools.py): typed actions · Bounded business actions with Result-style success and error outcomes. · `src/prosper/tools.py`
- [Speculation](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/speculation.py): prefetch logic · Support for speculative routing and early intent handling. · `src/prosper/speculation.py`
- [EHR client](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr_client.py): http client · Bot-side HTTP boundary to the clinical service; no direct database access. · `src/prosper/ehr_client.py`

### Clinical backend

Separate FastAPI EHR service and its data access layers.

- [EHR service](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/api.py): fastapi app · Separate clinical API process serving patients, slots, and appointments. · `src/prosper/ehr/api.py`
- [Repository](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/repository.py): persistence · Data access layer that mediates all database operations. · `src/prosper/ehr/repository.py`
- [Models](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/models.py): sqlalchemy models · Persistent entities and constraints for appointments and related records. · `src/prosper/ehr/models.py`
- [Schemas](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/schemas.py): validation schemas · Transport and validation models for the EHR API. · `src/prosper/ehr/schemas.py`
- [SQLite DB](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/ehr/db.py): sqlite store · Database setup and engine/session management for the EHR. · `src/prosper/ehr/db.py`

### Operator console

Read-only monitoring plane fed by bot events and audit streams.

- [Console server](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/console/server.py): sse app · FastAPI/SSE surface for live monitoring and session views. · `src/prosper/console/server.py`
- [Event bus](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/console/bus.py): pubsub stream · In-process event distribution from the bot to console subscribers. · `src/prosper/console/bus.py`
- [Audit log](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/console/audit.py): jsonl audit · Append-only, redacted per-session audit trail. · `src/prosper/console/audit.py`

### Eval and test harness

Scenario, simulation, and adversarial validation around the live architecture.

- [Eval runner](https://github.com/matiasmoram/prosperai-challenge/blob/main/evals/runner.py): scenario harness · Scenario execution and scripted evaluation entrypoint. · `evals/runner.py`
- [Sim runner](https://github.com/matiasmoram/prosperai-challenge/blob/main/evals/sim.py): mock runtime · Deterministic simulation and mocked live-call execution. · `evals/sim.py`
- [Judge](https://github.com/matiasmoram/prosperai-challenge/blob/main/evals/judge.py): llm evaluator · LLM-based scoring alongside state assertions. · `evals/judge.py`
- [Human sim](https://github.com/matiasmoram/prosperai-challenge/tree/main/tester): persona/noise · Adversarial call simulation with noise, clarification, and receipt-gate behavior. · `tester`

### Support systems

Shared libraries for LLM access, observability, and extra integrations.

- [LLM adapter](https://github.com/matiasmoram/prosperai-challenge/blob/main/src/prosper/llm.py): model access · Shared access layer for chat and judge models. · `src/prosper/llm.py`
- [Observability](https://github.com/matiasmoram/prosperai-challenge/tree/main/src/prosper/observability): redact timing · Timing and PII redaction utilities used across live and console paths. · `src/prosper/observability`
- [Integrations](https://github.com/matiasmoram/prosperai-challenge/tree/main/src/prosper/integrations): aux services · Additional side integrations and routing beyond the core booking path. · `src/prosper/integrations`

## Connections

- Bot runtime → Agent core: starts · Main process loads the bot orchestration layer.
- Agent core → Dispatcher: uses · Bot passes conversation control to the dispatcher.
- Dispatcher → Flows: advances · FSM states govern the clinical conversation flow.
- Dispatcher → Prompts: selects · State determines the active prompt frame.
- Dispatcher → Tools: permits · Only tools allowed by the current state are exposed.
- Dispatcher → Speculation: prefetches · Speculative logic supports early routing decisions.
- Dispatcher → LLM adapter: calls · Model reasoning is mediated by the shared LLM adapter.
- Tools → EHR client: invokes · Clinical actions are executed through the HTTP client.
- EHR client → EHR service: requests · Bot talks to the EHR only over HTTP.
- EHR service → Schemas: validates · API transport uses typed schemas.
- EHR service → Repository: delegates · Request handlers hand off to repository logic.
- Repository → Models: persists · Repository operates on SQLAlchemy models and constraints.
- Repository → SQLite DB: stores · Repository uses the SQLite session/engine layer.
- Agent core → Event bus: emits events · Live execution publishes redacted events for observers.
- Event bus → Console server: streams · Console subscribes to the event bus over SSE.
- Event bus → Audit log: records · The same events are appended to the audit log.
- Console server → Observability: redacts · Console presentation relies on shared redaction utilities.
- Agent core → Observability: measures · Timing and PII handling are shared across the live path.
- Eval runner → Sim runner: executes · Runner drives simulated and scripted scenarios.
- Eval runner → Judge: scores · Each eval combines state checks with an LLM judge.
- Eval runner → LLM adapter: uses · Evaluation depends on the shared model adapter.
- Human sim → Sim runner: feeds · Human-simulation behavior is plugged into simulated runs.
- Human sim → Dispatcher: stresses · Adversarial scenarios probe routing and safety boundaries.
- Integrations → Agent core: extends · Auxiliary integrations support side workflows around the core bot.
- Integrations → Observability: logs · Integration surfaces share redaction and timing conventions.
