Token Budget & Cost Limits¶
Import: from selectools import AgentConfig Stability: beta
from selectools import Agent, AgentConfig, LocalProvider, tool
@tool(description="Count words in text")
def word_count(text: str) -> str:
return f"Word count: {len(text.split())}"
agent = Agent(
tools=[word_count],
provider=LocalProvider(),
config=AgentConfig(
max_total_tokens=50000,
max_cost_usd=0.25,
),
)
result = agent.run("Count words in 'hello world'")
print(result.content)
See Also
- Cancellation -- cooperative agent stopping
- Token Estimation -- pre-run token and cost estimates
- Usage & Cost Tracking -- actual token counts after execution
Added in: v0.17.3 File: src/selectools/agent/config.py, src/selectools/agent/core.py
Overview¶
The budget system prevents runaway costs by enforcing hard limits on token usage and dollar spend per agent run. When a limit is hit, the agent stops gracefully and returns a partial result.
Quick Start¶
from selectools import Agent, AgentConfig
config = AgentConfig(
max_total_tokens=50000, # stop after 50k cumulative tokens
max_cost_usd=0.20, # stop after $0.20 cumulative cost
max_iterations=12, # existing iteration limit still applies
)
agent = Agent(tools=[...], provider=provider, config=config)
result = agent.run("Analyze this dataset")
# Check if budget was the reason for stopping
if "budget exceeded" in result.content.lower():
print(f"Stopped early — used {result.usage.total_tokens} tokens, ${result.usage.total_cost_usd:.4f}")
How It Works¶
The budget check runs at the start of each iteration, after the previous iteration's tokens have been counted. If cumulative usage exceeds either limit:
- A
BUDGET_EXCEEDEDtrace step is recorded - The
on_budget_exceededobserver event fires - The agent returns an
AgentResultwith partial content from completed iterations
Iteration 1: 15,000 tokens → total: 15,000 (under 50,000) ✓
Iteration 2: 20,000 tokens → total: 35,000 (under 50,000) ✓
Iteration 3: budget check → 35,000 < 50,000 → continue
18,000 tokens → total: 53,000
Iteration 4: budget check → 53,000 ≥ 50,000 → STOP
Configuration¶
| Field | Type | Default | Description |
|---|---|---|---|
max_total_tokens | Optional[int] | None | Cumulative token limit. None = no limit. |
max_cost_usd | Optional[float] | None | Cumulative cost limit in USD. None = no limit. |
Both fields are None by default, preserving backward compatibility.
Observer Event¶
from selectools import AgentObserver
class MyObserver(AgentObserver):
def on_budget_exceeded(self, run_id: str, reason: str, tokens_used: int, cost_used: float):
log.warning(f"Budget exceeded: {reason} (tokens={tokens_used}, cost=${cost_used:.4f})")
Trace Step¶
Budget stops are recorded as StepType.BUDGET_EXCEEDED in the execution trace:
for step in result.trace.steps:
if step.type == "budget_exceeded":
print(step.summary) # "Token budget exceeded: 53000/50000 tokens"
Interaction with Other Limits¶
If both max_iterations and max_total_tokens are set, whichever limit is hit first wins. Budget is checked before the LLM call, so no tokens are wasted on a call that would exceed the budget.
See Also¶
- Usage & Cost Tracking — per-call and per-run token/cost tracking
- Agent —
AgentConfigreference
Related Examples¶
| # | Script | Description |
|---|---|---|
| 05 | 05_cost_tracking.py | Token and cost tracking per run |
| 43 | 43_token_budget.py | Token budget enforcement demo |
| 47 | 47_token_estimation.py | Pre-run token estimation |