Runtime Brake on AI Agents: Stop Loops & Cut Cost
This guide shows you how to add a runtime brake to an AI agent so it stops looping, caps its own spending, and stays within your budget. You will set a hard time limit, a maximum number of steps, and a cost ceiling—then make the agent check those limits before every action. No special hardware is needed; you only need access to the agent’s code or orchestration layer.
What You’ll Need
- Access to the AI agent’s source code or the orchestration framework it runs on (e.g., LangChain, AutoGen, or a custom Python script).
- An API key or cost-tracking endpoint from your LLM provider (most providers expose usage data per request).
- A way to measure elapsed time (the system clock is fine).
- Basic familiarity with your programming language (examples here use Python).
Step-by-Step
- Define your limits. Decide on three numbers: max runtime in seconds (e.g., 60), max number of agent steps (e.g., 10), and max cost in dollars (e.g., $0.50). Store them as constants or environment variables so you can change them without editing code.
- Initialize a tracking object. At the start of the agent run, create a structure that holds the start time, a step counter, and a running cost total. In Python, this could be a simple dict or a class instance.
- Wrap the agent’s main loop. Find the loop where the agent decides its next action (often a
whileloop). Add a check at the top of each iteration that calls a function likecheck_limits(). That function should returnTrueif any limit is exceeded. - Implement the time check. Inside
check_limits(), computeelapsed = time.time() - start_time. Ifelapsed > max_runtime, returnTrue. - Implement the step counter. Increment a counter at the start of each iteration. If
step_count > max_steps, returnTrue. - Implement the cost check. After each LLM call (or after each step), fetch the usage from the API response (e.g.,
response.usage.total_tokens) and add the cost to your running total. Use your provider’s pricing per token. Iftotal_cost > max_cost, returnTrue. - Break the loop. If
check_limits()returnsTrue, break out of the loop and optionally log a message like “Runtime brake triggered: time limit exceeded.” - Add a fallback output. When the brake triggers, return the best result you have so far (e.g., the last valid response) so the user isn’t left empty-handed, or return a clear error message.
- Test with a dummy loop. Run your agent with a deliberately low limit (e.g., 2 steps) to confirm the brake fires. Then set realistic limits and test again.
- Monitor and adjust. After a few real runs, check your logs to see how often the brake triggers. If it triggers too often, raise the limits slightly; if never, lower them to save cost.
Common Mistakes
- Checking limits only after a step completes. If a single step takes 30 seconds, your time limit of 60 seconds might be exceeded mid-step. Check before the step, but also consider adding a hard timeout on the LLM call itself (e.g., using
timeoutparameter in your HTTP client). - Forgetting to reset the brake between runs. If you reuse the same tracking object across multiple agent runs, the old counters will trigger immediately. Always re-initialize at the start of each run.
- Ignoring token usage for streaming responses. If you stream tokens, the usage may not be in the final response. You may need to sum tokens from chunks or use a separate usage endpoint.
- Hardcoding limits instead of using config. This makes it painful to adjust per environment (dev vs. prod). Use environment variables or a config file.
- Not logging the brake reason. Without a log, you won’t know if you’re hitting the time limit or the cost limit. Log which limit was exceeded.
Tips
- Use a separate thread for a watchdog. For critical applications, run a watchdog thread that force-kills the agent if it exceeds the time limit by a margin (e.g., 10% over). This catches hangs that the main loop can’t.
- Estimate cost before calling. Some providers let you estimate tokens from the prompt length. If the prompt is huge, you can preemptively reject the step.
- Exponential backoff on retries. If your agent retries failed API calls, make sure the retry loop also respects the time and cost limits—otherwise it can blow through your budget in seconds.
- Keep the brake logic separate. Put the limit-checking in its own module or class so you can unit-test it independently of the agent logic.
- Use a budget per step, not just total. Some agents can take one very expensive step. Set a per-step token cap in addition to the total cost cap.
Troubleshooting
- The brake never triggers. Check that you’re calling
check_limits()at the top of the loop, not after the loop. Also verify that your cost calculation is actually summing—print the total cost each iteration to see if it’s increasing. - The brake triggers too early. If your time limit is 60 seconds but the agent finishes in 50, you’re fine. If it triggers at 10 seconds, your
start_timemight be set inside the loop. Move it to before the loop. - Cost is showing zero. Your provider’s API might not include usage in the response by default. Check the docs for a parameter like
stream_options: {"include_usage": true}for streaming, or use a separate usage endpoint. - The agent hangs on a network call. The brake can’t break a blocking call. Add a timeout to your HTTP client (e.g.,
requests.get(..., timeout=10)) so the call raises an exception and the loop can check the brake. - Multiple agents share the same brake. If you run agents in parallel, each needs its own tracking object. Use a context variable or pass the tracker explicitly.
Frequently Asked Questions
Can I set a brake without modifying the agent’s code?
If you’re using an orchestration framework, check if it has built-in callbacks or middleware. For example, LangChain allows a custom callback handler that can raise an exception to stop execution. Otherwise, you need to modify the agent’s code.
What unit should I use for the cost limit?
Use dollars (or your currency) as a float. Calculate cost per request as: (prompt_tokens * prompt_price_per_token) + (completion_tokens * completion_price_per_token). Most providers list prices per 1M tokens, so convert accordingly.
How do I handle the brake when the agent is in the middle of a tool call?
The brake should only interrupt between steps. If a tool call takes too long, you need a separate timeout on the tool execution. Some frameworks let you set a timeout per tool call.
Is it better to use a step limit or a time limit?
Use both. Step limits prevent infinite loops where each step is fast; time limits prevent slow steps from dragging on. Cost limits are the ultimate backstop for API spending.
What should I return when the brake triggers?
Return the last successful result if it’s meaningful, otherwise a clear message like “Agent stopped: exceeded max steps.” This helps the user know the output is incomplete.
Can I make the brake adaptive?
Yes. You can adjust limits based on the task complexity—for example, allow more steps for a complex research task. But start with fixed limits and only add adaptivity after you have data.
Related
Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.