555e282cc4
pi-agent-plugin checks / lint (push) Has been cancelled
pi-agent-plugin checks / test (20) (push) Has been cancelled
pi-agent-plugin checks / test (22) (push) Has been cancelled
pi-agent-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / check_changes (push) Has been cancelled
TypeScript SDK CI / changelog_check (push) Has been cancelled
ci / changelog_check (push) Has been cancelled
ci / check_changes (push) Has been cancelled
ci / build_mem0 (3.10) (push) Has been cancelled
ci / build_mem0 (3.11) (push) Has been cancelled
ci / build_mem0 (3.12) (push) Has been cancelled
CLI Node CI / lint (push) Has been cancelled
CLI Node CI / test (20) (push) Has been cancelled
CLI Node CI / test (22) (push) Has been cancelled
CLI Node CI / build (push) Has been cancelled
CLI Python CI / lint (push) Has been cancelled
CLI Python CI / test (3.10) (push) Has been cancelled
CLI Python CI / test (3.11) (push) Has been cancelled
CLI Python CI / test (3.12) (push) Has been cancelled
CLI Python CI / build (push) Has been cancelled
openclaw checks / lint (push) Has been cancelled
openclaw checks / test (20) (push) Has been cancelled
openclaw checks / test (22) (push) Has been cancelled
openclaw checks / build (push) Has been cancelled
opencode-plugin checks / build (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / build_ts_sdk (22) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (20) (push) Has been cancelled
TypeScript SDK CI / integration_ts_sdk (22) (push) Has been cancelled
352 lines
13 KiB
Plaintext
352 lines
13 KiB
Plaintext
---
|
|
title: Google ADK
|
|
description: "Integrate Mem0 with Google Agent Development Kit for persistent memory across multi-agent workflows."
|
|
---
|
|
|
|
Integrate [**Mem0**](https://github.com/mem0ai/mem0) with [Google ADK (Agent Development Kit)](https://github.com/google/adk-python), an open-source framework for building multi-agent workflows. This integration enables agents to access persistent memory across conversations, enhancing context retention and personalization.
|
|
|
|
## Overview
|
|
|
|
In this guide, we'll create a Google ADK agent that:
|
|
1. Uses ADK's native `MemoryService` interface to connect Mem0
|
|
2. Automatically injects relevant memories using ADK's built-in `load_memory` tool
|
|
3. Persists session history to Mem0 after each turn via an after-agent callback
|
|
4. Shares memory seamlessly across multi-agent hierarchies
|
|
|
|
## Setup and Configuration
|
|
|
|
Install the necessary libraries:
|
|
|
|
```bash
|
|
pip install google-adk mem0ai python-dotenv
|
|
```
|
|
|
|
Set up your API keys:
|
|
- <a href="https://app.mem0.ai/dashboard/api-keys?utm_source=oss&utm_medium=integration-google-ai-adk" rel="nofollow">Mem0 API Key</a>
|
|
- Google AI Studio API Key
|
|
|
|
<Note>Remember to get your API key from <a href="https://app.mem0.ai" rel="nofollow">Mem0 Platform</a> and set up a [Google AI Studio API Key](https://aistudio.google.com/apikey).</Note>
|
|
|
|
```python
|
|
import os
|
|
from dotenv import load_dotenv
|
|
|
|
load_dotenv()
|
|
|
|
# os.environ["GOOGLE_API_KEY"] = "your-google-api-key"
|
|
# os.environ["MEM0_API_KEY"] = "your-mem0-api-key"
|
|
```
|
|
|
|
## Implement Mem0MemoryService
|
|
|
|
Create a custom `MemoryService` by implementing ADK's `BaseMemoryService`. Save the following as **`mem0_memory_service.py`**:
|
|
|
|
```python
|
|
import asyncio
|
|
import os
|
|
from typing import Optional
|
|
from typing_extensions import override
|
|
|
|
from google.adk.memory.base_memory_service import BaseMemoryService, SearchMemoryResponse
|
|
from google.adk.memory.memory_entry import MemoryEntry
|
|
from google.adk.sessions import Session
|
|
from google.genai.types import Content, Part
|
|
from mem0 import MemoryClient
|
|
|
|
|
|
class Mem0MemoryService(BaseMemoryService):
|
|
"""MemoryService implementation backed by the Mem0 Platform."""
|
|
|
|
def __init__(self, api_key: Optional[str] = None):
|
|
super().__init__()
|
|
api_key = api_key or os.environ.get("MEM0_API_KEY")
|
|
self._client: Optional[MemoryClient] = MemoryClient(api_key=api_key) if api_key else None
|
|
|
|
@override
|
|
async def search_memory(
|
|
self, *, app_name: str, user_id: str, query: str
|
|
) -> SearchMemoryResponse:
|
|
"""Search for memories relevant to the current user and query."""
|
|
if not self._client:
|
|
return SearchMemoryResponse(memories=[])
|
|
|
|
try:
|
|
results = await asyncio.to_thread(
|
|
self._client.search,
|
|
query,
|
|
filters={"AND": [{"user_id": user_id}, {"app_id": app_name}]},
|
|
top_k=5,
|
|
)
|
|
|
|
entries = []
|
|
for mem in results.get("results", []):
|
|
text = mem.get("memory", "")
|
|
if not text:
|
|
continue
|
|
|
|
raw_ts = mem.get("created_at") or mem.get("updated_at")
|
|
entries.append(
|
|
MemoryEntry(
|
|
content=Content(parts=[Part(text=text)]),
|
|
author=mem.get("metadata", {}).get("author", "user"),
|
|
timestamp=str(raw_ts) if raw_ts else None,
|
|
)
|
|
)
|
|
|
|
return SearchMemoryResponse(memories=entries)
|
|
|
|
except Exception as e:
|
|
print(f"[Mem0MemoryService] search_memory error: {e}")
|
|
return SearchMemoryResponse(memories=[])
|
|
|
|
@override
|
|
async def add_session_to_memory(self, session: Session) -> None:
|
|
"""Persist a completed ADK session into Mem0."""
|
|
if not self._client:
|
|
return
|
|
|
|
user_id = session.user_id
|
|
if not user_id:
|
|
return
|
|
|
|
app_name = getattr(session, "app_name", None)
|
|
|
|
try:
|
|
messages = []
|
|
for event in session.events:
|
|
if not (event.content and event.content.parts):
|
|
continue
|
|
role = getattr(event.content, "role", None) or "user"
|
|
if role == "model":
|
|
role = "assistant"
|
|
elif role not in ("user", "assistant"):
|
|
continue
|
|
text_parts = [
|
|
p.text for p in event.content.parts if hasattr(p, "text") and p.text
|
|
]
|
|
if text_parts:
|
|
messages.append({"role": role, "content": " ".join(text_parts)})
|
|
|
|
if messages:
|
|
metadata = {"app_id": app_name} if app_name else {}
|
|
await asyncio.to_thread(
|
|
self._client.add, messages, user_id=user_id, metadata=metadata
|
|
)
|
|
|
|
except Exception as e:
|
|
print(f"[Mem0MemoryService] add_session_to_memory error: {e}")
|
|
```
|
|
|
|
## Add Auto-Save Callback
|
|
|
|
This after-agent callback fires at the end of every turn and saves the session to Mem0. Save as **`memory_callbacks.py`**:
|
|
|
|
```python
|
|
async def save_session_to_memory(callback_context) -> None:
|
|
"""Persist the completed session to Mem0 after each agent turn."""
|
|
try:
|
|
await callback_context.add_session_to_memory()
|
|
except ValueError:
|
|
pass
|
|
except Exception as e:
|
|
print(f"[save_session_to_memory] error: {e}")
|
|
```
|
|
|
|
## Basic Integration Example
|
|
|
|
The following example demonstrates creating an ADK agent with automatic Mem0 memory:
|
|
|
|
```python
|
|
import asyncio
|
|
from google.adk.agents import LlmAgent
|
|
from google.adk.runners import Runner
|
|
from google.adk.sessions import InMemorySessionService
|
|
from google.adk.tools import load_memory
|
|
from google.genai.types import Content, Part
|
|
|
|
from mem0_memory_service import Mem0MemoryService
|
|
from memory_callbacks import save_session_to_memory
|
|
|
|
memory_service = Mem0MemoryService()
|
|
session_service = InMemorySessionService()
|
|
|
|
agent = LlmAgent(
|
|
name="personal_assistant",
|
|
model="gemini-2.0-flash",
|
|
instruction="""You are a helpful personal assistant.
|
|
Relevant memories from past conversations are provided to you automatically.
|
|
Use them to personalize your responses.""",
|
|
description="A personal assistant that remembers user preferences and past interactions",
|
|
tools=[load_memory],
|
|
after_agent_callback=save_session_to_memory,
|
|
)
|
|
|
|
runner = Runner(
|
|
agent=agent,
|
|
session_service=session_service,
|
|
memory_service=memory_service,
|
|
app_name="memory_assistant",
|
|
)
|
|
|
|
|
|
async def chat(user_input: str, user_id: str) -> str:
|
|
session = await session_service.create_session(
|
|
app_name="memory_assistant",
|
|
user_id=user_id,
|
|
)
|
|
content = Content(role="user", parts=[Part(text=user_input)])
|
|
async for event in runner.run_async(user_id=user_id, session_id=session.id, new_message=content):
|
|
if event.is_final_response() and event.content and event.content.parts:
|
|
return event.content.parts[0].text
|
|
return "No response generated"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print(asyncio.run(chat(
|
|
"I love Italian food and I'm planning a trip to Rome next month",
|
|
user_id="alice",
|
|
)))
|
|
|
|
print(asyncio.run(chat(
|
|
"Any food recommendations for my trip?",
|
|
user_id="alice",
|
|
)))
|
|
```
|
|
|
|
## Multi-Agent Hierarchy with Shared Memory
|
|
|
|
Because `memory_service` is passed to the `Runner`, every agent in the hierarchy shares the same memory automatically. Only the root coordinator needs the auto-save callback: ADK fires it once when the full turn completes:
|
|
|
|
```python
|
|
import asyncio
|
|
from google.adk.agents import LlmAgent
|
|
from google.adk.runners import Runner
|
|
from google.adk.sessions import InMemorySessionService
|
|
from google.adk.tools.agent_tool import AgentTool
|
|
from google.adk.tools import load_memory
|
|
from google.genai.types import Content, Part
|
|
|
|
from mem0_memory_service import Mem0MemoryService
|
|
from memory_callbacks import save_session_to_memory
|
|
|
|
memory_service = Mem0MemoryService()
|
|
session_service = InMemorySessionService()
|
|
|
|
travel_agent = LlmAgent(
|
|
name="travel_specialist",
|
|
model="gemini-2.0-flash",
|
|
instruction="""You are a travel planning specialist.
|
|
Relevant memories about the user's travel preferences are provided automatically.
|
|
Use them to make personalized recommendations.""",
|
|
description="Specialist in travel planning and recommendations",
|
|
tools=[load_memory],
|
|
)
|
|
|
|
health_agent = LlmAgent(
|
|
name="health_advisor",
|
|
model="gemini-2.0-flash",
|
|
instruction="""You are a health and wellness advisor.
|
|
Relevant memories about the user's health goals are provided automatically.
|
|
Use them to give personalized advice.""",
|
|
description="Specialist in health and wellness advice",
|
|
tools=[load_memory],
|
|
)
|
|
|
|
coordinator = LlmAgent(
|
|
name="coordinator",
|
|
model="gemini-2.0-flash",
|
|
instruction="""You are a coordinator that delegates requests to specialist agents.
|
|
For travel-related questions, delegate to the travel specialist.
|
|
For health-related questions, delegate to the health advisor.
|
|
Relevant memories about the user are provided automatically.""",
|
|
description="Coordinates requests between specialist agents",
|
|
tools=[
|
|
load_memory,
|
|
AgentTool(agent=travel_agent, skip_summarization=False),
|
|
AgentTool(agent=health_agent, skip_summarization=False),
|
|
],
|
|
after_agent_callback=save_session_to_memory,
|
|
)
|
|
|
|
runner = Runner(
|
|
agent=coordinator,
|
|
session_service=session_service,
|
|
memory_service=memory_service,
|
|
app_name="specialist_system",
|
|
)
|
|
|
|
|
|
async def chat_with_specialists(user_input: str, user_id: str) -> str:
|
|
session = await session_service.create_session(
|
|
app_name="specialist_system",
|
|
user_id=user_id,
|
|
)
|
|
content = Content(role="user", parts=[Part(text=user_input)])
|
|
async for event in runner.run_async(user_id=user_id, session_id=session.id, new_message=content):
|
|
if event.is_final_response() and event.content and event.content.parts:
|
|
return event.content.parts[0].text
|
|
return "No response generated"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
response = asyncio.run(chat_with_specialists("Plan a healthy meal for my Italy trip", user_id="alice"))
|
|
print(response)
|
|
```
|
|
|
|
## Key Features
|
|
|
|
1. **Automatic Memory Injection**: ADK's built-in `load_memory` tool searches Mem0 at the start of each turn and injects relevant memories directly into the agent context. No prompt instructions are needed.
|
|
2. **Automatic Session Saving**: The `save_session_to_memory` callback persists every completed turn to Mem0 without any manual calls.
|
|
3. **Native ADK Integration**: `Mem0MemoryService` implements ADK's `BaseMemoryService` and integrates via the `Runner`. It works natively across the entire agent hierarchy.
|
|
4. **User Scoping**: `user_id` is passed automatically from the ADK session context, ensuring memories are always scoped to the correct user.
|
|
5. **Multi-Agent Support**: A single `Mem0MemoryService` instance shared through the `Runner` gives all agents, coordinators and specialists, access to the same user memory.
|
|
|
|
## Configuration Options
|
|
|
|
### Using Vertex AI
|
|
|
|
To use Google Cloud Vertex AI instead of AI Studio, set the following environment variables before creating agents:
|
|
|
|
```python
|
|
import os
|
|
os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "True"
|
|
os.environ["GOOGLE_CLOUD_PROJECT"] = "your-project-id"
|
|
os.environ["GOOGLE_CLOUD_LOCATION"] = "us-central1"
|
|
```
|
|
|
|
### Advanced Memory Filtering
|
|
|
|
You can customize how memories are searched by modifying `Mem0MemoryService.search_memory`. For example, to filter by category:
|
|
|
|
```python
|
|
results = await asyncio.to_thread(
|
|
self._client.search,
|
|
query,
|
|
filters={
|
|
"AND": [
|
|
{"user_id": user_id},
|
|
{"app_id": app_name},
|
|
{"categories": {"contains": "travel"}}
|
|
]
|
|
},
|
|
top_k=10,
|
|
)
|
|
```
|
|
|
|
<Note>`InMemorySessionService` stores sessions in memory and is intended for prototyping. For production, use a persistent session service and clean up sessions when they are no longer needed.</Note>
|
|
|
|
## Conclusion
|
|
|
|
By implementing `Mem0MemoryService` as an ADK `BaseMemoryService`, you get persistent, user-scoped memory across single agents and complex multi-agent hierarchies with minimal code. Memory injection and session saving happen automatically, keeping your agent prompts clean and your token usage efficient.
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="Healthcare Agent Cookbook" icon="heart-pulse" href="/cookbooks/integrations/healthcare-google-adk">
|
|
Build HIPAA-compliant healthcare agents with Google ADK
|
|
</Card>
|
|
<Card title="OpenAI Agents SDK" icon="cube" href="/integrations/openai-agents-sdk">
|
|
Compare with OpenAI's agent framework
|
|
</Card>
|
|
</CardGroup>
|
|
|
|
<Snippet file="star-on-github.mdx" />
|