Set a hard cost cap
A cost cap is the simplest way to make sure an agent can't blow past your budget. It works at two levels:
- Per-workflow — set on a workflow, halts the run when cumulative cost exceeds the cap.
- Per-call — projected cost from the SDK, rejects any single call that would exceed the cap.
Per-workflow
In the dashboard, open the workflow and set the budget. Or via the HTTP API:
curl -X PATCH https://api.nullrun.io/api/v1/orgs/$ORG_ID/workflows/$WORKFLOW_ID \
-H "X-API-Key: *** \
-H "X-Signature: $(compute_hmac)" \
-H "X-Signature-Timestamp: $(date +%s)" \
-H "Content-Type: application/json" \
-d '{"budget_cents": 500}'
Auth uses
X-API-Keyplus an HMAC-SHA256 signature overtimestamp:api_key:body_hash(see the HTTP API reference) and the SDK'sNULLRUN_SECRET_KEY. Bearer session tokens are for dashboard / admin endpoints only.
Then in the SDK:
import nullrun
from nullrun import init, protect
init(api_key="nr_live_...")
with nullrun.workflow("my-workflow"):
@protect
def run(): ...
Cumulative cost > 500¢ → NullRunBudgetError raised on the next
gate call with error_code = "BUDGET_HARD_BLOCKED". For non-budget
policy blocks (tool block, sensitive tool) the generic
NullRunBlockedException is raised with error_code = "TOOL_BLOCKED".
See Errors for the full catalog and the
recommended except pattern.
max_budget_cents == 0 means "no per-key budget configured", not
"block everything" — the gate passes through to the org-level plan
cap. See Budgets → How to set the budget.
Per-call
The SDK does not project per-call cost on its own — the per-call
cap is enforced by the workspace policy on the gateway. When the
policy carries a per-call threshold, the v3 /gate call rejects
any single call whose projected cost would exceed the cap before
the model is invoked (see Budgets → v3 wire contract
for the v3 reservation flow). The SDK raises
NullRunBlockedException with error_code = "BUDGET_HARD_BLOCKED".
If you need to skip the pre-flight check in test environments
only, set NULLRUN_SKIP_BUDGET_CHECK=1. The SDK emits a
RuntimeWarning at import so this can't slip into production —
and BREAKER_ENV=production refuses-to-start the gateway with
that flag set (no escape hatch). See
Configuration → Server-side fail-CLOSED guards.
See also
- Budgets — v3 reservation lifecycle and the
pre-flight
/gateend-to-end - Errors
- Examples → cost cap demo