State¶
A State holds one task: its history, its context and its answer. Create one per task:
from alpineagents import State
state = State("Find the bug in main.py")
The task becomes the first message the model sees. A State can go through several runs, for example one per message in a chat.
history and context¶
A State keeps two lists.
history |
context |
|
|---|---|---|
| Contains | Everything that happened | The messages the model sees at the next think |
| Can shrink | No. Entries are only added | Yes, by compaction, clear_tool_results and start_from |
| Use it to | Inspect, log or debug | Know what the model knows right now |
After compaction, for example, the context holds only the task and a summary. The history still holds every message, reply and tool result.
Read the result¶
| Property | Value |
|---|---|
answer |
The value given to finish(answer). Otherwise the text of the latest reply without tool calls. Otherwise None |
stopped_by |
Why the last loop stopped: "finish", "limit", or the name of an until function. None while running or after an exception |
turn |
How many times think succeeded |
usage |
Tokens, requests and cost of every model request on this State |
Read the inside¶
| Property | Value |
|---|---|
task |
The task the State was created with |
pending_calls |
Tool calls the model asked for that have no result yet |
context |
See above |
history |
See above. HistoryEntry.kind values are listed in the Data types API |
data |
A dict for your own values. The model never sees it |
The size of the context is in Context size. Every property is in the State API.
Check the run¶
| Method | True when |
|---|---|
is_answered() |
The last message in the context is a model reply without tool calls |
wants_tools() |
pending_calls is not empty |
is_finished() |
finish() was called |
These take only the State, so they work as stop conditions: until=State.is_answered.
Add a message¶
| Method | Adds |
|---|---|
add_user_message(text) |
A message from the person |
add_notice(text) |
A message from your code. The model sees it with the prefix [notice] |
A message added after the model's answer makes is_answered() false, so the loop continues. The guide
Check the work before finishing uses this.
Control the run¶
| Method | Effect |
|---|---|
deny(call, reason) |
Refuses one pending call. The model gets reason as that call's error result |
finish(answer=None) |
Stops the loop before the next turn. Sets answer if it is not None |
finish ends the State for good. After it, think, use_tools, ask and run raise ValueError. If a tool calls
finish, end the loop body without another think.
Shrink the context¶
clear_tool_results and start_from shrink the context without a model request. See
Context size.
Pending calls¶
When a reply asks for tools, each call becomes a pending call in state.pending_calls. A call stops being pending
when:
use_toolsrecords its result,denyrefuses it, or- an exception ends the run and closes it.
Every tool call needs a result before the model is asked again. So while calls are pending:
| Method | Behavior |
|---|---|
think, compact, start_from, clear_tool_results |
Raise ValueError |
add_user_message, add_notice |
Wait, and go into the context right after the results |
finish, deny |
Work as usual |
Your own data¶
state.data is a dict for your code and your tools. Use it to keep values across turns:
allowed = state.data.setdefault("allowed", set())
A single read or write is thread-safe. For an update in several steps, hold state.lock:
with state.lock:
state.data["calls"] = state.data.get("calls", 0) + 1
Run the same State again¶
agent.run(state) continues a State that already ran. Use the same Agent: another Agent, including one made with
agent.copy(...), raises ValueError.
| The State | What run does |
|---|---|
Stopped by an until function |
Stops at once if the function is still true. To continue a conversation, add a message with add_user_message first. See Chat |
Stopped by limit |
Runs up to limit more turns. The loop counts turns from zero on every call |
| Stopped by Ctrl+C or an exception | Continues. Pending calls were closed with a result such as (interrupted by user) |
Ended with finish() |
Raises ValueError |