DevilNReality/Incident-Triage-Reinforcement-Learning
0
1---2title: Incident Triage & Alert Routing3emoji: ๐จ4colorFrom: indigo5colorTo: red6sdk: docker7app_port: 78608tags:9 - openenv10 - sre11 - devops12 - incident-management13 - alert-routing14 - triage15 - fastapi16 - streamlit17short_description: OpenEnv โ Train AI agents like a senior SRE18---19 20# ๐จ Incident Triage & Alert Routing โ OpenEnv21 22> **Meta ร Hugging Face AI Hackathon | Round 1** 23> An OpenEnv environment for training AI agents to triage production incidents like a senior SRE.24 25---26 27## Environment Description28 29This environment simulates the real-world job of a **Site Reliability Engineer (SRE)** who receives a flood of production alerts and must:30 311. Identify the **root cause** from a set of correlated alerts322. Assign the correct **severity level** (P1โP4)333. **Route** the incident to the correct on-call team (SRE, Database, Network, or App)344. *(Hard task only)* **Suppress noise alerts** โ flapping/self-resolving false positives35 36Every tech company faces alert fatigue. Reducing Mean Time To Detection (MTTD) by even 5 minutes has enormous operational value. This environment benchmarks how well an AI agent handles that pressure.37 38---39 40## Observation Space41 42At each step the agent receives an `AlertObservation`:43 44```python45class AlertObservation(BaseModel):46 alerts: List[Alert] # incoming monitoring alerts47 services_map: Dict[str, str] # service โ responsible team48 step: int # current step in the episode49 max_steps: int # maximum steps allowed50 task_id: str # "task_easy" | "task_medium" | "task_hard"51```52 53Each `Alert` contains:54 55```python56class Alert(BaseModel):57 alert_id: str # e.g. "alert-001"58 service: str # e.g. "postgres-primary"59 metric: str # e.g. "db_query_time_ms"60 value: float # current metric value61 threshold: float # value that triggered the alert62 duration_s: int # how long it has been firing (seconds)63```64 65### Services Map66 67| Service | Team |68|---|---|69| `api-server-03`, `api-server-07`, `redis-cache-01` | `sre` |70| `postgres-primary`, `postgres-replica` | `database` |71| `checkout-service`, `payment-service`, `auth-service`, `reporting-service` | `app` |72| `load-balancer-01`, `cdn-edge-02`, `dns-resolver-01` | `network` |73 74---75 76## Action Space77 78```python79class TriageAction(BaseModel):80 severity: Literal['P1', 'P2', 'P3', 'P4']81 team: Literal['sre', 'database', 'network', 'app']82 root_cause: str # one-sentence explanation, graded by keyword match83 suppressed: List[str] # alert_ids believed to be noise (task_hard only)84```85 86| Field | Description |87|---|---|88| `severity` | **P1** = Critical (revenue impact), **P2** = High (users affected), **P3** = Medium, **P4** = Low |89| `team` | On-call team to page: `sre`, `database`, `network`, or `app` |90| `root_cause` | Free-text root cause. Scored by keyword match against ground truth. |91| `suppressed` | Alert IDs the agent believes are noise. Only scored in `task_hard`. |92 93---94 95## Reward Function96 97### task_easy98| Component | Weight |99|---|---|100| Severity correct | 0.50 |101| Team correct | 0.50 |102 103### task_medium104| Component | Weight |105|---|---|106| Severity correct | 0.35 |107| Team correct | 0.35 |108| Root cause keywords | 0.30 |109 110### task_hard111| Component | Weight |112|---|---|113| Noise suppression (F1) | 0.20 |114| Severity correct | 0.25 |115| Team correct | 0.25 |116| Root cause keywords | 0.30 |117| Over-suppression penalty | โ0.20 per real alert wrongly suppressed |118 119---120 121## Task Descriptions122 123### ๐ข task_easy โ Single Alert, Obvious Root Cause124- 1 alert randomly chosen from 4 scenario variants125- Variants: CPU spike โ SRE ยท DB timeout โ Database ยท Network latency โ Network ยท 5xx errors โ App126- Max steps: 3127- **Expected score (frontier model):** 0.9โ1.0128 129### ๐ task_medium โ 3 Correlated Alerts, Identify Root Cause130- 3 correlated alerts from 4 scenario sets (Database overload, Network partition, App memory leak, CPU saturation)131- Agent must identify the single upstream root cause from downstream effects132- Max steps: 3133- **Expected score (frontier model):** 0.5โ0.75134 135### ๐ฅ task_hard โ 10โ15 Alerts, Suppress Noise & Escalate136- 6 real alerts (database outage root cause) + 5 noise alerts (short-duration, barely over threshold)137- Noise rule: `duration_s < 60` AND `value < threshold ร 1.10`138- Agent must suppress noise alerts and correctly identify the P1 database root cause139- Max steps: 5140- **Expected score (frontier model):** 0.2โ0.45141 142---143 144## API Reference145 146All endpoints are available on port **7860** (via nginx reverse proxy).147 148| Method | Path | Description |149|---|---|---|150| `GET` | `/health` | Health check โ returns `{"status": "ok"}` |151| `GET` | `/tasks` | List all tasks with metadata |152| `POST` | `/reset` | Start a new episode. Body: `{"task_id": "task_easy", "seed": null}` |153| `POST` | `/step` | Submit a `TriageAction`. Returns observation, reward, done, info. |154| `GET` | `/state` | Full environment state including ground truth team/severity |155 156### Example: Full Episode157 158```python159import requests160 161BASE = "https://<your-username>-incident-triage-env.hf.space"162 163# 1. Reset164obs = requests.post(f"{BASE}/reset", json={"task_id": "task_medium"}).json()165 166# 2. Step167action = {168 "severity": "P1",169 "team": "database",170 "root_cause": "Database overload causing query timeouts and downstream 5xx errors",171 "suppressed": []172}173result = requests.post(f"{BASE}/step", json=action).json()174print(result["reward"], result["done"], result["info"])175```176 177---178 179## ๐ Setup & Deployment180 181### Option A โ Hugging Face Spaces (recommended)182 183#### Prerequisites184- Git installed185- A Hugging Face account with a token from https://huggingface.co/settings/tokens186 187#### Step 1 โ Install the HF CLI & login188 189```bash190pip install huggingface_hub191huggingface-cli login192```193 194#### Step 2 โ Create a new Space195 196Go to https://huggingface.co/new-space and set:197- **Space name:** `incident-triage-env`198- **SDK:** Docker199- **Visibility:** Public200 201#### Step 3 โ Clone and push202 203```bash204git clone https://huggingface.co/spaces/<your-username>/incident-triage-env205cd incident-triage-env206 207# Copy all project files here, then:208git add .209git commit -m "deploy: Incident Triage OpenEnv"210git push211```212 213HF Spaces detects the Dockerfile and builds automatically (~3โ5 min). Monitor progress in the **Logs** tab.214 215#### Step 4 โ Add secrets (for LLM agent mode)216 217In your Space โ **Settings** โ **Repository secrets**:218 219| Secret | Value |220|---|---|221| `HF_TOKEN` | Your HF token (`hf_...`) |222| `API_BASE_URL` | `https://router.huggingface.co/v1` |223| `MODEL_NAME` | `meta-llama/Llama-3.3-70B-Instruct` |224 225> The Streamlit UI and rule-based agent work without secrets. Secrets are only needed for LLM Agent mode.226 227---228 229### Option B โ Local Development230 231```bash232# 1. Install dependencies233pip install -r requirements.txt234 235# 2. Start FastAPI backend (terminal 1)236cd backend237uvicorn server:app --reload --port 8000238 239# 3. Start Streamlit UI (terminal 2, from project root)240BACKEND_URL=http://localhost:8000 streamlit run frontend/app.py241# Opens at http://localhost:8501242 243# 4. (Optional) Run the LLM baseline agent244cp .env.example .env # fill in your API keys245source .env246python inference.py247```248 249### Option C โ Docker locally250 251```bash252docker build -t incident-triage-env .253docker run -p 7860:7860 \254 -e HF_TOKEN=hf_... \255 -e API_BASE_URL=https://router.huggingface.co/v1 \256 -e MODEL_NAME=meta-llama/Llama-3.3-70B-Instruct \257 incident-triage-env258 259# UI + API both at http://localhost:7860260```261 262---263 264## Architecture265 266```267Browser / OpenEnv Checker268 โ269 โผ port 7860 (public)270 nginx271 โฑ โฒ272 โผ โผ273FastAPI Streamlit274 :8000 :8501275(API calls) (Web UI)276```277 278nginx routes:279- `POST /reset`, `GET /health`, `/tasks`, `/step`, `/state` โ **FastAPI** (OpenEnv checker)280- `/` and all other traffic โ **Streamlit UI** (browser)281 282---283 284## Project Structure285 286```287incident-triage-env/288โโโ Dockerfile โ Builds & runs nginx + FastAPI + Streamlit289โโโ nginx.conf โ Reverse proxy: port 7860 โ FastAPI:8000 / Streamlit:8501290โโโ start.sh โ Startup script launching all three processes291โโโ requirements.txt โ Python dependencies (latest versions)292โโโ openenv.yaml โ OpenEnv spec: tasks, action/observation spaces, reward293โโโ pyproject.toml โ Package config; server entry point: server.app:main294โโโ .env.example โ Template for local env vars295โโโ .dockerignore โ Excludes __pycache__, *.pyc, .git, uv.lock etc.296โโโ inference.py โ LLM baseline agent (uses OpenAI client + HF router)297โโโ backend/298โ โโโ models.py โ Pydantic v2: Alert, AlertObservation, TriageAction, TriageReward299โ โโโ tasks.py โ All task definitions + graders (easy / medium / hard)300โ โโโ environment.py โ OpenEnv contract: reset() step() state()301โ โโโ server.py โ FastAPI app with /reset /step /state /health /tasks302โโโ server/303โ โโโ app.py โ Entry point wrapper for multi-mode deployment (server.app:main)304โโโ frontend/305 โโโ app.py โ Streamlit UI: alert cards, routing table, score chart306```307 308---309 310## Baseline Scores311 312| Task | Score | Notes |313|---|---|---|314| `task_easy` | ~0.95 | Near-perfect on single alert |315| `task_medium` | ~0.63 | Good severity+team, partial root cause keyword match |316| `task_hard` | ~0.31 | Noise suppression is the primary challenge |317 318Scores from `meta-llama/Llama-3.3-70B-Instruct` via HF inference router.319 320---321 322*Built for the Meta ร Hugging Face AI Hackathon, Round 1.*323 