Stop conditions¶
A loop stops in one of three ways. Pick the one that matches who decides.
| Who decides | How | state.stopped_by |
|---|---|---|
| A check on the State, before every turn | An until function |
The function's name |
| Your code or a tool, at a specific moment | state.finish(answer) |
"finish" |
| A fixed maximum number of turns | limit |
"limit" |
Stop on a check¶
from alpineagents import Agent, State, loop
def spent_too_much(state: State) -> bool:
return state.usage.output_tokens > 20_000
@loop(until=[State.is_answered, spent_too_much], limit=30)
def careful(agent: Agent, state: State):
agent.think(state)
if state.wants_tools():
agent.use_tools(state)
spent_too_muchtakes the State and returnsTrueto stop.untiltakes a list. The loop stops when any function in it returnsTrue.- After the run,
state.stopped_byis"is_answered","spent_too_much"or"limit". The terminal output shows the same name.
Give stop conditions clear names. The name is the only record of why the run stopped.
Stop from a tool¶
Let the model decide when the work is done, and return a structured answer:
from alpineagents import Agent, State, tool
@tool
def submit(summary: str, files_changed: list[str], state: State) -> None:
"""Submit the finished work. Call it once, at the end."""
state.finish({"summary": summary, "files_changed": files_changed})
agent = Agent(
model="claude-sonnet-5",
system="When the work is done, call submit.",
tools=[submit],
)
print(agent.run("Rename the helper functions in utils.py"))
- The model calls
submitwhen it thinks the work is done. state.finish(...)setsstate.answerto the dict. The loop stops before the next turn.agent.runreturns the dict.- The State is now finished. Running it again or calling
askon it raisesValueError.
The answer can be any value. The model fills the tool's typed parameters, so the answer has a known shape.
Check for the limit¶
Reaching limit stops the loop without an exception. Check it when an unfinished run matters. agent is the Agent
from the example above:
from alpineagents import State
state = State("Rename the helper functions in utils.py")
agent.run(state)
if state.stopped_by == "limit":
print(f"Stopped after {state.stopped_limit} turns. The task may be unfinished.")
Related¶
- Loops: the order of the checks
- Tools that use the State