Set an agent's budget
A budget caps each turn of an agent: how many model calls it makes, what they cost, and how long it takes. A turn that runs out fails, and the run says which limit it hit.
// in agents/order-desk/index.ts budget: { maxSteps: 6, maxCostUsd: 0.05, maxWallMs: 60_000 },# in agents/order_desk.py budget={"maxSteps": 6, "maxCostUsd": 0.05, "maxWallMs": 60_000},| Field | Caps | Default |
|---|---|---|
maxSteps |
Model calls in the turn. | 8 |
maxCostUsd |
The turn's model spend, in US dollars. | none |
maxWallMs |
The turn's time, in milliseconds. | 120000 |
A step is one model call. The tool calls the model asks for run between steps, so a turn that looks an order up and then answers takes two. Repairing a typed answer takes a step too.
Cost is what the models' registered prices make of the tokens each call used (see Models); a model registered with a price of zero never uses the cost budget.
When a turn runs out
Section titled “When a turn runs out”Each limit fails the turn with its own error. These are from
kindgi runs start … --verbose on acme.order-desk, with one limit set low at
a time.
Steps. After a model call that asks for more tool calls, with no steps left:
Error [server]: Agent turn steps budget exceeded (limit 1, observed 1){ "code": "server", "serverCode": "budget-exceeded", "message": "Agent turn steps budget exceeded (limit 1, observed 1)", "fields": { "kind": "steps", "limit": 1, "observed": 1, "runId": "32e87e56-e221-489c-be0e-74885038520d" }}Cost. Checked after each model call, against the turn's total so far:
Error [server]: Agent turn cost budget exceeded (limit 0.0005, observed 0.000982){ "code": "server", "serverCode": "budget-exceeded", "message": "Agent turn cost budget exceeded (limit 0.0005, observed 0.000982)", "fields": { "kind": "cost", "limit": 0.0005, "observed": 0.000982, "runId": "c24f58c5-f883-4b82-8091-a48b053e53b7" }}Time. A timer that starts with the turn; when it fires, the model call in flight is cancelled:
Error [server]: Agent turn aborted: Request was aborted.{ "code": "server", "serverCode": "agent-turn-aborted", "message": "Agent turn aborted: Request was aborted.", "fields": { "reason": "timeout", "runId": "2950dd5b-c706-48bd-837f-5329b19c29d4" }}The run is failed, and kindgi runs journal <run-id> shows how far it got.
Leave room for real models: one call to a hosted model takes a second or more, and a model on your own machine can take ten. A turn with a tool call makes two calls.
Handle it in your app
Section titled “Handle it in your app”The failed turn comes back as an error, with the limit in its fields:
import { KindgiApiError, createClient } from '@kindgi/sdk/client';
const kindgi = createClient(); // KINDGI_API_URL, KINDGI_API_TOKEN, or the running kindgi dev
try { await kindgi.runs.start({ agent: 'acme.order-desk', input: { userMessage: 'Where is my order A-1001?' }, });} catch (err) { if (!(err instanceof KindgiApiError)) throw err; const e = err.error; if (e.code === 'server' && e.serverCode === 'budget-exceeded') { console.log(e.fields?.kind, e.fields?.limit, e.fields?.observed, e.fields?.runId); } else { throw err; }}steps 1 1 2cc56724-92e7-42e8-aefd-14ad5c294d1ffrom kindgi.client import Kindgi, KindgiApiError
kindgi = Kindgi() # KINDGI_API_URL, KINDGI_API_TOKEN, or the running kindgi devtry: kindgi.runs.start(agent="acme.order-desk", input={"userMessage": "Where is my order A-1001?"})except KindgiApiError as err: if err.server_code == "budget-exceeded": print(err.details["kind"], err.details["limit"], err.details["observed"], err.details["runId"]) else: raisesteps 1 1 3deffc12-053e-43e3-b735-9a415d95645fA turn that runs out of time has serverCode agent-turn-aborted instead,
with reason timeout.
In a flow
Section titled “In a flow”An agent step whose turn runs out fails, and the flow run fails with it. The run carries the reason:
kindgi runs start --flow=acme.notify-customer --input='{"orderId":"A-1001"}'{ … "flowId": "acme.notify-customer", … "status": "failed", … "failureMessage": "budget-exceeded: Agent turn cost budget exceeded (limit 0.00001, observed 0.00031)", "output": {}, …}Here the step's agent, acme.order-update from
Give an agent its input, had
budget: { maxCostUsd: 0.00001 }.