Google ADK Memory: How to Add Persistent Memory to an Agent

Agent FrameworksAI Agent MemoryMaximem Team29 May 20268 min read
Google ADK Memory: How to Add Persistent Memory to an Agent
On this page
  1. Where Google ADK Excels
  2. How Google ADK Memory Works Today
  3. What Synap Adds
  4. Technical Deep Dive
  5. What Synap Adds to Google ADK
  6. What Production Teams Gain
  7. How to Get Started
  8. Memory Is Infrastructure

Google ADK handles memory in layers. A Session holds one conversation and survives a restart only with DatabaseSessionService or VertexAiSessionService. State is key-value data on the session, where a user: prefix shares a value across all of one user's sessions. A MemoryService is the searchable long-term store, scoped by app_name and user_id: InMemoryMemoryService does keyword matching and keeps nothing after a restart, while the persistent options, VertexAiMemoryBankService and VertexAiRagMemoryService, run on Google Cloud. Maximem Synap adds persistent memory as two ADK FunctionTool objects, search_memory and store_memory, with user_id and customer_id fixed in the tool closures so the model never sees them.

For a team that is already on Google Cloud, Memory Bank is the native answer to the question in the title, and it is a good one. A separate memory layer is for memory that has to live outside Google Cloud, or that agents outside ADK have to share.


Where Google ADK Excels

ADK is Google's open-source agent development framework, available in Python, TypeScript, Go, Java and Kotlin. Agents are defined in code with a model, an instruction and tools; plain functions become tools from their signatures and docstrings; and ADK 2.0 adds graph workflows. The quickstart uses Gemini, ADK works with many other models through adapters, and deployment targets include Agent Runtime on Google's Agent Platform, Cloud Run and GKE. If you are building agents that will run on Google Cloud, ADK handles that plumbing well.

One naming note saves confusion later. The ADK docs now say Agent Platform, Agent Runtime and Knowledge Engine where older material said Vertex AI, and the Python classes keep their VertexAi prefix.


How Google ADK Memory Works Today

ADK separates the conversation, the values attached to it, and long-term knowledge. The Google ADK documentation covers each one, and they persist under different conditions.

Session. A session is one conversation thread, identified by app_name, user_id and a session ID. InMemorySessionService loses everything when the application restarts. DatabaseSessionService persists to a SQL database such as PostgreSQL, MySQL or SQLite, and VertexAiSessionService persists through Agent Runtime.

State. State is a scratchpad of key-value pairs, and the key prefix sets the scope. A key with no prefix belongs to the current session, a user: key is shared across all sessions for that user within the app, and an app: key across all users. With a persistent session service, user: state is durable per-user memory for small, explicit values.

MemoryService. This is the searchable store that outlives sessions. You pass a memory_service to the Runner, ingest a finished session with add_session_to_memory, and give the agent the load_memory tool, which it calls when it decides memory would help, or preload_memory, which retrieves at the start of every turn. VertexAiMemoryBankService extracts meaningful information from conversations with an LLM, consolidates it with existing memories and searches semantically. VertexAiRagMemoryService stores full conversations and retrieves them by vector similarity.

The gap is narrower than "ADK has no memory", and it is about where the memory lives. The default InMemoryMemoryService matches keywords and is lost on restart, and both persistent implementations are Google Cloud services. If your agents run on another cloud, if the same user also talks to agents that are not built on ADK, or if you need a tenant level above user_id and entity resolution across identifiers, the long-term layer has to come from somewhere else. ADK allows for that: any BaseMemoryService implementation or any tool can supply it.


What Synap Adds

Synap is agentic context management. It does not replace ADK's sessions or state. It adds persistent per-user memory that the agent calls as tools, hosted independently of where the agent runs.

We ship one factory that produces two FunctionTool objects:

create_synap_tools returns search_memory and store_memory. Drop them into the tools argument of any ADK Agent. The agent decides when to recall context and when to save new facts. search_memory accepts a query and returns Synap's formatted context as text, or a short "no relevant memories" message. store_memory takes content and returns a confirmation with an ingestion ID. Note the name: Synap's search_memory tool is separate from the search_memory method on ADK's own MemoryService.

