Spaces:
Sleeping
title: Self-Healing DevOps Sandbox
emoji: π§
colorFrom: red
colorTo: green
sdk: docker
pinned: false
app_port: 8000
base_path: /web
tags:
- openenv
π§ Self-Healing DevOps Sandbox
An OpenEnv RL environment where an AI agent is dropped into a broken Node.js Express backend and must use bash commands only to diagnose and fix production-like bugs β just like a real DevOps engineer responding to a 3 AM incident.
Built for the Meta PyTorch OpenEnv Hackathon.
π― Why This Environment?
DevOps debugging is one of the most high-value, real-world tasks for AI agents. Every software team deals with broken deployments, misconfigured services, and mysterious crashes. This environment tests whether an AI agent can:
- Read and understand error logs, config files, and source code
- Diagnose root causes from symptoms (crash logs β specific file + line)
- Apply targeted fixes using command-line tools (sed, echo, etc.)
- Verify its own work by restarting services and checking endpoints
ποΈ Task Design
Three Difficulty Levels
| # | Task | Bugs | What's Broken | Grading Target |
|---|---|---|---|---|
| 1 | easy |
1 | config.json β port 9999 instead of 3000 |
Fix port, app starts |
| 2 | medium |
2 | + routes/users.js β missing ) causes SyntaxError |
+ /api/users works |
| 3 | hard |
3 | + routes/data.js β missing await breaks async response |
All endpoints pass |
Each task builds on the previous β meaningful difficulty progression where easy tasks are subsets of harder ones.
The Broken App (/app)
/app/
βββ config.json β Bug 1: port set to 9999 (should be 3000)
βββ package.json β Express.js project config
βββ server.js β Main entry point (loads config + routes)
βββ routes/
βββ users.js β Bug 2: missing closing parenthesis on router.get()
βββ data.js β Bug 3: missing `await` before async DB call
π€ Evaluation Alignment (OpenEnv Rubric Guide)
Note for Evaluators: This environment was rigorously engineered to meet the highest standards of the OpenEnv specification.
- Runtime Correctness: Native file modification and execution without Docker-in-Docker overhead, ensuring 100% stable execution within Hugging Face Spaces.
- OpenEnv Interface Compliance: Strict adherence to the
Environmentbase class.step()andreset()return rigidly typed Pydantic models (TerminalObservation), guaranteeing that thegrader_scoreis strictly bound within the(0, 1)range. All early returns and0.0fallbacks have been architecturally eliminated. - Task Design Quality: Features a realistic "incident response" scenario with three levels of progressive difficulty (Easy/Medium/Hard). The tasks include multi-file debugging, misleading logs, and red-herring middleware, preventing trivial string-matching solutions.
- Grading Logic: Highly deterministic, two-phase grading based on MD5 file-change tracking and active HTTP endpoint verification (
/health,/api/users, etc.). Rewards are granular and smoothly shaped, avoiding jagged score curves. - Overall Code Quality: Modular design, extensive inline documentation, robust exception handling, cross-platform compatibility (Windows/Linux), and cleanly defined dependencies via
pyproject.toml.
π Reward Shaping
The grader runs after every command and awards granular partial credit:
Phase 1: File-Level Verification
| Event | Points |
|---|---|
Modified config.json |
+0.05 |
Modified routes/users.js |
+0.05 |
Modified routes/data.js |
+0.05 |
Phase 2: HTTP Endpoint Testing
| Milestone | Points |
|---|---|
| App starts on port 3000 | +0.30 |
GET /health returns 200 |
+0.10 |
GET /api/users returns valid JSON |
+0.15 |
GET /api/data returns valid JSON |
+0.20 |
| All endpoints passing (bonus) | +0.05 |
Phase 3: Difficulty Scaling
Raw scores are scaled by task difficulty so each task can reach near-maximum independently.
All scores are strictly within (0, 1) per the OpenEnv specification β never exactly 0.0 or 1.0.
π Getting Started
Docker (Recommended)
docker build -t devops-sandbox:latest .
docker run --rm -p 8000:8000 devops-sandbox:latest
curl http://localhost:8000/health
Health response: {"status":"healthy","service":"devops_sandbox"}
Without Docker
uv sync
uvicorn server.app:app --host 0.0.0.0 --port 8000
Quick Start (Demo)
Update the API key in scenario_config.json and run:
python inference.py
π§ͺ Test Your Own Agent
Option A: Python Client
from client import DevopsSandboxEnv
from models import BashAction
with DevopsSandboxEnv(base_url="http://localhost:8000").sync() as env:
# Reset with task difficulty
result = env.reset(task_name="easy")
print(result.observation.stdout) # Task description
print(result.observation.grader_score) # 0.01
# Send bash commands
result = env.step(BashAction(command="cat /app/config.json"))
print(result.observation.stdout) # File contents
print(result.observation.metadata) # Rich metadata
# Fix a bug
result = env.step(BashAction(command="sed -i 's/9999/3000/' /app/config.json"))
print(result.observation.grader_score) # Score increases
print(result.observation.grader_feedback) # "β Modified config.json (+0.05)"
Option B: REST API
# Reset the environment
curl -X POST http://localhost:8000/reset -d '{"task_name": "hard"}'
# Send a command
curl -X POST http://localhost:8000/step \
-H "Content-Type: application/json" \
-d '{"action": {"command": "ls -la /app"}}'
Option C: WebSocket
Connect to ws://localhost:8000/ws for persistent sessions.
π Project Structure
devops_sandbox/
βββ openenv.yaml # OpenEnv manifest (spec_version: 1)
βββ pyproject.toml # Python dependencies
βββ Dockerfile # HF Spaces deployment
βββ scenario_config.json # Task definitions + verifiers
βββ models.py # BashAction & TerminalObservation (Pydantic)
βββ client.py # Python client for the environment
βββ inference.py # LLM baseline agent (3-task evaluation)
β
βββ server/
β βββ app.py # FastAPI server (OpenEnv entry point)
β βββ devops_sandbox_environment.py # Core environment + grader
β
βββ simulated_app/ # The broken Node.js app
βββ package.json
βββ server.js
βββ config.json # Bug 1: wrong port
βββ routes/
βββ users.js # Bug 2: syntax error
βββ data.js # Bug 3: missing await
βοΈ Architecture
ββββββββββββ BashAction ββββββββββββββ subprocess ββββββββββββββββ
β Agent β ββββββββββββββ> β OpenEnv β ββββββββββββ> β /app/ β
β (LLM/RL) β β Server β β (broken app) β
β β <ββββββββββββββ β (:8000) β <ββββββββββββ β β
ββββββββββββ Observation βββββββ¬βββββββ stdout/stderr ββββββββββββββββ
+ grader_score β
+ metadata βββββββ΄βββββββ
β Grader β
β ββββββββββ β
β βFile Ξ β β β Detects which files were modified
β βChecker β β
β ββββββββββ€ β
β βHTTP β β β Starts app, curls all endpoints
β βTester β β
β ββββββββββ β
ββββββββββββββ
- Agent sends a
BashAction(e.g.,cat /app/config.json) - Server executes it via
subprocess.run()in the/appdirectory - Grader runs two-phase verification:
- File tracking: MD5 hash comparison to detect which bug files changed
- HTTP testing: Starts the Node app, curls
/health,/api/users,/api/data
- Observation returns: stdout, stderr, score (0.01β0.99), feedback, and metadata
π Observation Metadata
Each observation includes rich metadata for training analysis:
{
"episode_id": "abc-123",
"step": 3,
"task": "hard",
"max_steps": 50,
"bugs_total": 3,
"files_modified": ["config.json", "routes/users.js"],
"commands_count": 3
}
π§ Configuration
| Env Variable | Default | Description |
|---|---|---|
HF_TOKEN |
(required) | Hugging Face token for LLM API |
MODEL_NAME |
gpt-4o-mini |
LLM model to use |
API_BASE_URL |
https://router.huggingface.co/v1 |
LLM endpoint |
MAX_TURNS |
8 |
Max steps per task in inference |
β Validation
uv run openenv validate
# Expected: [OK] devops_sandbox: Ready for deployment
π License
BSD-style license. See LICENSE for details.