modules/agents.mdEngineering, modules~2 min read

Module: agents

Part of the Travi AI Agent monolith (app/modules/agents/). Read 00-overview.md §3 (hard rules) before changing anything here.

Purpose The six bounded agents, their policy envelopes, evidence records, kill switches, and exception routing. Agents gather evidence; they never set state.
Owns (data) agent_action, policy envelopes (versioned)
Public surface goal queue (internal), /admin/kill-switches enforcement point
Depends on episode (evidence → engine), notification, ehr_adapter, Twilio voice
Requirements owned AUT-001/006/009
Constraining ADRs ADR-011 (routing targets)
Key references modules/episode.md (who actually moves state)

12. Agentic Execution Layer

12.1 Orchestration Loop (deterministic core)

  1. Workflow engine (episode module) emits a goal (e.g., verify_dispense(plan_item)) to the agent queue with the current policy envelope version.
  2. Agent plans with LLM assist (optional) but may only call tools on its allowlist; every call → agent_action row (params redacted, result, evidence).
  3. Agent returns structured evidence, never a state: e.g., {dispense_status:"picked_up", source:"pharmacy_phone", confidence:"confirmed"}.
  4. Workflow engine validates evidence against deterministic rules and executes the §7.1 transition (five-element contract).
  5. Retry ladder per envelope; exhaustion → L1 exception route (§12.5); kill switches checked before every tool call (cached ≤10 s).

12.2 Agent Catalog & Envelopes

Agent Tool Allowlist Max Retries Hard Prohibitions
Engagement notification.send, channel.select, schedule.reminder 3/task/day No PHI in payloads; no promises of clinician monitoring (CLN-008 language lint).
Appointment ehr.search_slots, ehr.book(with patient authorization token), patient.present_options 3 Never book/cancel without explicit patient authorization event; never invent availability (APT rules).
Med Access pharmacy.call (Twilio flow), pharmacy.status_form, patient.ask_structured 2/barrier No substitutions, dose advice, or clinical guidance, script templates only.
Records ehr.list_documents, ehr.fetch_binary 5 Approved document types only; read-only.
Brief facts.read(published), brief.render, notify.clinician_link 2 Assembles published facts only; cannot trigger confirmations.
Outcome adt.match, hie.lookup, claims.ingest 5 Read/match only; flags completeness, never edits episodes.

12.3 Policy Envelope (stored, versioned, enforced in code)

{ "agent": "med_access", "version": 4,
 "tools": ["pharmacy.call","pharmacy.status_form","patient.ask_structured"],
 "max_retries": 2, "retry_backoff_hours": [4, 24],
 "requires_patient_authorization": false,
 "clinical_boundaries": ["no_substitution","no_dose_advice"],
 "cost_caps": {"tokens_per_run": 20000, "voice_minutes_per_run": 6},
 "kill_scopes": ["global","tenant","cohort","agent","tool","integration"],
 "logging": "full_evidence", "pii_redaction": "params_hashed" }

12.4 Kill Switches (AUT-009)

Six scopes resolve most-specific-wins; state lives in tenant_config with Redis cache TTL 10 s; the admin endpoint requires reason + role and takes effect before the next tool call. Read-only surfaces (Today, brief) are never disabled by agent kills.

12.5 Exception Routing (PRD §8.1)

Level Trigger Terminal Route (MVP)
L1 Retry exhaustion on operational tasks (unreachable, scheduling fail, stock-out) Caregiver prompt (if consented) → blocked persists → weekly exception report; hospital queue only if ops.tier=2 (AUT-006 keeps routine ops out of hospital queues).
L2 Conflicting sources; transcript vs order; uncertain material fact pending_clinical_decision → previsit brief open-questions; if no appointment within window → configured transition-team endpoint digest.
L3 Severe symptom report / explicit help request Immediate approved emergency instructions (911/ED language, versioned per EDU-007) + alert to configured clinical endpoint; never an improvised agent reply.