Budgets
Run budgets
Attach a spend cap to a named job or pipeline run. The run budget persists in the database across server restarts, making it reliable for long-running batch jobs and agent workflows.
What is a run?
A run is any logical unit of work you want to cap independently: a nightly ETL job, a document-processing pipeline, a single agent session, a one-off analysis. You identify it with a run_id string of your choice.
Every call tagged with the same run_id counts toward that run's budget. When the budget is exhausted, the run status changes to exhausted and all further calls with that run ID are blocked (HTTP 402).
Using run budgets
Send two headers on each call that belongs to the run:
| Header | Required | Description |
|---|---|---|
X-Zelyx-Run-Id | Yes | A unique string identifying this run. Any value you choose. |
X-Zelyx-Run-Budget-USD | First call only | The total spend cap for this run. Set once — later calls with the same run ID ignore this header. |
import uuid
from datetime import date
# Generate a stable run ID — same ID across retries to share one budget
run_id = f"nightly-summary-{date.today().isoformat()}"
for document in documents:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": f"Summarise: {document}"}],
extra_headers={
"X-Zelyx-Run-Id": run_id,
"X-Zelyx-Run-Budget-USD": "10.00", # $10 for the whole batch
},
)nightly-summary-2026-06-04). Each day gets its own $10 budget. Retries and restarts within the same day all count toward the same budget, preventing double spend.Run lifecycle
| Status | Meaning |
|---|---|
| active | Run has remaining budget. Calls proceed normally (subject to other budget checks). |
| exhausted | Budget fully consumed. All calls with this run ID are blocked with HTTP 402. |
View active and recent runs on the Run Budgets dashboard page, which shows spend progress, call count, and current status for each run.
Handling exhaustion in your code
import httpx
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": doc}],
extra_headers={
"X-Zelyx-Run-Id": run_id,
"X-Zelyx-Run-Budget-USD": "10.00",
},
)
except httpx.HTTPStatusError as e:
if e.response.status_code == 402:
# Run budget exhausted — stop processing, notify operator
print(f"Run {run_id} budget exhausted. Stopping.")
breakBudget alert on exhaustion
When a run budget is exhausted, Zelyx fires a run_exhausted alert to all configured channels. Set up a Slack or webhook channel to be notified the moment a run hits its cap (see Alert setup).
Differences from session limits
| Run budget | Session limit | |
|---|---|---|
| Storage | Database (persists across restarts) | In-memory (lost on restart) |
| Set via | X-Zelyx-Run-Budget-USD header | X-Zelyx-Session-Limit-USD header |
| Resets | Never (exhausted permanently until a new run ID is used) | Never (in-memory only) |
| Best for | Batch jobs, pipelines, agent runs | Interactive user sessions |