Google ADKgoogle-adk 2.8 · Python 3.10+
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
28 small wins to finish your pathNext lesson →

Memory service: memory across conversations

State carries facts you chose to save, for the conversation that is happening now. Memory is different: it holds finished conversations and lets a later one search them, once you have added them to it.

Two objects make it work, and they are created side by side. A session service holds conversations while they happen, and a memory service holds the finished ones.

A session holds a conversation; memory holds the finished ones
turn 1latereventsadd_session_to_memoryload_memoryCustomerlistenerfirst conversationrecallertool: load_memorySession serviceInMemorySessionServiceMemory serviceInMemoryMemoryService
Hover or tap a piece to see what it is and which lesson built it.
Trace a request

Pick one to watch it run, step by step.

A first conversation

python
listener = LlmAgent(name="listener", model=PretendModel(replies=[say("Noted.")]),
                    instruction="Listen to the customer.")

runner = Runner(agent=listener, app_name="demo",
                session_service=sessions, memory_service=memory)

Runner rather than InMemoryRunner here, because both services are being passed in explicitly. That is the only difference.

Example
first = await sessions.create_session(app_name="demo", user_id="u1")
said = types.Content(role="user", parts=[types.Part(text="I prefer email over phone")])

async for _ in runner.run_async(user_id="u1", session_id=first.id, new_message=said):
    pass

print("the conversation happened, and is still only a session")

Saving it

One call does it. Running the same search either side of that call is what shows you what it changed:

Example
before = await memory.search_memory(app_name="demo", user_id="u1", query="email")
print("searchable before saving:", len(before.memories))

finished = await sessions.get_session(app_name="demo", user_id="u1", session_id=first.id)
await memory.add_session_to_memory(finished)

after = await memory.search_memory(app_name="demo", user_id="u1", query="email")
print("searchable after saving: ", len(after.memories))
print("state on that session:   ", dict(finished.state))

The conversation had already happened, and the search still found nothing, because a session becomes searchable only when you add it. The state on that session is empty too: state is for the conversation that is running, and this one is over. Memory is what is left of it afterwards, and only what you chose to keep.

Nothing is remembered automatically. You decide when a finished conversation is worth keeping, which is the right way round: most are not.

Searching it later

python
recaller = LlmAgent(
    name="recaller",
    model=PretendModel(replies=[call("load_memory", query="email"),
                                say("You told us you prefer email.")]),
    instruction="Use memory when the customer refers to something from before.",
    tools=[load_memory],
)

load_memory is a tool ADK ships. It goes in the tools list like any other, and the model calls it with a query.

Example
later = Runner(agent=recaller, app_name="demo",
               session_service=sessions, memory_service=memory)
second = await sessions.create_session(app_name="demo", user_id="u1")
asked = types.Content(role="user", parts=[types.Part(text="How should we contact you?")])

async for event in later.run_async(user_id="u1", session_id=second.id, new_message=asked):
    for part in (event.content.parts if event.content else []):
        if part.function_response:
            for item in part.function_response.response["result"].memories:
                text = "".join(p.text or "" for p in item.content.parts)
                print("memory found:", item.author, "said", repr(text))
        elif part.text:
            print("answer:      ", part.text.strip())

A new conversation found the old one and answered from it. The memory belongs to the user, so a different customer searching the same words finds nothing.

What the in-memory service does

It matches keywords. Search for a word that appears in the stored conversation and you get a hit; search for a phrase that means the same thing in different words and you get nothing. Fine for learning, and wrong for production, where the managed memory service searches properly.

StateMemory
What it holdsFacts you chose to saveWhole past conversations
How it is readA template, or a tool reading itA search, through load_memory
Written byYour code, deliberatelyYou, when you add a finished session
Good forThe order id, the customer's planWhat was said last month
Which one you need
Most agents need state and never need memory. Reach for memory when the useful thing is what was said, rather than a fact you could have extracted and stored at the time.
Try it yourself
  • Search for a word that is not in the conversation and print the empty result.
  • Store two conversations and search for something in both.

Slow is fine. Stopping is the only problem.