Three prefixes, three lifetimes
A key with no prefix belongs to this conversation. Three prefixes change that, and one of them is how an agent remembers you across conversations.
| Prefix | Scope | Lives as long as |
|---|---|---|
| none | This session | The conversation |
user: | This user, every session in the app | The user, if the service persists |
app: | The whole app, every user | The application |
temp: | This one invocation | The current turn. Then it is gone |
A tool that writes two of them
def remember(name: str, tool_context: ToolContext) -> dict:
"""Remember the customer's name for every future conversation."""
tool_context.state["user:name"] = name
tool_context.state["temp:working"] = "scratch"
return {"status": "success"}One key with the user prefix, one temporary. Everything else about the tool is the same as lesson 21.
agent = LlmAgent(
name="support",
model=PretendModel(replies=[call("remember", name="Asha"), say("Nice to meet you.")]),
instruction="Be friendly.",
tools=[remember],
)
runner = InMemoryRunner(agent=agent, app_name="demo")Watching a prefix cross a session
first = await runner.session_service.create_session(app_name="demo", user_id="u1")
message = types.Content(role="user", parts=[types.Part(text="I am Asha")])
async for _ in runner.run_async(user_id="u1", session_id=first.id, new_message=message):
pass
done = await runner.session_service.get_session(
app_name="demo", user_id="u1", session_id=first.id)
print("first session: ", dict(done.state))The user key is there, and temp:working is not. Temporary means the current invocation only, and that one has finished.
second = await runner.session_service.create_session(app_name="demo", user_id="u1")
print("second session:", dict(second.state))
other = await runner.session_service.create_session(app_name="demo", user_id="u2")
print("another user: ", dict(other.state))A brand new conversation for the same person already knows the name. A different person does not. That is the whole point of the prefix.
Where the persistence actually comes from
The prefixes describe scope. Whether anything survives a restart is a property of the session service. InMemorySessionService keeps user and app state across sessions, as you just saw, and loses everything when the process ends.
- Learning and tests: in memory, which is what
InMemoryRunnergives you. - A real deployment: a database session service, so a restart does not wipe conversations.
- On Google Cloud: the managed service, which persists for you.
user: prefix, because it will still be there in a year.- Change
user:nameto a plain key and watch the second session start empty. - Write to an
app:key and read it from another user's session.
You understood something today that you didn't yesterday.