Tool Budget
Use tool-budget to block a request when its top-level max_tokens value is
greater than the configured ceiling for any tool definition listed in that
request. The current policy is a declaration-time guard, not a usage meter.
It does not observe whether the model actually calls a tool, how many tokens a tool invocation consumes, or how much the request costs.
Outcome
| Condition | Verdict | Reason code |
|---|---|---|
| At least one listed tool exceeds its token ceiling | block | tool-budget.exceeded |
| No listed tool exceeds | allow | tool-budget.ok |
The nested policy-result details contain:
{
"exceeded_tools": [
"web_search"
]
}
An allowed chain normally retains final reason ok; inspect the nested
tool-budget.ok result for policy-specific evidence. A block happens before
the upstream call and returns an HTTP 400 policy-violation response.
Prerequisites
- Add
tool-budgetto the effective request chain. - Use exactly the same tool names as the client sends in
request.tools. - Ensure clients send a non-negative integer
max_tokensfield. Other token limit names are not read by this policy. - Use separate Usage, key-budget, rate-limit, or billing controls for actual or cumulative consumption.
Configuration
pack:
name: tool-budget-example-1
version: "1.0.0"
enabled: true
policies:
chain:
- tool-budget
policy:
tool-budget:
budgets:
web_search:
max_tokens: 5000
database_query:
max_tokens: 2000
Supported fields
| Field | Type | Default | Notes |
|---|---|---|---|
budgets | object | {} | Map of tool names to limit objects. |
budgets.<tool>.max_tokens | integer ≥ 1 | — | Enforced against the request's top-level max_tokens. |
budgets.<tool>.max_cost_usd | number ≥ 0 | — | Schema-valid and parsed, but not enforced by this evaluator. |
The linter warns when a budget entry has neither max_tokens nor
max_cost_usd. A max_cost_usd-only entry satisfies that lint check but still
has no runtime effect in this policy.
Exact evaluation
The evaluator:
- Reads top-level
request.max_tokensas an unsigned integer. - Reads every item in top-level
request.tools. - Extracts
tools[*].function.name, falling back totools[*].name. - Looks up each name in
policy.tool-budget.budgets. - Adds the name to
exceeded_toolswhenrequest.max_tokens > budgets.<name>.max_tokens.
The comparison is strict: a request equal to the configured ceiling is allowed.
Request shapes
Both tool-name forms are recognized:
{
"max_tokens": 250,
"tools": [
{
"type": "function",
"function": {
"name": "web_search"
}
},
{
"name": "database_query"
}
]
}
The list is the set of tools made available in the request. It is not a list of tool calls already executed by the model.
Missing and alternate fields
These cases currently evaluate as a zero token request and do not exceed a positive limit:
- missing
max_tokens; - negative, fractional, or string
max_tokens; and - request families that send only
max_completion_tokensormax_output_tokens.
An absent or non-array tools field also yields no checked tools. Unconfigured
tool names are allowed by this policy.
Do not depend on those allow paths as safe defaults. Normalize the client request to the exact supported fields or use another owning control.
Test the blocking contract
Create tests/blocks-search-over-budget.json:
{
"name": "blocks-search-over-budget",
"input": {
"messages": [
{
"role": "user",
"content": "Search the documentation."
}
],
"request": {
"model": "replace-with-model-id",
"max_tokens": 250,
"tools": [
{
"type": "function",
"function": {
"name": "web_search"
}
}
]
}
},
"expected": {
"verdict": "block",
"reason_code": "tool-budget.exceeded"
}
}
With web_search.max_tokens: 100, run:
kt policy lint --file policy-config.yaml
kt policy test --json
Inspect details.policy_results[] and confirm
exceeded_tools: ["web_search"].
Add boundary fixtures for:
max_tokens: 100->allow/ok;max_tokens: 101->block/tool-budget.exceeded;- an unconfigured tool ->
allow/ok; - missing
max_tokens->allow/ok; and - multiple tools where only one exceeds.
What this policy does not provide
- Cumulative session, user, team, agent, or organization counters.
- Actual prompt, completion, or tool-execution token metering.
- Cost estimation or enforcement for
max_cost_usd. - Limits on the number of tool calls.
- Validation of tool arguments, schemas, safety, or authorization.
- Enforcement against tool calls returned later in a model response.
Use tool-validation, tool-security, agent-firewall, token rate limits, and
the product's Usage/budget surfaces for those separate concerns.
Rollout guidance
- Capture the exact
toolsand token-limit shape sent by each client library. - Normalize tool names and casing; budget lookup is an exact map-key match.
- Set limits from the maximum declared completion size you are willing to permit when each tool is available.
- Add equality, one-over-limit, missing-field, and multi-tool fixtures.
- Run a live request and verify the HTTP response plus nested
exceeded_toolsevent details. - Monitor false blocks when applications expose a large tool catalog on every request, even when most tools will not be called.
Troubleshooting
| Symptom | Likely cause | Resolution |
|---|---|---|
| Large request was allowed | The client used max_completion_tokens/max_output_tokens, omitted max_tokens, or sent a non-integer value. | Send supported top-level max_tokens or use a control that owns the alternate request family. |
| Tool was not checked | Its name was absent, nested differently, or did not exactly match a budget key. | Inspect request.tools and align function.name or name. |
| Request blocked although no tool was called | The policy checks tools declared as available, not model-emitted invocations. | Reduce the request tool list or choose a different control for actual calls. |
| Cost-only budget never blocks | max_cost_usd is not enforced here. | Use the product's supported cost-budget/Usage workflow. |
| Equality was expected to block | The evaluator uses > rather than >=. | Set the ceiling one unit lower if that is the intended contract and retest. |
Allowed event has final reason ok | Allow-only nested reasons do not replace the final decision reason. | Inspect the nested result for tool-budget.ok. |
Next steps
- Tool Validation — validate declared tools and schemas
- Tool Security — inspect tool request risk
- Agent Firewall — restrict tool access and actions
- Rate Limits Configuration — govern request/token rates separately
- Policy Controls Catalog — compare adjacent controls