Spaces:
Sleeping
Sleeping
PROTHAM commited on
Commit Β·
887572f
1
Parent(s): cbb7810
Final README with full documentation
Browse files
README.md
CHANGED
|
@@ -9,4 +9,298 @@ pinned: false
|
|
| 9 |
|
| 10 |
# API Debug Environment
|
| 11 |
|
| 12 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
|
| 10 |
# API Debug Environment
|
| 11 |
|
| 12 |
+
> A real-world OpenEnv environment where AI agents learn to debug broken HTTP API requests.
|
| 13 |
+
|
| 14 |
+
Built for the **Scaler Γ Meta PyTorch Γ HuggingFace OpenEnv Hackathon 2026**.
|
| 15 |
+
|
| 16 |
+
---
|
| 17 |
+
|
| 18 |
+
## What This Environment Does
|
| 19 |
+
|
| 20 |
+
An AI agent is given a **broken HTTP request** and a task description. It interacts with a live mock REST API running inside the same container, reads the real HTTP error responses (401, 422, 429, 500), and iteratively fixes its requests β adjusting headers, methods, body types, and authentication flows β until it receives a successful 200 response.
|
| 21 |
+
|
| 22 |
+
Every step produces a real HTTP call. The grader is fully deterministic: no LLM, no fuzzy matching. The reward is derived entirely from HTTP status codes and response schema matching.
|
| 23 |
+
|
| 24 |
+
---
|
| 25 |
+
|
| 26 |
+
## Environment Summary
|
| 27 |
+
|
| 28 |
+
| Property | Value |
|
| 29 |
+
|---|---|
|
| 30 |
+
| **Framework** | OpenEnv (openenv-core 0.2.3) |
|
| 31 |
+
| **Tasks** | 3 difficulty levels β 9 tasks total |
|
| 32 |
+
| **Max Steps per Episode** | 5 |
|
| 33 |
+
| **Reward Range** | 0.0 β 1.0 |
|
| 34 |
+
| **Grader** | Fully deterministic (no LLM) |
|
| 35 |
+
| **Mock API** | Internal FastAPI router, same container |
|
| 36 |
+
| **Port** | 7860 (HF Spaces) |
|
| 37 |
+
|
| 38 |
+
---
|
| 39 |
+
|
| 40 |
+
## Action Space
|
| 41 |
+
|
| 42 |
+
The agent sends a structured HTTP request at each step.
|
| 43 |
+
|
| 44 |
+
| Field | Type | Description |
|
| 45 |
+
|---|---|---|
|
| 46 |
+
| `method` | `str` | HTTP method β `GET`, `POST`, `PUT`, `DELETE`, `PATCH` |
|
| 47 |
+
| `url` | `str` | Endpoint path e.g. `/mock_api/users` |
|
| 48 |
+
| `headers` | `dict` | Request headers e.g. `{"Authorization": "Bearer token"}` |
|
| 49 |
+
| `body` | `dict` | Request body β `null` for GET requests |
|
| 50 |
+
| `query_params` | `dict` | URL query parameters e.g. `{"q": "python"}` |
|
| 51 |
+
|
| 52 |
+
---
|
| 53 |
+
|
| 54 |
+
## Observation Space
|
| 55 |
+
|
| 56 |
+
After each step the agent receives:
|
| 57 |
+
|
| 58 |
+
| Field | Type | Description |
|
| 59 |
+
|---|---|---|
|
| 60 |
+
| `task_id` | `str` | Current task β `easy`, `medium`, or `hard` |
|
| 61 |
+
| `task_description` | `str` | Plain-English description of what needs to be fixed |
|
| 62 |
+
| `broken_request` | `dict` | The original broken request shown at episode start |
|
| 63 |
+
| `last_status_code` | `int` | HTTP status from last step (0 = not yet tried) |
|
| 64 |
+
| `last_response_headers` | `dict` | Response headers from last step |
|
| 65 |
+
| `last_response_body` | `str` | Raw response body from last step |
|
| 66 |
+
| `step_feedback` | `str` | Human-readable hint based on last error |
|
| 67 |
+
| `current_score` | `float` | Running reward 0.0β1.0 |
|
| 68 |
+
| `reward` | `float` | Reward for the last step |
|
| 69 |
+
| `done` | `bool` | Whether the episode has ended |
|
| 70 |
+
| `attempt` | `int` | Current step number |
|
| 71 |
+
|
| 72 |
+
---
|
| 73 |
+
|
| 74 |
+
## Tasks
|
| 75 |
+
|
| 76 |
+
### Easy β Auth and Header Errors
|
| 77 |
+
|
| 78 |
+
Simple fixes to authentication headers and request format.
|
| 79 |
+
|
| 80 |
+
| Task ID | Bug | What the Agent Needs to Fix |
|
| 81 |
+
|---|---|---|
|
| 82 |
+
| `easy_auth` | Missing `Authorization` header | Add `Authorization: Bearer demo_token_123` to GET `/mock_api/users` |
|
| 83 |
+
| `easy_content_type` | Wrong `Content-Type: text/plain` | Change to `application/json` and add `{"name": "book"}` body to POST `/mock_api/items` |
|
| 84 |
+
| `easy_query_param` | Missing `?q=` query param | Add `q=python` to GET `/mock_api/search` |
|
| 85 |
+
|
| 86 |
+
### Medium β Method and Body Errors
|
| 87 |
+
|
| 88 |
+
Requires understanding API semantics and request structure.
|
| 89 |
+
|
| 90 |
+
| Task ID | Bug | What the Agent Needs to Fix |
|
| 91 |
+
|---|---|---|
|
| 92 |
+
| `medium_wrong_method` | `GET` instead of `POST` | Change method to POST on `/mock_api/orders` |
|
| 93 |
+
| `medium_type_mismatch` | `product_id: "five"` (string) | Fix to integer `5` in body |
|
| 94 |
+
| `medium_nested_field` | `address: "123 Main St"` (string) | Fix to dict `{"street": "123 Main St", "city": "NY"}` |
|
| 95 |
+
|
| 96 |
+
### Hard β Rate Limiting and Multi-step Auth
|
| 97 |
+
|
| 98 |
+
Requires multi-step reasoning and handling stateful API behaviour.
|
| 99 |
+
|
| 100 |
+
| Task ID | Bug | What the Agent Needs to Fix |
|
| 101 |
+
|---|---|---|
|
| 102 |
+
| `hard_token_exchange` | Stale/expired Bearer token | First POST to `/mock_api/auth/token` to get a fresh token, then use it on GET `/mock_api/protected` |
|
| 103 |
+
| `hard_rate_limit` | No backoff after 429 | After receiving 429, include `X-Retry-After: 2` header on next request |
|
| 104 |
+
| `hard_pagination` | Never follows cursor | Call GET `/mock_api/logs?cursor=<value>` until `has_more` is `false` |
|
| 105 |
+
|
| 106 |
+
---
|
| 107 |
+
|
| 108 |
+
## Reward Function
|
| 109 |
+
|
| 110 |
+
```
|
| 111 |
+
reward = schema_match_score Γ attempt_bonus
|
| 112 |
+
attempt_bonus = max(0.0, 1.0 β (attempt / max_steps) Γ 0.15)
|
| 113 |
+
```
|
| 114 |
+
|
| 115 |
+
Agents are rewarded more for solving tasks in fewer steps. Partial credit is given at every step:
|
| 116 |
+
|
| 117 |
+
| HTTP Status Received | Partial Reward | Meaning |
|
| 118 |
+
|---|---|---|
|
| 119 |
+
| 0 | 0.00 | Request never sent / connection error |
|
| 120 |
+
| 401 / 403 / 404 | 0.05 | Hit the endpoint, auth failed |
|
| 121 |
+
| 405 / 415 | 0.10 | Auth ok, wrong method or content-type |
|
| 122 |
+
| 422 | 0.15 | Auth ok, body validation failed |
|
| 123 |
+
| 429 | 0.20 | Hit endpoint, needs rate limit handling |
|
| 124 |
+
| 200 (schema mismatch) | 0.70 | Right status, wrong response structure |
|
| 125 |
+
| 200 (schema match) | 0.85β1.00 | Correct β higher reward for fewer attempts |
|
| 126 |
+
|
| 127 |
+
---
|
| 128 |
+
|
| 129 |
+
## Mock API Endpoints
|
| 130 |
+
|
| 131 |
+
All endpoints are mounted at `/mock_api/` inside the same container οΏ½οΏ½ no external calls, fully reproducible.
|
| 132 |
+
|
| 133 |
+
| Method | Path | What it Does | Common Error |
|
| 134 |
+
|---|---|---|---|
|
| 135 |
+
| `GET` | `/mock_api/users` | Returns user list | 401 if no Bearer token |
|
| 136 |
+
| `POST` | `/mock_api/items` | Creates an item | 415 if wrong Content-Type, 422 if no `name` |
|
| 137 |
+
| `GET` | `/mock_api/search` | Search results | 422 if no `?q=` param |
|
| 138 |
+
| `POST` | `/mock_api/orders` | Creates an order | 405 if GET, 422 if wrong types |
|
| 139 |
+
| `POST` | `/mock_api/profile` | Updates profile | 422 if `address` is not a dict |
|
| 140 |
+
| `POST` | `/mock_api/auth/token` | Issues a token | 401 if wrong credentials |
|
| 141 |
+
| `GET` | `/mock_api/protected` | Protected resource | 401 if token not from `/auth/token` |
|
| 142 |
+
| `GET` | `/mock_api/rate_limited` | Rate-limited resource | 429 after 3 requests without `X-Retry-After` |
|
| 143 |
+
| `GET` | `/mock_api/logs` | Paginated log entries | Returns cursor β must follow chain |
|
| 144 |
+
|
| 145 |
+
---
|
| 146 |
+
|
| 147 |
+
## API Endpoints (OpenEnv)
|
| 148 |
+
|
| 149 |
+
| Method | Path | Description |
|
| 150 |
+
|---|---|---|
|
| 151 |
+
| `GET` | `/health` | Health check β returns `{"status": "ok"}` |
|
| 152 |
+
| `POST` | `/reset` | Start new episode. Body: `{"task_id": "easy"}` |
|
| 153 |
+
| `POST` | `/step` | Execute action. Body: `{"action": {...}}` |
|
| 154 |
+
| `GET` | `/state` | Get current episode state |
|
| 155 |
+
| `GET` | `/docs` | Auto-generated Swagger UI |
|
| 156 |
+
|
| 157 |
+
---
|
| 158 |
+
|
| 159 |
+
## Quick Start
|
| 160 |
+
|
| 161 |
+
### Connect to the deployed Space
|
| 162 |
+
|
| 163 |
+
```python
|
| 164 |
+
from client import APIDebugEnv
|
| 165 |
+
from models import APIAction
|
| 166 |
+
|
| 167 |
+
with APIDebugEnv(base_url="https://ProthamD-api-debug-env.hf.space").sync() as env:
|
| 168 |
+
# Start an episode
|
| 169 |
+
obs = env.reset(task_id="easy")
|
| 170 |
+
print(obs.task_description)
|
| 171 |
+
print(obs.broken_request)
|
| 172 |
+
|
| 173 |
+
# Fix the request and step
|
| 174 |
+
result = env.step(APIAction(
|
| 175 |
+
method="GET",
|
| 176 |
+
url="/mock_api/users",
|
| 177 |
+
headers={"Authorization": "Bearer demo_token_123"},
|
| 178 |
+
body=None,
|
| 179 |
+
query_params={}
|
| 180 |
+
))
|
| 181 |
+
print(result.reward) # 0.85+
|
| 182 |
+
print(result.observation.step_feedback)
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
### Install the client
|
| 186 |
+
|
| 187 |
+
```bash
|
| 188 |
+
pip install git+https://huggingface.co/spaces/ProthamD/api-debug-env
|
| 189 |
+
```
|
| 190 |
+
|
| 191 |
+
### Run locally with Docker
|
| 192 |
+
|
| 193 |
+
```bash
|
| 194 |
+
docker pull registry.hf.space/ProthamD-api-debug-env:latest
|
| 195 |
+
docker run -p 7860:7860 registry.hf.space/ProthamD-api-debug-env:latest
|
| 196 |
+
```
|
| 197 |
+
|
| 198 |
+
---
|
| 199 |
+
|
| 200 |
+
## Run the Baseline Inference Script
|
| 201 |
+
|
| 202 |
+
```bash
|
| 203 |
+
# Set environment variables
|
| 204 |
+
export API_BASE_URL=https://router.huggingface.co/v1
|
| 205 |
+
export MODEL_NAME=mistralai/Mistral-7B-Instruct-v0.3
|
| 206 |
+
export HF_TOKEN=hf_your_token_here
|
| 207 |
+
export ENV_URL=https://ProthamD-api-debug-env.hf.space
|
| 208 |
+
|
| 209 |
+
# Run
|
| 210 |
+
python inference.py
|
| 211 |
+
```
|
| 212 |
+
|
| 213 |
+
### Expected log format
|
| 214 |
+
|
| 215 |
+
```json
|
| 216 |
+
[START] task=easy env=api_debug_env model=mistralai/Mistral-7B-Instruct-v0.3
|
| 217 |
+
[STEP] step=1 action={"method":"GET","url":"/mock_api/users",...} reward=0.05 done=false error=null
|
| 218 |
+
[STEP] step=2 action={"method":"GET","url":"/mock_api/users","headers":{"Authorization":"Bearer demo_token_123"},...} reward=0.92 done=true error=null
|
| 219 |
+
[END] success=true steps=2 score=0.920 rewards=0.05,0.92
|
| 220 |
+
```
|
| 221 |
+
|
| 222 |
+
---
|
| 223 |
+
|
| 224 |
+
## Project Structure
|
| 225 |
+
|
| 226 |
+
```
|
| 227 |
+
api_debug_env/
|
| 228 |
+
βββ inference.py β Baseline inference script (root, mandatory)
|
| 229 |
+
βββ models.py β APIAction, APIObservation, APIState
|
| 230 |
+
βββ client.py β APIDebugEnv(EnvClient)
|
| 231 |
+
βββ openenv.yaml β Environment manifest
|
| 232 |
+
βββ pyproject.toml β Package config
|
| 233 |
+
βββ Dockerfile β HF Spaces Dockerfile (port 7860)
|
| 234 |
+
βββ tasks/
|
| 235 |
+
β βββ easy.py β 3 easy tasks
|
| 236 |
+
β βββ medium.py β 3 medium tasks
|
| 237 |
+
β βββ hard.py β 3 hard tasks
|
| 238 |
+
β βββ registry.py β TASK_REGISTRY dict
|
| 239 |
+
βββ graders/
|
| 240 |
+
β βββ grader.py β Deterministic reward logic
|
| 241 |
+
βββ server/
|
| 242 |
+
βββ app.py β FastAPI app with create_app()
|
| 243 |
+
βββ api_debug_environment.py β Environment logic
|
| 244 |
+
βββ mock_api.py β Internal mock REST API router
|
| 245 |
+
βββ requirements.txt
|
| 246 |
+
```
|
| 247 |
+
|
| 248 |
+
---
|
| 249 |
+
|
| 250 |
+
## Setup from Source
|
| 251 |
+
|
| 252 |
+
```bash
|
| 253 |
+
git clone https://huggingface.co/spaces/ProthamD/api-debug-env
|
| 254 |
+
cd api-debug-env
|
| 255 |
+
|
| 256 |
+
pip install openenv-core fastapi uvicorn httpx pydantic openai python-dotenv
|
| 257 |
+
|
| 258 |
+
# Windows
|
| 259 |
+
$env:PYTHONPATH = "path\to\api-debug-env"
|
| 260 |
+
|
| 261 |
+
# Linux/Mac
|
| 262 |
+
export PYTHONPATH=$(pwd)
|
| 263 |
+
|
| 264 |
+
uvicorn server.app:app --host 0.0.0.0 --port 7860
|
| 265 |
+
```
|
| 266 |
+
|
| 267 |
+
Test it:
|
| 268 |
+
```bash
|
| 269 |
+
curl http://localhost:7860/health
|
| 270 |
+
curl -X POST http://localhost:7860/reset \
|
| 271 |
+
-H "Content-Type: application/json" \
|
| 272 |
+
-d '{"task_id": "easy"}'
|
| 273 |
+
```
|
| 274 |
+
|
| 275 |
+
---
|
| 276 |
+
|
| 277 |
+
## Environment Variables
|
| 278 |
+
|
| 279 |
+
| Variable | Required | Description |
|
| 280 |
+
|---|---|---|
|
| 281 |
+
| `API_BASE_URL` | Yes | LLM API endpoint e.g. `https://router.huggingface.co/v1` |
|
| 282 |
+
| `MODEL_NAME` | Yes | Model identifier e.g. `mistralai/Mistral-7B-Instruct-v0.3` |
|
| 283 |
+
| `HF_TOKEN` | Yes | HuggingFace token with inference access |
|
| 284 |
+
| `ENV_URL` | No | Override environment URL (default: localhost) |
|
| 285 |
+
|
| 286 |
+
---
|
| 287 |
+
|
| 288 |
+
## Why API Debugging?
|
| 289 |
+
|
| 290 |
+
Debugging broken HTTP requests is one of the most common real-world developer tasks. Every backend developer, DevOps engineer, and API integrator does this daily. Unlike existing OpenEnv environments (games, code execution, financial simulations), there was no environment for this domain.
|
| 291 |
+
|
| 292 |
+
Key advantages of this domain for RL training:
|
| 293 |
+
- **Deterministic grading** β HTTP status codes are binary, no LLM judge needed
|
| 294 |
+
- **Rich partial reward signal** β agent gets meaningful feedback at every step
|
| 295 |
+
- **Stateful multi-turn reasoning** β hard tasks require chaining multiple requests
|
| 296 |
+
- **Real-world transferability** β skills learned here apply directly to production debugging
|
| 297 |
+
|
| 298 |
+
---
|
| 299 |
+
|
| 300 |
+
## License
|
| 301 |
+
|
| 302 |
+
MIT
|
| 303 |
+
|
| 304 |
+
## Author
|
| 305 |
+
|
| 306 |
+
Pratham Dey (ProthamD) β IIEST Shibpur, Information Technology
|