Standard library only · runs in your browser
The most expensive agent bug is the one that never errors: the model calls the same tool with the same arguments forever, and every call succeeds. Add the two guardrails every production agent has, repeat-call detection and a context budget.
The starter is the stage-5 loop. Add:
Loop detection. For every successfully parsed tool call, build a signature: the tool name followed by json.dumps(arguments, sort_keys=True). If this call's signature equals the previous two calls' signatures (three identical in a row), don't run it. Return with "stop_reason": "loop_detected" and "steps": step. The repeated call isn't added to tools_called.
Token budget. At the start of each step, before calling the model, compute context_tokens = sum(count_tokens(m["content"]) for m in messages). If max_tokens is set and context_tokens > max_tokens, return with "stop_reason": "token_budget" and "steps": step - 1 (the model calls actually made).
Every returned dict also gets "context_tokens", the sum over messages at the moment you return. Defaults change to max_steps=8.
run_agent(task, script, max_steps=8, max_consecutive_errors=3, max_tokens=None) -> dict