DEV Community

Mukunda Rao Katta
Mukunda Rao Katta

Posted on

My Hermes agent ran 500 turns and cost $40 before I noticed. Now it can't.

Hermes Agent Challenge Submission: Build With Hermes Agent

This is a submission for the Hermes Agent Challenge.

My Hermes agent had a bug in its stop condition. The exit check evaluated to False every time, so the agent kept going. The tool calls chained. The loop ran. I came back to 500 turns and a $40 bill.

The fix is a hard cap with a warning before the cap hits. That's agent-turn-limit.

One line to add a hard limit

from agent_turn_limit import make_turn_counter, TurnLimitExceeded

counter = make_turn_counter(hard_limit=20)

while True:
    counter.tick()   # raises TurnLimitExceeded at turn 21
    response = client.messages.create(...)
    if is_done(response):
        break
Enter fullscreen mode Exit fullscreen mode

That's the whole integration. One make_turn_counter, one tick() call per iteration. If the loop runs 21 turns, you get an explicit exception instead of a runaway process.

Warnings before the limit

The default warning thresholds are 50% and 80% of hard_limit. At those turns, your callback fires:

import logging
from agent_turn_limit import make_turn_counter, TurnWarning

def warn(w: TurnWarning) -> None:
    logging.warning(w.message)
    # "agent: turn 10/20 (10 remaining)"

counter = make_turn_counter(hard_limit=20, on_warn=warn)
Enter fullscreen mode Exit fullscreen mode

You can set absolute turn numbers or fractions:

# Integer thresholds
counter = make_turn_counter(hard_limit=20, warn_at=[10, 16], on_warn=warn)

# Fraction of hard_limit (same result)
counter = make_turn_counter(hard_limit=20, warn_at=[0.5, 0.8], on_warn=warn)
Enter fullscreen mode Exit fullscreen mode

This is useful in multi-agent systems where "turn 16/20" in a sub-agent should trigger
a summary or escalation before the hard stop.

stop_on_limit=False for graceful handling

If you'd rather check a return value than catch an exception:

from agent_turn_limit import TurnCounter

counter = TurnCounter(hard_limit=20, stop_on_limit=False)

while True:
    if not counter.tick():
        summary = summarize_so_far()
        break
    ...
Enter fullscreen mode Exit fullscreen mode

tick() returns False when the limit is hit. No exception. You handle it however you want.

Context manager form

from agent_turn_limit import TurnCounter, TurnLimitExceeded

try:
    with TurnCounter(hard_limit=10, label="summarizer") as c:
        while True:
            c.tick()
            ...
except TurnLimitExceeded as e:
    print(e)  # "summarizer: hard turn limit of 10 exceeded (turn 11)"
Enter fullscreen mode Exit fullscreen mode

The label parameter makes the error message identify which agent hit the limit when
you have multiple running concurrently.

TurnWarning has the data you need

@dataclass
class TurnWarning:
    turn: int          # current turn number
    hard_limit: int    # the cap you set
    remaining: int     # turns left
    message: str       # human-readable summary
Enter fullscreen mode Exit fullscreen mode

Log it, emit a metric, attach it to a span — it has everything.

What this solves in a Hermes agent

My Hermes research agent runs a supervisor + worker loop. The supervisor dispatches
sub-tasks to workers. Each worker has its own turn counter:

worker_counter = make_turn_counter(
    hard_limit=15,
    warn_at=[0.6, 0.85],
    on_warn=lambda w: supervisor.log(f"worker {worker_id}: {w.message}"),
    label=f"worker-{worker_id}",
)
Enter fullscreen mode Exit fullscreen mode

At 60% (turn 9) the supervisor knows the worker is taking longer than expected. At 85%
(turn 12) it pre-emptively summarizes what the worker has found so far. At turn 16 the
worker is stopped with an exception.

The supervisor handles TurnLimitExceeded, uses the partial summary, and marks the
sub-task as incomplete rather than letting it drain the full token budget on a dead end.

Zero dependencies

Standard library only: dataclasses, typing. No third-party packages.

pip install agent-turn-limit
Enter fullscreen mode Exit fullscreen mode

Repo: https://github.com/MukundaKatta/agent-turn-limit

Top comments (0)