Spaces:
Sleeping
title: TriageFlow
emoji: π₯
colorFrom: red
colorTo: blue
sdk: docker
app_port: 8000
tags:
- openenv
pinned: false
TriageFlow: AI-Assisted Patient Intake Prioritization
Motivation
When emergency departments are overwhelmed, the initial intake assessment β deciding who needs immediate attention and who can safely wait β becomes a critical cognitive load for clinical staff.
TriageFlow simulates the intake desk of a busy hospital emergency department. Patients arrive one at a time. For each patient, the AI agent must:
- Classify the patient's urgency (IMMEDIATE / URGENT / LESS_URGENT / NON_URGENT / ESCALATE)
- Output the full reordered priority queue β the correct ordering of all patients seen so far
This dual-output design tests both clinical judgment (is this patient critical?) and queue management (where does this patient rank against everyone else?).
Why this matters: Training AI agents to assist with intake prioritization β flagging obvious high-acuity cases and managing queue state β could reduce cognitive load on clinical staff. This environment provides a safe, reproducible benchmark for evaluating such agents.
What the agent simulates: The role of a triage nurse or intake coordinator, NOT a doctor. This is an operational, administrative, safety-critical workflow β not diagnosis.
Environment Overview
Episode Lifecycle
reset(task_name) β first patient presented with empty queue
β
agent observes incoming patient + current queue state
β
agent outputs: classification + full reordered priority queue
β
step(action) β reward computed (classification accuracy + queue correctness + escalation judgement)
β
next patient arrives β repeat
β
all patients seen β episode ends
β
grader scores full trajectory β score in [0.0, 1.0]
What the Agent Can Do
- Classify patients: IMMEDIATE, URGENT, LESS_URGENT, NON_URGENT
- Escalate patients with missing critical data (sends to human, removes from queue)
- Reorder the priority queue after each classification
What the Agent Must Never Do
- Issue a medical diagnosis
- Prescribe or recommend treatments
- Make clinical judgments about disease causation
Observation Space
| Field | Type | Description |
|---|---|---|
incoming_patient |
dict |
The patient who just arrived (symptoms, vitals, age, complaint, history) |
current_queue |
List[str] |
Patient IDs in current priority order (agent's queue so far) |
step_number |
int |
Current step in the episode |
total_expected_patients |
int |
Total patients the agent will see |
previous_feedback |
str |
Feedback on last classification |
task_name |
str |
Name of the active task |
done |
bool |
Whether the episode has ended |
reward |
float |
Reward for the last action |
Hidden from agent (grader-only): Per-step answer keys, full agent trajectory, internal scoring components.
Action Space
Each step, the agent outputs a single JSON object:
{
"classification": "immediate|urgent|less_urgent|non_urgent|escalate",
"reordered_queue": ["P001", "P003", "P002"]
}
| Field | Type | Description |
|---|---|---|
classification |
str |
Priority level for the incoming patient, or "escalate" if data is missing |
reordered_queue |
List[str] |
Full queue of all non-escalated patients in priority order |
Rules:
- IMMEDIATE patients go first, then URGENT, LESS_URGENT, NON_URGENT
- Escalated patients are removed from the queue entirely
- The queue should contain all patients classified so far (excluding escalated ones)
Reward Function
Three scoring components per step, weighted:
| Component | Weight | What It Measures |
|---|---|---|
| Classification Accuracy | 50% | Did the agent assign the correct priority label? |
| Queue Ordering | 30% | Does the agent's queue match the ideal queue? (position-weighted) |
| Escalation Judgment | 20% | Did the agent correctly identify missing data? |
Classification Penalties (Asymmetric)
| Mistake | Severity |
|---|---|
| Correct classification | Full credit |
| Off by one level (e.g., URGENT instead of IMMEDIATE) | Small penalty |
| Off by two levels (e.g., LESS_URGENT instead of IMMEDIATE) | Heavy penalty |
| IMMEDIATE classified as NON_URGENT | Maximum penalty (patient could die) |
| NON_URGENT classified as IMMEDIATE | Mild penalty (wastes resources but safe) |
| Correctly escalating incomplete patient | Full credit |
| Failing to escalate missing data (guessing) | Heavy penalty |
| Escalating complete patient unnecessarily | Moderate penalty |
Philosophy: Under-triaging dangerous patients is punished far harder than over-triaging safe patients.
Tasks
Task 1: Basic Triage (Easy) β 3 patients
- Scenario: 3 patients with complete records and clearly distinct urgency levels
- Patients: Chest pain with cardiac history (IMMEDIATE), sprained ankle (NON_URGENT), persistent fever with cough (URGENT)
- Challenge: Classify correctly and build the priority queue β no escalations needed
- Max Steps: 10
Task 2: Incomplete Records Triage (Medium) β 5 patients (3 + 1 escalation + 1 re-entry)
- Scenario: One patient arrives with missing vitals β must be escalated. They return later with complete data as a new patient.
- Challenge: Escalation judgment + correct re-classification after data completion
- Max Steps: 15
Task 3: Mass Casualty Triage (Hard) β 10 patients (8 + 1 escalation + 1 re-entry)
- Scenario: Building collapse. Multiple patients at similar urgency levels. Drug interactions (warfarin + head injury). Missing data requiring escalation.
- Challenge: Ranking 8+ patients correctly, escalation judgment under pressure, intra-priority ordering
- Max Steps: 20
Grading Formula
final_score = (classification_accuracy Γ 0.5) + (queue_ordering Γ 0.3) + (escalation_judgment Γ 0.2)
All scores are clipped to [0.0, 1.0]. Deterministic: same state always produces the same score.
Setup
Prerequisites
- Python 3.10+
- Docker (for containerized deployment)
Installation
git clone <repo-url>
cd triage-flow
pip install -r requirements.txt
Running Locally
Start the server:
ENABLE_WEB_INTERFACE=true uvicorn server.app:app --host 0.0.0.0 --port 8000
Run the baseline inference:
# Set environment variables (Linux/Mac)
export API_BASE_URL="https://router.huggingface.co/v1"
export MODEL_NAME="meta-llama/Llama-3.1-8B-Instruct"
export HF_TOKEN="your-hf-token"
# Windows CMD
set API_BASE_URL=https://router.huggingface.co/v1
set MODEL_NAME=meta-llama/Llama-3.1-8B-Instruct
set HF_TOKEN=your-hf-token
# Run inference
python inference.py
Validate:
openenv validate
Docker
# Build
docker build -t triage-flow .
# Run
docker run -p 8000:8000 triage-flow
# Test
curl -X POST http://localhost:8000/reset -H "Content-Type: application/json" -d '{}'
Baseline Scores (Llama 3.1 8B Instruct)
| Task | Score | Notes |
|---|---|---|
| basic-triage | 0.85 | Correctly identifies IMMEDIATE chest pain case |
| incomplete-records-triage | 0.76 | Successfully escalates patient with missing vitals |
| mass-casualty-triage | 0.86 | Handles escalation + 8-patient queue ordering |
Limitations
- Patient cases are synthetic and simplified β real triage involves much more nuanced assessment
- The environment does not model patient deterioration over time
- Vitals are static snapshots, not continuous monitoring data
- The queue ordering is evaluated against a single "ideal" ordering β real triage may have multiple valid orderings
- Graders focus on priority accuracy and queue correctness, not clinical reasoning quality
- The step budget abstraction does not capture real-time constraints
Repository Structure
triage-flow/
βββ inference.py # Baseline inference script (project root)
βββ models.py # Pydantic models: TriageAction, TriageObservation, TriageState
βββ openenv.yaml # OpenEnv spec metadata
βββ Dockerfile # Container build
βββ README.md # This file
βββ requirements.txt # Python dependencies
βββ pyproject.toml # Package config
βββ client.py # OpenEnv client for remote access
βββ triage_flow/ # Main environment package
β βββ __init__.py
β βββ environment.py # Core env: reset(), step(), state
β βββ tasks.py # Task definitions with per-step answer keys
β βββ graders.py # Deterministic 3-component grading
β βββ reward.py # Per-step reward (classification + queue + escalation)
βββ server/
β βββ __init__.py
β βββ app.py # FastAPI server (OpenEnv create_app)
β βββ ui.py # Custom Gradio clinical dashboard
β βββ triage_flow_environment.py # Server-side environment re-export
βββ .github/
βββ workflows/
βββ sync_to_hub.yml # GitHub Actions β HF Spaces sync
License
MIT
Built by Team Squirrel for OpenEnv Round 1 Hackathon.