DEV Community

Mohammed Rafay
Mohammed Rafay

Posted on Originally published at memorysync.hashnode.dev

How to add memory to a Google ADK agent that survives restarts (MemoryService, preload_memory, per-user recall)

Disclosure: I'm Mohammed, founder of MemorySync. I drafted this with AI assistance and checked it against Google's ADK docs and MemorySync's ADK guide. Code status: on Oct 25, 2026 I installed google-adk 2.13.0 and google-adk-memorysync 1.1.0 (Python 3.13) and ran all imports and the agent, Runner, context tool, callbacks and tools construction shown. I then ran the whole flow locally with a stand-in model and MemorySync's HTTP responses mocked: one turn, add_session_to_memory, a second ingest of the same session, and a turn in a fresh Runner and session that used preload_memory. Later the same day I reran the flow against the live MemorySync API (no live Gemini call; stand-in model).

In Google's Agent Development Kit (ADK), a Session holds the events and state of one conversation. The ADK docs call that short-term memory. Recalling things from earlier conversations is the job of a separate MemoryService (ADK memory docs). If your agent forgets a user every time you restart or open a new session, this is the layer to fix.

What ADK gives you

BaseMemoryService has four operations:

  • add_session_to_memory(session): ingest a completed session.
  • add_events_to_memory(...): append a delta, such as the latest turn.
  • add_memory(...): add explicit MemoryEntry objects.
  • search_memory(...): query, usually through a tool.

The docs note that add_events_to_memory and add_memory are optional and not every service implements them. Python ADK ships three services:

Service Persistence (per ADK docs)
InMemoryMemoryService None: data is lost on restart
VertexAiMemoryBankService Yes, managed by Google's Agent Platform
VertexAiRagMemoryService Yes, stored in Knowledge Engine

Agents read memory through ADK's built-in tools. load_memory lets the model decide when to search, and preload_memory injects results before the turn.

So your options are: stay in-memory (fine for dev), adopt Vertex AI's services, or implement BaseMemoryService against another backend.

Plugging in a third-party MemoryService

MemorySync publishes google-adk-memorysync, which implements all four BaseMemoryService methods (guide). It requires google-adk 2.0+ and Python 3.10+. Set MEMORYSYNC_API_KEY server-side.

pip install "google-adk>=2" google-adk-memorysync
Enter fullscreen mode Exit fullscreen mode

Step 1: Wire the service into the Runner

from google.adk.agents import LlmAgent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.adk.tools import preload_memory
from google_adk_memorysync import MemorySyncMemoryService

memory_service = MemorySyncMemoryService()  # reads MEMORYSYNC_API_KEY

agent = LlmAgent(
    name="assistant",
    model="gemini-2.5-flash",   # any model your ADK setup supports
    instruction="You are a helpful assistant.",
    tools=[preload_memory],     # ADK's own tool, backed by the service
)

runner = Runner(
    agent=agent,
    app_name="support",
    session_service=InMemorySessionService(),
    memory_service=memory_service,
)
Enter fullscreen mode Exit fullscreen mode

This construction ran on the box.

Step 2: Ingest the session when a conversation ends

session = await runner.session_service.get_session(
    app_name="support", user_id="customer-7", session_id="thread-42"
)
await memory_service.add_session_to_memory(session)
Enter fullscreen mode Exit fullscreen mode

Per the guide, this sends the text messages the user wrote for fact extraction. Agent replies, partial streams and tool traffic are skipped. It raises on failure. Re-ingesting the same session doesn't extract anything twice, because each message carries a seed derived from its ADK event id. The next session for customer-7, in any process, has preload_memory inject what's known.

In my local run (stand-in model, mocked API), the ingest sent only the user's message, the second ingest sent the same event-id-based seed again, and the stored fact appeared in the model's input on a new session in a fresh Runner. In a later run against the live MemorySync API, ingesting the same session a second time returned already_exists: true and nothing was extracted twice, and a fresh Runner and session got the stored fact injected.

The ADK user_id is your isolation key. Use your real, stable user id. By default a user's memory follows them across ADK apps. Pass MemorySyncMemoryService(scope_to_app=True) to keep each app_name separate.

Step 3 (alternative): Inject and capture every turn

If you don't want to manage the end-of-session ingest:

from google_adk_memorysync import MemorySyncContextTool

agent = LlmAgent(
    name="assistant",
    model="gemini-2.5-flash",
    instruction="You are a helpful assistant.",
    tools=[MemorySyncContextTool()],   # recall before each turn + save the user's message
)
Enter fullscreen mode Exit fullscreen mode

In a local run with a stand-in model and a mocked API, a stored fact reached the model's input and the user's message was the only thing written.

Use one capture path, not both. If you call add_session_to_memory, set MemorySyncContextTool(persist=False) and don't use the capture callback, so each message is sent once (the guide explains that the two paths use different seed schemes).

Optional: memory tools for the model

create_memorysync_tools(user_id="customer-7") returns five tools: add, search, list, update and delete. On the box it returned 5 tools. Pass read_only=True for untrusted agents (that returned 2 on the box).

Common questions

Why does my ADK agent forget everything after a restart? You're on InMemoryMemoryService (or no memory service at all). Its data lives in process memory, so ADK's docs say it is lost on restart.

load_memory or preload_memory? load_memory leaves recall to the model. preload_memory injects results before the turn. If recall must happen every turn, use injection.

Is there a TypeScript version? ADK has TypeScript, Go, Java and Kotlin SDKs. MemorySync's ADK package is Python only, and its docs point TypeScript users to its Vercel AI SDK or Mastra integrations.

Can I use two memory services? ADK's docs include an example of using two memory services. Check the "Can an agent have access to more than one memory service?" section.

See a fact survive a full page reload in the browser first: try MemorySync. No signup is needed.

Sources

Top comments (0)