Prerequisites
Go installed. From the repo root, make build produces bin/fuse (RunHalt server) and bin/mockprovider.
Start
Terminal 1 — mock provider. Terminal 2 — RunHalt pointed at it:
make run-mock
make run-fuse
# → http://127.0.0.1:8080/healthz → ok (503 if store down)
Virtual key
Create a key with a dollar budget. The agent uses this token — not your OpenAI key.
curl -s -X POST http://127.0.0.1:8080/v1/admin/keys \
-H "X-Fuse-Admin-Token: dev-admin" \
-H "Content-Type: application/json" \
-d '{"name":"demo","budget_usd":1.00}'
Halt mid-run
Reuse the same X-Run-Id. Ceilings are enforced before the next provider call. Breach → HTTP 409 run_killed.
TOKEN=sk-rh-…
curl -s http://127.0.0.1:8080/v1/chat/completions \
-H "Authorization: Bearer $TOKEN" \
-H "X-Run-Id: demo-run" \
-H "X-Fuse-Run-Max-Calls: 5" \
-H "Content-Type: application/json" \
-d '{"model":"mock-gpt","stream":false,"messages":[{"role":"user","content":"hi"}]}'
Useful headers (all optional overrides):
X-Fuse-Run-Max-CallsX-Fuse-Run-Max-Cost-UsdX-Fuse-Run-Max-DepthX-Fuse-Run-Max-Duration-Sec— wall-clock since first callX-Fuse-Run-Max-Usd-Per-Min— spend velocity (checked after 30s elapsed)
Abort on 409 / 402
Do not retry 409 run_killed or 402 budget_exhausted. Treat them as hard task failure and stop the agent loop.
# OpenAI Python SDK
from openai import OpenAI, APIStatusError
client = OpenAI(base_url="https://runhalt.com/v1", api_key="sk-rh-…")
try:
client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "hi"}],
extra_headers={
"X-Run-Id": "task-42",
"X-Fuse-Run-Max-Calls": "20",
},
)
except APIStatusError as e:
if e.status_code in (402, 409):
raise SystemExit(f"halted: {e.status_code}") # abort — do not retry
raise
# Agent loop pattern
# if status in (402, 409) or error.type in ("run_killed", "budget_exhausted"):
# break # never continue / never backoff-retry
Dashboard
- Lab — try chat / runaway kill without curl
- Overview — spend, calls, kills, 402s
- Keys — create / disable virtual keys
- Onboarding — paste a provider key (hosted mode)
Open /app. Self-host admin token default: dev-admin.
Real provider
Point RunHalt at OpenAI and set -provider-key. Full checklist: REAL_TEST.md or ./scripts/dogfood.sh openai.
./bin/fuse \
-listen :8080 \
-upstream https://api.openai.com \
-provider-key "$OPENAI_API_KEY" \
-admin-token dev-admin \
-fail-open=false
Then in the agent: OPENAI_BASE_URL=http://127.0.0.1:8080/v1 and OPENAI_API_KEY=sk-rh-….
Hosted
Production: https://runhalt.com · dashboard /app. Env vars still use the FUSE_* prefix for compatibility.