XAUUSDAITradingBot/EchoHeirloom
MedFlow Command
An operations console for medical logistics — shipments, cold chain, stock, transport, reported bed capacity, scheduling, procurement, incidents and recalls. A supervisor agent owns the spoken call through the AssemblyAI Voice Agent API, delegates to eight specialist services, and either acts within a policy envelope or hands a human validator a brief.
This is not a diagnostic or treatment system. No agent diagnoses, prescribes, changes a clinical instruction, picks a treatment or claims to be a clinician. All demo data is synthetic.
Run it
Hugging Face Space (Docker SDK): push these files, then add Space secrets.
Without ASSEMBLYAI_API_KEY the Space still runs end to end on the deterministic mock adapter, labelled as a mock in the UI.
Local:
pip install -r requirements.txt
ASSEMBLYAI_API_KEY=... uvicorn app.main:app --port 7860
pytest -q tests.py # 64 testsDemo in 60 seconds
- Sign in as Validator.
- Overview → Use demo scenario → Send to supervisor. Inventory, Transport, Incident, Scheduling and Compliance report typed findings. Two temperature loggers on SHP-881 disagree, so the conflict gate fires.
- Validation inbox shows the brief: verified facts, proposal, alternatives, impact, risk score with reasons, agent disagreement, and what is still unknown. Request evidence, edit, approve or reject (a reason is mandatory to reject or edit).
- Ask it to "substitute a different insulin brand" — it refuses and routes to a human.
- Voice centre → Start call. Live captions, tool activity,
session.endon hang-up.
File tree
Dockerfile HF Space image (python:3.11-slim, non-root, healthcheck)
README.md this file
requirements.txt
tests.py 64 tests: acceptance, policy matrix, state machine, adversarial
app/config.py env-only secrets, feature flags, voice tuning, system prompt
app/schemas.py versioned protocol + workflow state machine
app/store.py SQLite, append-only event log, outbox, redaction, synthetic seed
app/policy.py autonomy policy engine, risk scoring, metrics
app/tools.py 12 allow-listed server-side tools
app/agents.py supervisor + 8 specialists, briefs, approvals
app/voice.py AssemblyAI adapter, mock adapter, outbound queue
app/main.py REST, SSE, voice WebSocket bridge, RBAC, CSP
static/index.html console shell
static/styles.css design system (dark + light, WCAG AA, reduced motion)
static/app.js 14 screens, topology, kanban, captions, waveformArchitecture
browser ──WS(JSON/base64 PCM)──► FastAPI /ws/voice ──WSS──► agents.assemblyai.com/v1/ws
│ tool.call → server-side execute → tool.result
▼
supervisor ─► AgentTask ─► 8 specialists ─► AgentFinding (+evidence, confidence)
▼
conflicts → RiskAssessment → policy engine → autonomous | ApprovalRequest
▼
append-only event log → SSE → console + audit timeline + redacted reportThe browser never sees the API key and never executes a tool. Audio is relayed through the server; the key travels only in the server's Authorization: Bearer upgrade header.
Workflow state machine
RECEIVED → TRIAGED → INVESTIGATING → PROPOSED → VALIDATION_REQUIRED → APPROVED → EXECUTING → VERIFIED → CLOSED, plus BLOCKED, REJECTED, CANCELLED, FAILED, ESCALATED. Transitions are declared in app/schemas.py; illegal moves raise. Every transition writes an event.
Autonomy policy matrix
Autonomous only if the category is eligible and every threshold passes.
Gates: confidence ≥ min_confidence_autonomous (0.75), zero unresolved conflicts, risk level low, evidence fresher than max_evidence_age_seconds (3600), amount under max_autonomous_amount (500), tool permitted, no prior failure, no compliance veto.
Risk score = weighted patient-safety, reversibility, PHI sensitivity, legal impact, conflicts, deadline urgency, prior failures, amount-vs-cap and inverse confidence, with a staleness penalty.
The 90% figure is measured, never targeted. Analytics shows actual autonomy rate on eligible work, approval latency, override rate, false-escalation rate, task success and tool failure. No code path reads the target when deciding. tests.py::test_autonomy_target_never_forces_approval pins this.
AssemblyAI integration
- Endpoint
wss://agents.assemblyai.com/v1/ws, REST underhttps://agents.assemblyai.com/v1. - Auth:
Authorization: Bearer <key>, server-side only. - First message
session.updatewith everything nested undersession; whenASSEMBLYAI_AGENT_IDis set, the payload binds the stored agent and sends nothing inline. - ASR
universal-3.5-pro-realtime; greeting, medical-logistics key terms, language list, interruption handling and turn detection configured. transcript.user.deltais cumulative — the UI replaces the partial caption rather than concatenating.transcript.agent.deltadrives live agent captions.- Tool schemas are flat:
{ type: "function", name, description, parameters }. tool.callarguments are read fromarguments, neverargs.- Tools execute on the server.
tool.resultis buffered untilreply.doneis the most recent event, then flushed. Failures carryis_error: true. session.endis sent when a call finishes so the resumable grace period stops billing.- Reconnect uses
session.resume; tool idempotency keys (call_id:tool_call_id) mean a resumed socket cannot double-execute an action. - Outbound validator calls check consent, quiet hours, retry limit and escalation cooldown. With no phone provider bound the request is queued and shown blocked — never faked as connected.
API contracts
Tools
get_inventory_status, check_lot_and_expiry, get_temperature_history, get_shipment_status, estimate_route, list_capacity_reports, propose_schedule, draft_purchase_request, create_incident, notify_validator, request_validator_callback, write_audit_event
Each declares a strict schema, data classification, role check, idempotency behaviour, timeout/retry, dry-run mode, approval requirement and an audit event, and has a deterministic mock path. See Integrations in the console for the live catalogue.
Threat model
No HIPAA claim. Security controls are not compliance. Encryption at rest, BAAs, retention enforcement and access reviews are organisational work outside this repository.
Architecture decision records
ADR-1 — Python/FastAPI on one container instead of a TypeScript monorepo. The brief specified Next.js + Prisma + Redis/BullMQ. The target is a Hugging Face Space running a single Docker image, and the brief's own delivery constraint is Python. Kept: strict schemas (Pydantic v2 instead of Zod), migrations-equivalent schema bootstrap, seeded demo tenant, typed protocol.
ADR-2 — SQLite (WAL) instead of PostgreSQL, asyncio instead of Redis/BullMQ. A Space has no sidecar services. The properties actually relied on — transactional writes, an append-only outbox, idempotency keys, a dead-letter queue — are implemented directly. app/store.py is the only file that needs to change to move to Postgres.
ADR-3 — Audio is relayed through the server, not via a browser temporary token. A browser token would be one fetch less, but tool execution and PHI redaction must stay server-side, and relaying keeps a single audit point for every call.
ADR-4 — Specialists are deterministic, not LLM-backed. Logistics findings must be reproducible and traceable to a tool result. Only the supervisor's spoken turn uses a model, and it cannot execute anything the policy engine has not cleared.
ADR-5 — SSE for live updates. One-way fan-out; simpler than a second WebSocket and it survives proxy buffering with an explicit keepalive.
Integration checklist
Accessibility
WCAG AA contrast in both themes; every status carries a glyph and a word as well as colour; full keyboard navigation with visible focus rings; aria-live on the event feed and captions; prefers-reduced-motion disables all animation, including the topology pulses and the waveform refresh rate.
