cd /news/ai-agents/my-hermes-agent-s-stop-condition-was… · home topics ai-agents article
[ARTICLE · art-13865] src=dev.to pub= topic=ai-agents verified=true sentiment=↑ positive

My Hermes agent's stop condition was a 40-line if/elif chain. I replaced it with 3 lines.

A developer replaced a 40-line if/elif chain for stopping a Hermes research agent with a three-line solution using the new `agent-loop-stop` library. The library provides composable stop conditions like `after_n_turns()`, `cost_exceeds()`, and `response_contains()`, which can be combined with operators or functions. The package, which requires only the Python standard library, allows different agents to use named, reusable stop configurations.

read2 min publishedMay 25, 2026

This is a submission for the Hermes Agent Challenge.

My Hermes research agent's stop logic had grown into a 40-line if/elif block. Stop after 20 turns. Stop if cost exceeds $2. Stop if the response contains "FINAL ANSWER". Stop if the last tool called was "write_summary". Each condition was written out longhand, tested independently, and hard to reuse across different agents.

I extracted the pattern into agent-loop-stop

.

from agent_loop_stop import any_of, after_n_turns, cost_exceeds, response_contains

stopper = any_of(
    after_n_turns(20),
    cost_exceeds(2.00),
    response_contains("FINAL ANSWER"),
)

for turn in range(1, 100):
    response = call_llm(messages)
    state = {"turn": turn, "cost_usd": running_cost, "response": response.text}
    if stopper.check(state):
        break

That's it. stopper.check(state)

returns True when any condition fires. The state dict can have whatever you want in it — built-in conditions read well-known keys.

after_n_turns(20)                           # state["turn"] >= 20
cost_exceeds(2.00)                          # state["cost_usd"] > 2.00
response_contains("FINAL ANSWER")          # case-insensitive substring
last_tool_was("write_summary")             # state["last_tool"] == name
custom(lambda s: s.get("retries") > 3)    # any callable
always()                                   # always True (testing)
never()                                    # always False (placeholder)
c = after_n_turns(20) | cost_exceeds(1.00)

c = after_n_turns(10) & cost_exceeds(0.50)

c = ~response_contains("continue")

Or use the function form:

any_of(after_n_turns(20), cost_exceeds(2.00), response_contains("done"))
all_of(after_n_turns(5), cost_exceeds(0.25))
negate(response_contains("error"))

Both styles work identically. The operator form is more concise; the function form is more explicit about what's happening.

from agent_loop_stop import check_all

result = check_all(
    state,
    {
        "turn_limit": after_n_turns(20),
        "cost_limit": cost_exceeds(2.00),
        "done_signal": response_contains("FINAL ANSWER"),
    },
)

if result.stopped:
    log.info(f"Agent stopped. Reason(s): {result.triggered}")

check_all

checks every named condition individually and returns a StopResult

with which ones triggered. This is what I log in my Hermes agent — if I see "turn_limit" fired instead of "done_signal", that means the agent ran out of turns without finishing.

c = custom(lambda s: len(s.get("tool_calls_this_turn", [])) > 5)

Or subclass for reusable predicates:

from agent_loop_stop import StopCondition

class TokenBudgetStop(StopCondition):
    def __init__(self, limit: int):
        self._limit = limit

    def check(self, state):
        return state.get("tokens_used", 0) > self._limit

stopper = any_of(after_n_turns(20), TokenBudgetStop(4000))

Different Hermes agents have different stop requirements:

SUPERVISOR_STOP = any_of(
    after_n_turns(50),
    cost_exceeds(5.00),
    response_contains("SYNTHESIS COMPLETE"),
)

WORKER_STOP = any_of(
    after_n_turns(15),
    cost_exceeds(0.50),
    last_tool_was("submit_findings"),
)

Named, reusable, composable. Each agent gets its own stop config that says exactly what it means.

Standard library only: dataclasses

, typing

. No third-party packages.

pip install agent-loop-stop
── more in #ai-agents 4 stories · sorted by recency
── more on @hermes 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/my-hermes-agent-s-st…] indexed:0 read:2min 2026-05-25 ·