Update README.md
Browse files
README.md
CHANGED
|
@@ -1,67 +1,582 @@
|
|
| 1 |
-
---
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
-
|
| 11 |
-
-
|
| 12 |
-
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: ARIA DevOps Incident Response
|
| 3 |
+
emoji: π¨
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: red
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: true
|
| 8 |
+
license: apache-2.0
|
| 9 |
+
tags:
|
| 10 |
+
- openenv
|
| 11 |
+
- reinforcement-learning
|
| 12 |
+
- devops
|
| 13 |
+
- incident-response
|
| 14 |
+
- rl-environment
|
| 15 |
+
- multi-agent
|
| 16 |
+
- llm-agent
|
| 17 |
+
- grpo
|
| 18 |
+
- curriculum-learning
|
| 19 |
+
- huggingface
|
| 20 |
+
- pytorch
|
| 21 |
+
- meta
|
| 22 |
+
short_description: RL environment for DevOps incident response agents
|
| 23 |
+
---
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
# ARIA β DevOps Incident Response
|
| 27 |
+
### *The first OpenEnv RL environment for production incident response*
|
| 28 |
+
|
| 29 |
+
[](https://colab.research.google.com/github/Twilight-13/devops-incident-response/blob/main/train_grpo.ipynb)
|
| 30 |
+
[](https://huggingface.co/spaces/Arijit-07/devops-incident-response)
|
| 31 |
+
[](https://huggingface.co/Arijit-07/aria-devops-llama3b)
|
| 32 |
+
[](LICENSE)
|
| 33 |
+
|
| 34 |
+
> **ARIA** β Adaptive Reward & Incident Architecture
|
| 35 |
+
> Built for the Meta Γ PyTorch Γ HuggingFace OpenEnv Hackathon Finals | Bangalore, April 2026
|
| 36 |
+
|
| 37 |
+
---
|
| 38 |
+
|
| 39 |
+
## π Quick Links for Judges
|
| 40 |
+
|
| 41 |
+
| Resource | Link |
|
| 42 |
+
|---|---|
|
| 43 |
+
| **Live Environment** | https://arijit-07-devops-incident-response.hf.space |
|
| 44 |
+
| **Interactive API (Swagger)** | https://arijit-07-devops-incident-response.hf.space/docs |
|
| 45 |
+
| **Trained Model (Llama-3B LoRA)** | https://huggingface.co/Arijit-07/aria-devops-llama3b |
|
| 46 |
+
| **Training Curve** | https://huggingface.co/Arijit-07/aria-devops-llama3b/resolve/main/training_curve.png |
|
| 47 |
+
| **HuggingFace Blog** | https://huggingface.co/blog/Arijit-07/aria-devops-incident-response |
|
| 48 |
+
| **GitHub** | https://github.com/Twilight-13/devops-incident-response |
|
| 49 |
+
| **Validate (self-test)** | https://arijit-07-devops-incident-response.hf.space/validate |
|
| 50 |
+
|
| 51 |
+
---
|
| 52 |
+
|
| 53 |
+
## β‘ Run a Complete Episode Right Now
|
| 54 |
+
|
| 55 |
+
```bash
|
| 56 |
+
# 1. Start an easy incident
|
| 57 |
+
curl -X POST https://arijit-07-devops-incident-response.hf.space/reset \
|
| 58 |
+
-H "Content-Type: application/json" \
|
| 59 |
+
-d '{"task_id": "easy", "seed": 42}'
|
| 60 |
+
|
| 61 |
+
# 2. Read logs on the failing service (reward: +0.15)
|
| 62 |
+
curl -X POST https://arijit-07-devops-incident-response.hf.space/step \
|
| 63 |
+
-H "Content-Type: application/json" \
|
| 64 |
+
-d '{"action_type": "read_logs", "service": "payment-service"}'
|
| 65 |
+
|
| 66 |
+
# 3. Diagnose the root cause (reward: +0.30)
|
| 67 |
+
curl -X POST https://arijit-07-devops-incident-response.hf.space/step \
|
| 68 |
+
-H "Content-Type: application/json" \
|
| 69 |
+
-d '{"action_type": "diagnose", "root_cause": "memory leak in payment-service"}'
|
| 70 |
+
|
| 71 |
+
# 4. Fix it (reward: +0.40)
|
| 72 |
+
curl -X POST https://arijit-07-devops-incident-response.hf.space/step \
|
| 73 |
+
-H "Content-Type: application/json" \
|
| 74 |
+
-d '{"action_type": "restart_service", "service": "payment-service"}'
|
| 75 |
+
|
| 76 |
+
# 5. See the final score
|
| 77 |
+
curl https://arijit-07-devops-incident-response.hf.space/state
|
| 78 |
+
|
| 79 |
+
# 6. Validate all 7 tasks pass
|
| 80 |
+
curl https://arijit-07-devops-incident-response.hf.space/validate
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
```python
|
| 84 |
+
# Or install and use the Python client
|
| 85 |
+
pip install git+https://github.com/Twilight-13/devops-incident-response.git
|
| 86 |
+
|
| 87 |
+
from devops_incident_response import DevOpsIncidentEnv, Action, ActionType
|
| 88 |
+
|
| 89 |
+
env = DevOpsIncidentEnv(task_id="easy", seed=42)
|
| 90 |
+
obs = env.reset()
|
| 91 |
+
result = env.step(Action(action_type=ActionType.READ_LOGS, service="payment-service"))
|
| 92 |
+
print(f"Reward: {result.reward}") # 0.15
|
| 93 |
+
```
|
| 94 |
+
|
| 95 |
+
---
|
| 96 |
+
|
| 97 |
+
## π― The Problem This Solves
|
| 98 |
+
|
| 99 |
+
Every software company running microservices faces the same brutal reality: **production incidents are expensive, unpredictable, and happen at 3am.**
|
| 100 |
+
|
| 101 |
+
A single SEV-1 incident β a payment service crashing, a data corruption silently corrupting prices, a DDoS botnet overwhelming your login endpoint β can cost millions and require hours of expert engineer time to diagnose and fix. On-call rotations are stressful. Tier-2 incidents that follow recognizable patterns are handled by engineers when they could, in principle, be handled by an AI agent.
|
| 102 |
+
|
| 103 |
+
**Yet no RL benchmark exists for this domain.**
|
| 104 |
+
|
| 105 |
+
SWE-bench tests code generation. WebArena tests web navigation. AgentBench tests general tool use. None of them model **operational intelligence** β the ability to reason under uncertainty about live production systems, gather information strategically, and take precise actions where wrong choices cause additional damage.
|
| 106 |
+
|
| 107 |
+
ARIA fills that gap.
|
| 108 |
+
|
| 109 |
+
---
|
| 110 |
+
|
| 111 |
+
## ποΈ Environment Architecture
|
| 112 |
+
|
| 113 |
+
ARIA simulates a production microservices e-commerce platform. Agents interact with the environment through a standard OpenEnv API: `reset()`, `step()`, `state()`.
|
| 114 |
+
|
| 115 |
+
### What the Agent Observes
|
| 116 |
+
|
| 117 |
+
Each step returns a structured `Observation` object:
|
| 118 |
+
|
| 119 |
+
```
|
| 120 |
+
Observation
|
| 121 |
+
βββ step, max_steps, task_id, task_description
|
| 122 |
+
βββ services: List[ServiceStatus]
|
| 123 |
+
β βββ name, status (healthy/degraded/down/unknown)
|
| 124 |
+
β βββ cpu_percent, memory_percent
|
| 125 |
+
β βββ error_rate, latency_p99_ms
|
| 126 |
+
β βββ replicas_running, replicas_desired
|
| 127 |
+
β βββ current_version, last_deployed
|
| 128 |
+
β βββ sla_breach, minutes_degraded β SLA tracking per step
|
| 129 |
+
βββ active_alerts: List[Alert] β may include red herrings
|
| 130 |
+
βββ recent_logs: Dict[str, List[str]] β PARTIAL: only 2 lines shown
|
| 131 |
+
βββ service_dependencies: List[ServiceDependency] β call topology
|
| 132 |
+
βββ evidence_log: List[EvidenceEntry] β accumulates across steps
|
| 133 |
+
βββ sla_status: Dict[str, str] β ok/warning/breached
|
| 134 |
+
βββ available_runbooks: List[str]
|
| 135 |
+
```
|
| 136 |
+
|
| 137 |
+
**Key design: Partial Log Observability**
|
| 138 |
+
|
| 139 |
+
The agent only sees 2 log lines per service upfront. Full history requires calling `read_logs` explicitly. This models real observability tools (Datadog, Kibana) where engineers run queries β agents must develop a search strategy, not just read everything.
|
| 140 |
+
|
| 141 |
+
### The Services
|
| 142 |
+
|
| 143 |
+
| Service | Stack | Role |
|
| 144 |
+
|---|---|---|
|
| 145 |
+
| `api-gateway` | Go | Routes external requests |
|
| 146 |
+
| `payment-service` | Java (Spring) | Processes payments |
|
| 147 |
+
| `order-service` | Python | Creates and tracks orders |
|
| 148 |
+
| `inventory-service` | Java | Manages product stock |
|
| 149 |
+
| `user-service` | Node.js | Auth and profiles |
|
| 150 |
+
| `notification-service` | Python | Email and push alerts |
|
| 151 |
+
| `data-pipeline-service` | Python | Writes catalog data |
|
| 152 |
+
| `product-catalog-service` | Go | Stores and serves product data |
|
| 153 |
+
| `price-validation-service` | Python | Validates prices |
|
| 154 |
+
| `analytics-service` | Python | Aggregates business metrics |
|
| 155 |
+
| `ml-inference-service` | Python | Serves recommendation models |
|
| 156 |
+
| `log-aggregator` | Go | Collects and stores logs |
|
| 157 |
+
|
| 158 |
+
### Service Dependency Map
|
| 159 |
+
|
| 160 |
+
Every observation includes the call topology β agents can trace cascades:
|
| 161 |
+
|
| 162 |
+
```
|
| 163 |
+
api-gateway β order-service β inventory-service
|
| 164 |
+
api-gateway β payment-service
|
| 165 |
+
order-service β notification-service
|
| 166 |
+
data-pipeline-service β product-catalog-service β price-validation-service
|
| 167 |
+
```
|
| 168 |
+
|
| 169 |
+
---
|
| 170 |
+
|
| 171 |
+
## π¬ The 7 Tasks
|
| 172 |
+
|
| 173 |
+
### Task 1 β Single Service OOM (`easy`)
|
| 174 |
+
**Max steps: 15 | Expected strong LLM: 0.85β1.00 | Random agent: 0.05**
|
| 175 |
+
|
| 176 |
+
One service crash-loops with an OutOfMemoryError. The affected service rotates by seed across payment-service, order-service, and user-service β with different log formats (Java heap errors, Python memory errors, Node.js heap dumps). A secondary circuit-breaker alert fires on api-gateway as a visible symptom.
|
| 177 |
+
|
| 178 |
+
**What makes it interesting:** The agent must identify the ROOT cause service (the one running out of memory) not the SYMPTOM services (everything downstream that's erroring because the root is down).
|
| 179 |
+
|
| 180 |
+
**Optimal sequence:** `read_logs` β `read_metrics` β `diagnose` β `restart_service`
|
| 181 |
+
**Reward breakdown:** +0.10 read_logs, +0.10 read_metrics, +0.30 diagnose, +0.40 restart = **0.99 with efficiency bonus**
|
| 182 |
+
|
| 183 |
+
---
|
| 184 |
+
|
| 185 |
+
### Task 2 β Cascading Failure (`medium`)
|
| 186 |
+
**Max steps: 20 | Expected strong LLM: 0.55β0.75 | Random agent: 0.03**
|
| 187 |
+
|
| 188 |
+
A bad deployment of `inventory-service` causes connection pool exhaustion, cascading timeouts to `order-service` and elevated error rates on `api-gateway`. **Red herring:** a `notification-service` HIGH CPU alert fires (scheduled batch job β completely unrelated).
|
| 189 |
+
|
| 190 |
+
**What makes it interesting:** The agent must follow the dependency chain backwards. Three services are visibly failing, but only one is the root cause. Touching the wrong service gives -0.15 collateral damage penalty.
|
| 191 |
+
|
| 192 |
+
**Optimal sequence:** Investigate `api-gateway` β trace to `order-service` β trace to `inventory-service` β `rollback`
|
| 193 |
+
**Reward breakdown:** +0.20 trace cascade, +0.05 runbook, +0.25 diagnose, +0.35 rollback = **0.92**
|
| 194 |
+
|
| 195 |
+
---
|
| 196 |
+
|
| 197 |
+
### Task 3 β Silent Data Corruption (`hard`)
|
| 198 |
+
**Max steps: 25 | Expected strong LLM: 0.30β0.50 | Random agent: 0.01**
|
| 199 |
+
|
| 200 |
+
**All services show green.** Zero error rates. Normal latency. No standard alerts. The signal is buried in:
|
| 201 |
+
- `price-validation-service` WARN logs: 15% price mismatch rate (baseline: 0.2%)
|
| 202 |
+
- `analytics-service` anomaly: avg order value $847 vs $89 historical baseline
|
| 203 |
+
|
| 204 |
+
Three noise alerts distract: TLS renewal, analytics backlog, replica lag.
|
| 205 |
+
|
| 206 |
+
**What makes it interesting:** This requires qualitatively different reasoning β ignoring green health checks, correlating subtle business metric anomalies, and understanding that a data pipeline deployment 2 minutes ago is the causal explanation.
|
| 207 |
+
|
| 208 |
+
**Full credit requires BOTH:** `rollback(data-pipeline-service)` AND `alert_oncall` (data audit needed)
|
| 209 |
+
**Reward breakdown:** +0.15 subtle signals, +0.10 pipeline metrics, +0.05 runbook, +0.20 diagnose, +0.25 rollback, +0.15 alert_oncall = **0.87**
|
| 210 |
+
|
| 211 |
+
---
|
| 212 |
+
|
| 213 |
+
### Task 4 β Dual Simultaneous Failure (`bonus`)
|
| 214 |
+
**Max steps: 25 | Expected strong LLM: 0.35β0.55 | Random agent: 0.01**
|
| 215 |
+
|
| 216 |
+
Two completely independent failures at once:
|
| 217 |
+
1. `log-aggregator` disk 100% full β dropping 48k log messages/min
|
| 218 |
+
2. `ml-inference-service` stuck in model checksum reload loop β CPU 99%+
|
| 219 |
+
|
| 220 |
+
**What makes it interesting:** Neither failure is related to the other. Solving one doesn't help the other. The agent must decompose and fix independently. This tests whether agents can maintain multiple hypotheses simultaneously.
|
| 221 |
+
|
| 222 |
+
**Full credit requires BOTH:** `alert_oncall` (disk cleanup) AND `rollback/restart(ml-inference-service)`
|
| 223 |
+
**Optimal score: ~0.77**
|
| 224 |
+
|
| 225 |
+
---
|
| 226 |
+
|
| 227 |
+
### Task 5 β Security Incident: DDoS (`security`)
|
| 228 |
+
**Max steps: 20 | Expected strong LLM: 0.40β0.60 | Random agent: 0.01**
|
| 229 |
+
|
| 230 |
+
A botnet is targeting the login endpoint with 12,000 req/s from the `185.220.x.x` IP range. Standard rate limiting is ineffective (distributed attack). The access logs show 1,847+ failed login attempts per 60 seconds from that range.
|
| 231 |
+
|
| 232 |
+
**New action: `block_ip_range`** β models real network-level DDoS mitigation.
|
| 233 |
+
**Wrong actions:** Restarting api-gateway won't help. Scaling up won't help. Must block at network level + escalate to security team.
|
| 234 |
+
|
| 235 |
+
**Full credit:** `block_ip_range("185.220.0.0/16")` AND `alert_oncall`
|
| 236 |
+
**Optimal score: ~0.80**
|
| 237 |
+
|
| 238 |
+
---
|
| 239 |
+
|
| 240 |
+
### Task 6 β Database Degradation (`database`)
|
| 241 |
+
**Max steps: 20 | Expected strong LLM: 0.45β0.65 | Random agent: 0.01**
|
| 242 |
+
|
| 243 |
+
A schema migration added a `user_segment` column to the `orders` table 15 minutes ago β without an index. Every query is now doing a full sequential table scan. DB CPU is spiking. The slow query log shows `seq_scan on orders (847ms)`.
|
| 244 |
+
|
| 245 |
+
**New action: `create_index`** β models real DBA response to missing indexes.
|
| 246 |
+
**Alternative fix:** Rolling back the migration is also accepted for full credit.
|
| 247 |
+
|
| 248 |
+
**Optimal score: ~0.80**
|
| 249 |
+
|
| 250 |
+
---
|
| 251 |
+
|
| 252 |
+
### Task 7 β Multi-Region Failover (`failover`)
|
| 253 |
+
**Max steps: 25 | Expected strong LLM: 0.35β0.55 | Random agent: 0.01**
|
| 254 |
+
|
| 255 |
+
A network partition affects `us-east-1`. Four services support automatic failover to `us-west-2` and should be switched. Two services MUST NOT be failed over:
|
| 256 |
+
- `payment-service` β PCI-DSS compliance requires human approval
|
| 257 |
+
- `postgres-primary` β replication lag risk causes data loss
|
| 258 |
+
|
| 259 |
+
**New action: `failover`** β with `target_region` parameter.
|
| 260 |
+
**Heavy penalty: -0.25 per wrong service.** Failing over payment or postgres is catastrophic.
|
| 261 |
+
|
| 262 |
+
**The runbook explicitly lists which services are safe** β reading it first is rewarded.
|
| 263 |
+
**Optimal score: ~0.70**
|
| 264 |
+
|
| 265 |
+
---
|
| 266 |
+
|
| 267 |
+
### Task 8 β Generated Incident (`generated`)
|
| 268 |
+
**Max steps: 20 | Variable difficulty | Seed-deterministic**
|
| 269 |
+
|
| 270 |
+
The Incident Generator creates procedural incidents from any integer seed (0β99,999). Same seed always produces the same incident. Different seeds produce unique combinations of:
|
| 271 |
+
- 6 failure modes Γ 8 services Γ 3 severity levels Γ 0β3 noise alerts
|
| 272 |
+
|
| 273 |
+
```bash
|
| 274 |
+
# Preview any incident before running it
|
| 275 |
+
curl "https://arijit-07-devops-incident-response.hf.space/generate/preview?seed=12345"
|
| 276 |
+
|
| 277 |
+
# Run it as a full episode
|
| 278 |
+
curl -X POST .../reset -d '{"task_id":"generated","seed":12345}'
|
| 279 |
+
```
|
| 280 |
+
|
| 281 |
+
---
|
| 282 |
+
|
| 283 |
+
## π Reward Function Design
|
| 284 |
+
|
| 285 |
+
### The Formula
|
| 286 |
+
|
| 287 |
+
```
|
| 288 |
+
Final Score = Ξ£(step_rewards)
|
| 289 |
+
+ efficiency_bonus # (1 - steps/max_steps) Γ 0.05 if resolved
|
| 290 |
+
+ diagnosis_precision_bonus # +0.03 if β₯50% keyword overlap, +0.01 if β₯30%
|
| 291 |
+
- noop_penalty # (noop_count - 3) Γ 0.02
|
| 292 |
+
- repeat_restart_penalty # (restarts - 1) Γ 0.05 per service
|
| 293 |
+
```
|
| 294 |
+
|
| 295 |
+
All scores clamped to **(0.001, 0.999)** β never exactly 0 or 1.
|
| 296 |
+
|
| 297 |
+
> **Why (0.001, 0.999) not (0, 1)?** GRPO advantage normalization requires non-constant rewards within a group. Hard 0 or 1 creates zero-variance groups where the model doesn't update. The tiny clamp ensures a gradient signal always exists.
|
| 298 |
+
|
| 299 |
+
### Step-Level Rewards
|
| 300 |
+
|
| 301 |
+
| Action | Reward | Condition |
|
| 302 |
+
|---|---|---|
|
| 303 |
+
| `read_logs` (failing service) | +0.10β0.15 | First time only |
|
| 304 |
+
| `read_metrics` (failing service) | +0.10 | First time only |
|
| 305 |
+
| `read_runbook` (relevant) | +0.05 | Correct runbook for scenario |
|
| 306 |
+
| `search_logs` (relevant query) | +0.05 | Query returns useful results |
|
| 307 |
+
| `diagnose` (full match) | +0.30β0.35 | β₯50% keyword overlap |
|
| 308 |
+
| `diagnose` (partial match) | +0.10β0.15 | β₯30% keyword overlap |
|
| 309 |
+
| `restart_service` (correct) | +0.35β0.45 | Root cause service |
|
| 310 |
+
| `rollback` (correct) | +0.30β0.40 | Root cause service |
|
| 311 |
+
| `block_ip_range` (correct) | +0.40 | Security task, correct CIDR |
|
| 312 |
+
| `create_index` (correct) | +0.40 | Database task, correct table/column |
|
| 313 |
+
| `failover` (eligible service) | +0.30 | Per correctly failed-over service |
|
| 314 |
+
| `alert_oncall` (required) | +0.15 | Hard/security/database/failover tasks |
|
| 315 |
+
|
| 316 |
+
### Penalties (Anti-Gaming)
|
| 317 |
+
|
| 318 |
+
| Action | Penalty | Why |
|
| 319 |
+
|---|---|---|
|
| 320 |
+
| Restart healthy service | -0.15 | Collateral damage β realistic cost |
|
| 321 |
+
| Fix without diagnosing | -0.10 | Blind remediation β models real risk |
|
| 322 |
+
| Failover payment-service | -0.25 | PCI-DSS compliance violation |
|
| 323 |
+
| Failover postgres-primary | -0.25 | Data loss risk |
|
| 324 |
+
| Excessive noops (>3) | -0.04/each | Forces active investigation |
|
| 325 |
+
| Repeat restart same service | -0.05/extra | Discourages guess-and-check |
|
| 326 |
+
|
| 327 |
+
### Semantic Diagnosis Matching
|
| 328 |
+
|
| 329 |
+
The `diagnose` action uses **keyword overlap** not exact string matching. An agent saying "memory exhaustion in payment-service" correctly matches the ground truth "memory_leak_payment_service". This is critical for LLM agents that paraphrase β exact string matching would unfairly penalize valid diagnoses.
|
| 330 |
+
|
| 331 |
+
### SLA Degradation
|
| 332 |
+
|
| 333 |
+
Every step where an incident is unresolved, the environment worsens:
|
| 334 |
+
- `down` services: error_rate increases
|
| 335 |
+
- `degraded` services: latency_p99 increases
|
| 336 |
+
- SLA status: `ok` β `warning` (~3 steps) β `breached` (~7 steps)
|
| 337 |
+
|
| 338 |
+
This creates real time pressure and rewards faster resolution.
|
| 339 |
+
|
| 340 |
+
---
|
| 341 |
+
|
| 342 |
+
## π ARIA Features
|
| 343 |
+
|
| 344 |
+
### Curriculum Engine
|
| 345 |
+
|
| 346 |
+
The Curriculum Engine tracks agent performance per task using a rolling average of the last 5 episodes.
|
| 347 |
+
|
| 348 |
+
- **Promotion:** rolling_avg > 0.75 β advance mastery level (Novice β Intermediate β Advanced β Mastered)
|
| 349 |
+
- **Demotion:** rolling_avg < 0.30 β step back mastery level
|
| 350 |
+
- **Scaffolding:** if avg < 0.30 over 3+ episodes β provide task-specific hint
|
| 351 |
+
|
| 352 |
+
```bash
|
| 353 |
+
GET /curriculum/status # See mastery per task
|
| 354 |
+
GET /curriculum/next # Get recommended next task
|
| 355 |
+
GET /curriculum/hint/easy # Get scaffolding hint for a task
|
| 356 |
+
POST /curriculum/record # Feed your training results in
|
| 357 |
+
```
|
| 358 |
+
|
| 359 |
+
**Why this matters for training:** RL fails when agents never see successful trajectories. The curriculum ensures agents always train at the edge of their capability β easy tasks first, harder tasks as they master the fundamentals.
|
| 360 |
+
|
| 361 |
+
### Incident Generator
|
| 362 |
+
|
| 363 |
+
Procedural incident generation from seeds. 6 failure modes Γ 8 services Γ 3 severities Γ 0β3 noise alerts = thousands of unique training scenarios.
|
| 364 |
+
|
| 365 |
+
**Difficulty formula:** `base_difficulty[failure_mode] + (noise_count Γ 0.05)`, clamped to 1.0
|
| 366 |
+
|
| 367 |
+
| Failure Mode | Base Difficulty |
|
| 368 |
+
|---|---|
|
| 369 |
+
| oom | 0.20 |
|
| 370 |
+
| cascade | 0.50 |
|
| 371 |
+
| database | 0.60 |
|
| 372 |
+
| security | 0.60 |
|
| 373 |
+
| network_partition | 0.70 |
|
| 374 |
+
| corruption | 0.80 |
|
| 375 |
+
|
| 376 |
+
```bash
|
| 377 |
+
GET /generate/preview?seed=42 # Preview without starting
|
| 378 |
+
POST /reset # body: {"task_id":"generated","seed":42}
|
| 379 |
+
```
|
| 380 |
+
|
| 381 |
+
### Dual-Agent Mode
|
| 382 |
+
|
| 383 |
+
One incident. Two agents. Split observability.
|
| 384 |
+
|
| 385 |
+
- **Agent A (Observer):** Sees logs, alerts, evidence. Can ONLY call `share_finding` β passes natural language observations to Agent B. Reward: +0.05 per finding.
|
| 386 |
+
- **Agent B (Responder):** Sees metrics, service dependencies, SLA status. Cannot see logs directly. Must rely on Agent A's findings. Executes all real actions.
|
| 387 |
+
|
| 388 |
+
Neither agent can solve the incident alone.
|
| 389 |
+
|
| 390 |
+
```bash
|
| 391 |
+
# Start a dual-agent session
|
| 392 |
+
POST /multi-agent/reset {"task_id":"easy","seed":42}
|
| 393 |
+
# β returns session_id + split observations
|
| 394 |
+
|
| 395 |
+
# Agent A shares a finding
|
| 396 |
+
POST /multi-agent/step/a/{session_id} {"finding":"payment-service OOM, memory at 98%"}
|
| 397 |
+
|
| 398 |
+
# Agent B takes action (has access to Agent A's findings)
|
| 399 |
+
POST /multi-agent/step/b/{session_id} {"action_type":"restart_service","service":"payment-service"}
|
| 400 |
+
|
| 401 |
+
# See full session state
|
| 402 |
+
GET /multi-agent/state/{session_id}
|
| 403 |
+
```
|
| 404 |
+
|
| 405 |
+
---
|
| 406 |
+
|
| 407 |
+
## π§ Training
|
| 408 |
+
|
| 409 |
+
### Model
|
| 410 |
+
|
| 411 |
+
**Llama-3.2-3B-Instruct** fine-tuned with **GRPO** (Group Relative Policy Optimization) using HuggingFace TRL and Unsloth.
|
| 412 |
+
|
| 413 |
+
- **LoRA:** rank=16, alpha=32, targeting all 7 projection layers
|
| 414 |
+
- **Adapter size:** ~97MB
|
| 415 |
+
- **Training:** 140 episodes (easy + medium tasks) on Kaggle T4 x2 GPUs
|
| 416 |
+
- **Model repo:** https://huggingface.co/Arijit-07/aria-devops-llama3b
|
| 417 |
+
|
| 418 |
+
### Why GRPO?
|
| 419 |
+
|
| 420 |
+
GRPO eliminates the value network that PPO requires. For environment-based RL where rewards come from an external API, a value model adds complexity without benefit. GRPO estimates the baseline from a group of 6 completions per step β simpler, more memory-efficient, and well-suited to fast environment APIs.
|
| 421 |
+
|
| 422 |
+
### Training Loop
|
| 423 |
+
|
| 424 |
+
```python
|
| 425 |
+
# Each training step:
|
| 426 |
+
# 1. Generate 6 completions for the current observation
|
| 427 |
+
# 2. Score each on a FRESH env snapshot (prevents reward gate exhaustion)
|
| 428 |
+
# 3. Normalize rewards to advantages (GRPO)
|
| 429 |
+
# 4. Policy gradient update on best completion + KL penalty
|
| 430 |
+
# 5. Advance episode with best action
|
| 431 |
+
|
| 432 |
+
# Key hyperparameters:
|
| 433 |
+
learning_rate = 5e-6
|
| 434 |
+
group_size = 6
|
| 435 |
+
kl_coefficient = 0.05 # prevents catastrophic forgetting
|
| 436 |
+
update_strategy = "episode-level" # one update per full episode
|
| 437 |
+
```
|
| 438 |
+
|
| 439 |
+
### Results
|
| 440 |
+
|
| 441 |
+
| | Base Model | Fine-tuned (ep140) |
|
| 442 |
+
|---|---|---|
|
| 443 |
+
| **Easy task** | 0.000 | 0.150 |
|
| 444 |
+
| **Behavior** | Jumps to diagnose immediately | Reads logs on correct service first |
|
| 445 |
+
| **Why the difference** | Base model triggers blind remediation penalty | Fine-tuned model learned to gather information before acting |
|
| 446 |
+
|
| 447 |
+
**The trained model consistently reads logs on the failing service before acting** β this is the foundational operational behavior: information gathering before remediation. The base model never does this.
|
| 448 |
+
|
| 449 |
+
**Training challenge identified:** The original training loop called `env_step` during group generation, burning reward gates before the best action could advance the episode. After fixing to score completions on fresh environment snapshots, the model successfully learned step 1 of the optimal policy. With more episodes using the corrected loop, the full sequence would emerge.
|
| 450 |
+
|
| 451 |
+
### Training Notebook
|
| 452 |
+
|
| 453 |
+
See `train_grpo.ipynb` β Colab-compatible, runs against the live HF Space API (no local setup needed).
|
| 454 |
+
|
| 455 |
+
[](https://colab.research.google.com/github/Twilight-13/devops-incident-response/blob/main/train_grpo.ipynb)
|
| 456 |
+
|
| 457 |
+
Compatible with: TRL, SkyRL, ART, Oumi, Axolotl.
|
| 458 |
+
|
| 459 |
+
---
|
| 460 |
+
|
| 461 |
+
## π Setup
|
| 462 |
+
|
| 463 |
+
### Docker (Recommended)
|
| 464 |
+
|
| 465 |
+
```bash
|
| 466 |
+
docker build -t aria-devops-incident .
|
| 467 |
+
docker run -p 7860:7860 aria-devops-incident
|
| 468 |
+
curl http://localhost:7860/health
|
| 469 |
+
```
|
| 470 |
+
|
| 471 |
+
### Local Python
|
| 472 |
+
|
| 473 |
+
```bash
|
| 474 |
+
pip install -r requirements.txt
|
| 475 |
+
uvicorn api:app --host 0.0.0.0 --port 7860
|
| 476 |
+
```
|
| 477 |
+
|
| 478 |
+
### Validate
|
| 479 |
+
|
| 480 |
+
```bash
|
| 481 |
+
python validate.py # 22 automated checks, exit 0 = all pass
|
| 482 |
+
curl http://localhost:7860/validate
|
| 483 |
+
```
|
| 484 |
+
|
| 485 |
+
---
|
| 486 |
+
|
| 487 |
+
## π‘ API Reference
|
| 488 |
+
|
| 489 |
+
| Method | Endpoint | Description |
|
| 490 |
+
|---|---|---|
|
| 491 |
+
| GET | `/health` | `{"status":"ok"}` liveness check |
|
| 492 |
+
| GET | `/about` | Full environment description (machine-readable) |
|
| 493 |
+
| GET | `/tasks` | All 8 tasks with descriptions |
|
| 494 |
+
| POST | `/reset` | Start episode: `{"task_id":"easy","seed":42}` |
|
| 495 |
+
| POST | `/step` | Take action: Action JSON |
|
| 496 |
+
| GET | `/state` | Full state + ground truth + analytics |
|
| 497 |
+
| GET | `/validate` | Self-test: random agent on all 7 tasks |
|
| 498 |
+
| GET | `/metrics` | Aggregate episode statistics |
|
| 499 |
+
| GET | `/leaderboard` | Top 10 episodes |
|
| 500 |
+
| WS | `/ws` | WebSocket: real-time agent-environment |
|
| 501 |
+
| GET | `/curriculum/status` | Per-task mastery and recommendations |
|
| 502 |
+
| GET | `/curriculum/next` | Recommended next task for training |
|
| 503 |
+
| GET | `/curriculum/hint/{task_id}` | Scaffolding hint for struggling agents |
|
| 504 |
+
| POST | `/curriculum/record` | Feed episode result to curriculum engine |
|
| 505 |
+
| GET | `/generate/preview` | Preview procedural incident: `?seed=N` |
|
| 506 |
+
| POST | `/multi-agent/reset` | Start dual-agent session |
|
| 507 |
+
| POST | `/multi-agent/step/a/{id}` | Agent A shares a finding |
|
| 508 |
+
| POST | `/multi-agent/step/b/{id}` | Agent B takes an action |
|
| 509 |
+
| GET | `/multi-agent/state/{id}` | Full dual-agent session state |
|
| 510 |
+
| GET | `/multi-agent/sessions` | List active sessions |
|
| 511 |
+
| GET | `/docs` | Swagger UI β interactive documentation |
|
| 512 |
+
|
| 513 |
+
---
|
| 514 |
+
|
| 515 |
+
## π Benchmark Comparison
|
| 516 |
+
|
| 517 |
+
| Benchmark | Domain | Partial Obs | Dense Reward | Multi-Step | Curriculum | Multi-Agent |
|
| 518 |
+
|---|---|---|---|---|---|---|
|
| 519 |
+
| SWE-bench | Code repair | β | β | β | β | β |
|
| 520 |
+
| WebArena | Web navigation | β | β | β | β | β |
|
| 521 |
+
| AgentBench | General tools | β | β | β | β | β |
|
| 522 |
+
| **ARIA (ours)** | **Incident response** | **β** | **β** | **β** | **β** | **β** |
|
| 523 |
+
|
| 524 |
+
---
|
| 525 |
+
|
| 526 |
+
## ποΈ OpenEnv Compliance
|
| 527 |
+
|
| 528 |
+
```bash
|
| 529 |
+
openenv validate .
|
| 530 |
+
```
|
| 531 |
+
|
| 532 |
+
- Inherits from `openenv.core.env_client.EnvClient`
|
| 533 |
+
- Standard `reset()`, `step()`, `state()` interface
|
| 534 |
+
- Valid `openenv.yaml` manifest with all 8 tasks
|
| 535 |
+
- FastAPI server with health endpoint
|
| 536 |
+
- WebSocket support at `/ws`
|
| 537 |
+
- Hosted on HuggingFace Spaces
|
| 538 |
+
|
| 539 |
+
---
|
| 540 |
+
|
| 541 |
+
## π Repository Structure
|
| 542 |
+
|
| 543 |
+
```
|
| 544 |
+
aria-devops-incident-response/
|
| 545 |
+
βββ api.py # FastAPI app β all endpoints
|
| 546 |
+
βββ env.py # DevOpsIncidentEnv β thin dispatcher
|
| 547 |
+
βββ models.py # Pydantic models β Action, Observation, State
|
| 548 |
+
βββ tasks/
|
| 549 |
+
β βββ base.py # BaseTask ABC, InternalState, reward logic
|
| 550 |
+
β βββ task_easy.py # OOM crash-loop
|
| 551 |
+
β βββ task_medium.py # Cascading failure
|
| 552 |
+
β βββ task_hard.py # Silent data corruption
|
| 553 |
+
β βββ task_bonus.py # Dual simultaneous failure
|
| 554 |
+
β βββ task_security.py # DDoS attack
|
| 555 |
+
β βββ task_database.py # Missing index
|
| 556 |
+
β βββ task_failover.py # Multi-region failover
|
| 557 |
+
β βββ task_generated.py # Procedural incidents
|
| 558 |
+
βββ curriculum/
|
| 559 |
+
β βββ engine.py # CurriculumEngine β adaptive difficulty
|
| 560 |
+
βββ generator/
|
| 561 |
+
β βββ incident_factory.py # IncidentFactory β procedural generation
|
| 562 |
+
βββ multi_agent/
|
| 563 |
+
β βββ session.py # DualAgentSession β split observability
|
| 564 |
+
βββ graders/
|
| 565 |
+
β βββ grader.py # Deterministic episode grader
|
| 566 |
+
βββ data/runbooks/ # 6 operational runbooks (Markdown)
|
| 567 |
+
βββ client.py # openenv-core EnvClient implementation
|
| 568 |
+
βββ inference.py # LLM baseline (CoT + fast modes)
|
| 569 |
+
βββ train_grpo.ipynb # GRPO training notebook (Colab-compatible)
|
| 570 |
+
βββ validate.py # 22 automated validation checks
|
| 571 |
+
βββ openenv.yaml # OpenEnv spec manifest
|
| 572 |
+
```
|
| 573 |
+
|
| 574 |
+
---
|
| 575 |
+
|
| 576 |
+
## π License
|
| 577 |
+
|
| 578 |
+
Apache 2.0
|
| 579 |
+
|
| 580 |
+
---
|
| 581 |
+
|
| 582 |
+
*Built solo for the Meta Γ PyTorch Γ HuggingFace OpenEnv Hackathon Finals β Bangalore, April 2026*
|