Scope is embedded in the tool closures, not passed to the model. Supply user_id and optional customer_id when you create the tools. The agent only sees query and content arguments.

A second helper, synap_st_instruction, returns an instruction callable that places Synap's compacted summary and recent turns for a conversation ID above your own instruction text. With the tools alone, memory is written when the model calls store_memory, so say in the instruction what is worth keeping.

We built this because agents on Google Cloud kept stalling in production. The problem was not bad cloud integration. It was missing context that lived in a different session last Tuesday. Production testing hit 92% LongMemEval, 93.2% on LoCoMo. Fast mode retrieves in under 100ms.

For why context management is infrastructure and not a feature, read What Is Agentic Context Management?. For build-versus-buy numbers, see The Real Cost of DIY Agent Memory.


Technical Deep Dive

LongMemEval Benchmark

LongMemEval tests whether agents recall facts across long, multi-turn conversations spanning multiple sessions. The benchmark simulates production conditions where users return days apart and expect the agent to remember prior context. Synap scores 92% on this benchmark. Baseline vector-only approaches typically score 60-70%. The gap comes from entity resolution and temporal awareness that pure vector search lacks.

Entity Resolution Mechanism

Synap tracks identity across 15 reference patterns: names, emails, phone numbers, account IDs, session IDs, device IDs, and more. When an agent encounters "John" in one session and "[email protected]" in another, the resolution engine runs deterministic matching on structured fields, then probabilistic matching on unstructured references. Conflicts are resolved using temporal recency and source confidence scores. The result is a single canonical entity that accumulates context across all identifiers.

Graph Traversal in Accurate Mode

Fast mode retrieves by vector similarity alone. Accurate mode adds a graph layer that traverses relationships between entities. If you ask about "the project John mentioned," the graph finds John, traverses to projects linked to John, and returns the relevant context. This adds latency but catches connections that vector similarity misses. Reranking then scores results by recency, confidence, and query relevance. The tools in this package request accurate mode.

Multi-Tenant Scoping

Synap's scope chain narrows from client to customer to user. user_id identifies the person and customer_id identifies the tenant, so a SaaS deploying agents for multiple customers uses customer_id to ensure tenant A never sees tenant B's memory. On a B2B instance customer_id is required; on a B2C instance it is rejected, because there the user is the whole identity. conversation_id groups turns inside a scope and must be a UUID. This scoping is enforced at the storage layer and not only in application logic.

For the Google ADK integration, scoping lives in the tool closures. Create a fresh tool set, and the Agent that holds it, for each user you serve, so that concurrent users cannot read one another's memories. Set ADK's session user_id and Synap's user_id from the same authenticated identity.


What Synap Adds to Google ADK

Persistence

Google ADK Native. Sessions and state persist with a database or Agent Runtime session service. Long-term memory persists with Memory Bank or the RAG memory service on Google Cloud. With Synap. Per-user memory survives across sessions and restarts, wherever the agent is hosted.


Entity Resolution

Google ADK Native. Memory Bank consolidates new information with existing memories. The ADK memory docs describe no linking of one person's different identifiers. With Synap. "John" and "[email protected]" resolve to one canonical entity across every session.


Compaction

Google ADK Native. Memory Bank extracts and consolidates with an LLM; the RAG service stores full conversations. With Synap. Server-side compaction with configurable levels, delivered to the agent through synap_st_instruction.


Retrieval Latency

Google ADK Native. Depends on the memory service you choose. With Synap. 50 to 100ms fast mode. 200 to 500ms accurate mode.


Long-Term Recall

Google ADK Native. The ADK memory docs give no cross-session recall figure. With Synap. 92% on LongMemEval.


Failure Handling

Google ADK Native. A tool exception goes to on_tool_error_callback when you define one and is raised out of the run when you do not. With Synap. Both tools log the failure once and raise SynapIntegrationError, for reads as well as writes, so a memory outage is never mistaken for an empty memory. Handle it in on_tool_error_callback to keep the agent running.


