State: the agent's scratchpad
State is a dictionary that belongs to the conversation. Tools write to it, instructions read from it, and it survives every turn of the session.
You have used it three times already without it being the subject: a tool wrote to it in lesson 10, an instruction template read it in lesson 12, and a sequence passed work through it in lesson 17.
A tool that writes two keys
def note_issue(kind: str, tool_context: ToolContext) -> dict:
"""Record what kind of problem the customer has."""
tool_context.state["issue"] = kind
tool_context.state["handled"] = False
return {"status": "success"}Plain dictionary assignment. There is no save call, because the runner writes the change out when it handles the event.
agent = LlmAgent(
name="support",
model=PretendModel(replies=[call("note_issue", kind="billing"),
say("Let me look into that.")]),
instruction="Help the customer.",
tools=[note_issue],
)Seeding a session, then reading it back
runner = InMemoryRunner(agent=agent, app_name="demo")
session = await runner.session_service.create_session(
app_name="demo", user_id="u1", state={"channel": "chat"})
message = types.Content(role="user", parts=[types.Part(text="I was charged twice")])A session can start with state already in it, which is how you pass in what your program knows before the conversation begins.
async for _ in runner.run_async(user_id="u1", session_id=session.id, new_message=message):
pass
done = await runner.session_service.get_session(
app_name="demo", user_id="u1", session_id=session.id)
print("state:", dict(done.state))One key you gave it, two the tool added. That is the whole model: a dictionary you can seed, write to from code, and read from instructions.
| Good | Bad |
|---|---|
| Facts about this conversation: the order id, the issue type | Anything that cannot be serialised, like a database connection |
| Small results a later step needs | Large blobs. Everything here is saved on every event |
| Flags: whether you already asked something | Secrets you would not want written to a database |
The documentation is explicit about serialisation: keys are strings and values must be basic types the session service can save and load. Store an identifier, not the object.
- Seed a session with a customer name and read it in the instruction with a template.
- Try to store a set or a custom object and see what happens.
Little by little, you're building something great.