An agent in a loop can hammer an expensive API and spike your bill. You want a hard ceiling on calls per session, not a soft promise in the prompt.
Any tool with per-call cost or upstream rate limits. LLM providers, paid search APIs, third-party integrations via pieces.
Free internal services where rate limiting just adds latency without preventing real harm.
Drop this into an app.yaml. Adjust the credential refs and module names to fit your existing setup.
1schema_version: 223app:4 app_id: rate-limit-with-fallback5 name: "Rate limit with fallback"6 version: "1.0.0"78modules:9 web: {}1011runtime:12 mode: conversation13 entry_agent: helper14 hooks:15 - id: cap_searches_per_session16 "on": tool_start17 condition:18 type: all_of19 conditions:20 - { type: tool_name, match: "web.search" }21 - { type: tool_calls, threshold: 10 }22 action:23 type: gate24 reason: "Session search cap (10 calls) reached. Work with what you already found."2526 - id: warn_at_half27 "on": tool_end28 condition:29 type: all_of30 conditions:31 - { type: tool_name, match: "web.search" }32 - { type: tool_calls, threshold: 5 }33 action:34 type: inject_message35 role: system36 content: "You have used about half your search budget this session. Consolidate."3738agents:39 - id: helper40 modules: [{web: [search, fetch]}]41 brain: { provider: anthropic, model: claude-haiku-4-5, credential: { ref: anthropic_main, scope: per_user, provider: anthropic } }Walking through the YAML one block at a time so the design is clear, not memorised.
Telling the model 'don't make too many calls' fails a meaningful fraction of the time. The runtime hook is deterministic: at the threshold, the next call is gated.
An inject_message hook tells the agent it has used half its budget. Models react to this signal and consolidate their calls.
When the cap fires, the gate action returns a clear reason instead of a raw failure. The agent works with what it already has instead of crashing.
Worst-case tool calls per session are known upfront. You can compute upper bounds for monthly spend without staring at a dashboard.
The pattern above is not the only answer. Here is when something else is the right call.
security.behavior.profile: coding already ships a max_sequential_same_tool rule. Coarser, no per-tool granularity, but zero extra YAML.
Put a proxy in front of the external API that enforces a global rate. Works for many agents at once, doesn't help with single-session cost.
Engineering notes from the Digitorn team. No marketing, no launch announcements, no "10 prompts that will change your life". Just the things we write that we'd want to read.