User Scoping

Google ADK Native. app_name, user_id and session ID, plus state prefixes. With Synap. user_id and customer_id embedded in tool closures. Fresh tool set per user for multi-tenant isolation.


What Production Teams Gain

Cross-session continuity. Your user chats on Monday and returns on Wednesday in a new session. The agent calls search_memory and gets what Synap holds for that user, including what a different agent stored.

Accuracy that ships. 92% LongMemEval, 93.2% on LoCoMo measures whether agents recall facts across long, multi-turn conversations spanning multiple sessions. This benchmark tests the specific failure mode that breaks production agents: accurate recall over distance and time.

Latency that does not block. Fast retrieval: 50 to 100ms. Accurate mode with graph traversal and reranking: 200 to 500ms. A memory call happens only when the model asks for one.


How to Get Started

Three steps. No rearchitecture.

Step 1: Install

pip install maximem-synap-google-adk google-adk

Generate a Synap API key from the Synap Dashboard and set it next to your Gemini key:

SYNAP_API_KEY=synap_your_key_here
GOOGLE_API_KEY=your-gemini-api-key

Step 2: Initialize and wire

import asyncio

from google.adk.agents import Agent from google.adk.runners import Runner from google.adk.sessions import InMemorySessionService from google.genai import types from maximem_synap import MaximemSynapSDK from synap_google_adk import create_synap_tools

async def main(): sdk = MaximemSynapSDK() # reads SYNAP_API_KEY await sdk.initialize()

# Scoped memory tools for this user
memory_tools = create_synap_tools(
    sdk=sdk,
    user_id="user_123",
    customer_id="acme_corp",  # B2B instances only; leave out on B2C
)

agent = Agent(
    name="support_agent",
    model="gemini-flash-latest",
    instruction=(
        "Call search_memory before answering questions about the user. "
        "Call store_memory when the user shares a fact worth keeping."
    ),
    tools=memory_tools,
)

session_service = InMemorySessionService()
runner = Runner(agent=agent, app_name="support", session_service=session_service)
session = await session_service.create_session(app_name="support", user_id="user_123")

message = types.Content(
    role="user",
    parts=[types.Part(text="What do you know about my open tickets?")],
)
async for event in runner.run_async(
    user_id="user_123", session_id=session.id, new_message=message
):
    if event.is_final_response() and event.content:
        print(event.content.parts[0].text)

await sdk.shutdown()

asyncio.run(main())

Step 3: Deploy

For multi-tenant production, construct the tools and the Agent per user, and swap InMemorySessionService for a persistent session service so that the conversation itself survives a restart. Synap handles long-term persistence and retrieval. Your agent handles orchestration.

Full config, scoping rules, and error handling: https://docs.maximem.ai/integrations/google-adk


Memory Is Infrastructure

ADK gave developers a framework with a real memory interface, and on Google Cloud its Memory Bank fills that interface well. Giving an agent memory that is independent of one cloud, shared across frameworks, and resolved to the right person is a different layer of the stack.

Teams either build that layer themselves, or they plug in a system built for it; what the second route buys is an agent that improves with each conversation and users who stop repeating themselves.

Memory is infrastructure, not a feature.

Start building Google ADK agents that remember across sessions → (https://synap.maximem.ai)

Synap pricing is usage-based. You pay for memory operations: storage, retrieval, compaction. No per-seat or per-framework surcharge. The $49/month starter plan includes a base allocation; usage beyond that is metered by operation. Every new account gets $25 in free credits to test before committing. See full pricing at https://synap.maximem.ai/pricing.


Related Posts

From the team at Maximem

Stop rebuilding agent memory from scratch

Maximem Synap is the context management layer we built after hitting every problem in this post ourselves. Persistent recall across sessions, entity resolution and conscious forgetting, in Python, TypeScript and REST.

Related posts

Looking for more to read? See our directory of the best engineering blogs to follow.