Keep the conversation¶
agent.run("text") creates a State, runs it and throws it away. To look at the run afterwards, or to talk to the
agent again, create the State yourself.
Create and keep a State¶
from alpineagents import Agent, Message, State
agent = Agent(model="claude-sonnet-5", system="You are a helpful assistant.")
state = State(messages=[Message.user("Name three Python web frameworks")])
print(agent.run(state))
print(state.stopped) # why the run ended
print(state.turn) # how many times the model answered
print(state.usage) # tokens and requests
print(state) # one line per history entry
state.add_message(Message.user("Which one is the smallest?"))
print(agent.run(state))
State(messages=[Message.user(...)])is one conversation. Its first message is the task.agent.run(state)runs until the model answers and returns the answer. The State stays yours.- After a run,
state.answeris the answer,state.stoppedsays why the run ended,state.turncounts the model's replies, andstate.usagehas the tokens and the requests. state.add_message(Message.user(...))adds the next message. The last message is now the person's, so the nextagent.run(state)continues the same conversation instead of stopping at once.
print(state) shows what happened, in order, one line for each entry of state.history. An entry is one thing that
happened: a request to the model, a reply, a stop. context_change import records the messages the State started with.
[turn 0] context_change import: 1 messages
[turn 0] run_start: anthropic/claude-sonnet-5
[turn 1] model_request: anthropic/claude-sonnet-5
[turn 1] model_reply: Flask, Django and FastAPI.
[turn 1] stop: stopped by waiting_for_user
done: stopped by waiting_for_user (1 turn)
History is all a State is. messages, turn and answer are computed from it, and every change is a new entry.
Nothing is hidden. See State and history.
A chat¶
A chat is the same two lines in a loop. This is the whole program:
from alpineagents import Agent, Message, State
agent = Agent(model="claude-sonnet-5", system="You are a helpful assistant.")
state = State(messages=[Message.user(input("> "))])
while True:
print(agent.run(state))
state.add_message(Message.user(input("> ")))
The model sees the whole conversation each time. Without the add_message line, run would stop at once, because the
last message would still be the model's own answer. Stop the program with Ctrl+C.
Messages from your code¶
Message.user is a message from the person. Message.notice is a message from your code, such as a test result.
It continues the example above:
state.add_message(Message.notice("The tests failed"))
The model sees it with the prefix [notice], so it can tell your code from the person. A notice added after the
model's answer makes the next run continue, like a user message.
Send an image¶
A user message can carry images after its text:
from alpineagents import Agent, Image, Message, State
agent = Agent(model="claude-sonnet-5")
state = State(messages=[Message.user("What is wrong in this screenshot?", Image.from_path("screen.png"))])
print(agent.run(state))
state.add_message(Message.user("And in this one?", Image.from_path("screen-2.png")))
print(agent.run(state))
Image.from_pathreads an image file.Image(bytes)takes bytes you already have.Message.user("", image)sends an image without text.- Use a model that reads images. Nothing checks that for you, and a server that cannot read images answers with its own error.
Next¶
Ask before a tool runs. To go deeper:
- Save and resume: keep a conversation when the process ends
- Keep the context small: what to do when a conversation gets long
- State and history: every value and every history entry