This quickstart will guide you through building a Google ADK agent with automatic memory, tool tracking, and query augmentation - all with just a few lines of code.
Prerequisites
Set Up Ryumem Server
First, you need a running Ryumem server. See Setup Guide for Docker Compose or local installation. Quick start with Docker: git clone https://github.com/predictable-labs/ryumem.git
cd ryumem
cp server/.env.example server/.env
# Add your GOOGLE_API_KEY to server/.env
docker-compose up -d
Get Your API Key
Register to get your Ryumem API key: curl -X POST "http://localhost:8000/register" \
-H "Content-Type: application/json" \
-d '{"customer_id": "my_project"}'
Save the API key from the response (starts with ryu_).
Install Dependencies for Google ADK
pip install ryumem google-adk python-dotenv
Set Environment Variables
Create a .env file in your project: GOOGLE_API_KEY = your_google_api_key
Building Your First Agent With Google ADK
Let’s build a weather assistant that remembers conversations and automatically tracks what it does.
First, define some simple tools for our agent:
from google.adk.tools import FunctionTool
def get_weather_report ( city : str ) -> dict :
"""Get the current weather for a specified city."""
if city.lower() == "london" :
return {
"status" : "success" ,
"report" : "Cloudy with 18°C and chance of rain."
}
elif city.lower() == "paris" :
return {
"status" : "success" ,
"report" : "Sunny with 25°C."
}
else :
return {
"status" : "error" ,
"error_message" : f "Weather info for ' { city } ' not available."
}
def analyze_sentiment ( text : str ) -> dict :
"""Analyze the sentiment of text."""
if "good" in text.lower() or "sunny" in text.lower():
return { "sentiment" : "positive" , "confidence" : 0.8 }
elif "rain" in text.lower() or "bad" in text.lower():
return { "sentiment" : "negative" , "confidence" : 0.7 }
else :
return { "sentiment" : "neutral" , "confidence" : 0.6 }
# Wrap as ADK tools
weather_tool = FunctionTool( func = get_weather_report)
sentiment_tool = FunctionTool( func = analyze_sentiment)
2. Create the Agent with Memory
Now create your agent and add memory with ONE line:
import os
from dotenv import load_dotenv
from google.adk.agents import Agent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from ryumem import Ryumem
from ryumem.integrations import add_memory_to_agent, wrap_runner_with_tracking
# Load environment variables
load_dotenv()
# Create the agent
agent = Agent(
model = "gemini-2.0-flash-exp" ,
name = "weather_assistant" ,
instruction = """You are a helpful assistant that provides weather information
and analyzes sentiment. Use get_weather_report for weather queries and
analyze_sentiment for feedback.""" ,
tools = [weather_tool, sentiment_tool]
)
# ⭐ Add memory in ONE line!
ryumem = Ryumem(
server_url = "http://localhost:8000" ,
api_key = "ryu_your_api_key_here"
)
memory = add_memory_to_agent(
agent,
ryumem_instance = ryumem,
track_tools = True , # Automatically track all tool calls
)
The agent now has 3 additional memory tools that it can use automatically: search_memory(), save_memory(), and get_entity_context().
3. Enable Query Tracking & Augmentation
Wrap your runner to automatically track queries and augment them with history:
import asyncio
from google.genai import types
async def main ():
# Setup session
session_service = InMemorySessionService()
await session_service.create_session(
app_name = "weather_app" ,
user_id = "user_123" ,
session_id = "session_456"
)
# Create runner
runner = Runner(
agent = agent,
app_name = "weather_app" ,
session_service = session_service
)
# ⭐ Wrap for automatic query tracking and augmentation!
runner = wrap_runner_with_tracking(
runner,
memory,
augment_queries = True , # Enable query augmentation
similarity_threshold = 0.3 , # Match queries with 30%+ similarity
top_k_similar = 5 # Use top 5 similar queries for context
)
# Run queries
queries = [
"What's the weather in London?" ,
"That sounds nice!" ,
"How about Paris?"
]
for query in queries:
print ( f " \n 👤 User: { query } " )
content = types.Content(
role = 'user' ,
parts = [types.Part( text = query)]
)
# Run the agent - everything tracked automatically!
events = runner.run(
user_id = "user_123" ,
session_id = "session_456" ,
new_message = content
)
# Get response
for event in events:
if event.is_final_response():
response = event.content.parts[ 0 ].text
print ( f "🤖 Agent: { response } " )
# Run it!
if __name__ == "__main__" :
asyncio.run(main())
4. Run Your Agent
Save the code as my_first_agent.py and run:
You should see output like:
👤 User: What's the weather in London?
🤖 Agent: The weather in London is currently cloudy with a temperature
of 18 degrees Celsius and there's a chance of rain.
👤 User: That sounds nice!
🤖 Agent: I'm glad you think so! The weather seems pleasant despite the
chance of rain.
👤 User: How about Paris?
🤖 Agent: The weather in Paris is sunny with a temperature of 25 degrees
Celsius. Much warmer and sunnier than London!
What Just Happened?
Behind the scenes, Ryumem:
Tracked all tool executions - Every call to get_weather_report() and analyze_sentiment() was logged
Stored user queries - All three questions were saved as episodes
Augmented queries - Later queries got context from earlier similar ones
Linked everything hierarchically - Queries are linked to their tool executions
What’s Next?
Full Example Code See the complete annotated example
Google ADK Integration Learn all the integration features
Core Concepts Understand how Ryumem works
Query Augmentation Deep dive into query augmentation
Full Code
Here’s the complete working example:
import os
import asyncio
from dotenv import load_dotenv
from google.adk.agents import Agent
from google.adk.tools import FunctionTool
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
from ryumem import Ryumem
from ryumem.integrations import add_memory_to_agent, wrap_runner_with_tracking
load_dotenv()
# Define tools
def get_weather_report ( city : str ) -> dict :
if city.lower() == "london" :
return { "status" : "success" , "report" : "Cloudy with 18°C" }
elif city.lower() == "paris" :
return { "status" : "success" , "report" : "Sunny with 25°C" }
return { "status" : "error" , "error_message" : f "No data for { city } " }
def analyze_sentiment ( text : str ) -> dict :
if "good" in text.lower() or "sunny" in text.lower():
return { "sentiment" : "positive" , "confidence" : 0.8 }
elif "rain" in text.lower():
return { "sentiment" : "negative" , "confidence" : 0.7 }
return { "sentiment" : "neutral" , "confidence" : 0.6 }
weather_tool = FunctionTool( func = get_weather_report)
sentiment_tool = FunctionTool( func = analyze_sentiment)
# Create agent
agent = Agent(
model = "gemini-2.0-flash-exp" ,
name = "weather_assistant" ,
instruction = "You provide weather info and analyze sentiment." ,
tools = [weather_tool, sentiment_tool]
)
# Add memory
ryumem = Ryumem(
server_url = "http://localhost:8000" ,
api_key = "ryu_your_api_key_here"
)
memory = add_memory_to_agent(
agent,
ryumem_instance = ryumem,
track_tools = True ,
)
async def main ():
session_service = InMemorySessionService()
await session_service.create_session(
app_name = "weather_app" ,
user_id = "user_123" ,
session_id = "session_456"
)
runner = Runner(
agent = agent,
app_name = "weather_app" ,
session_service = session_service
)
runner = wrap_runner_with_tracking(
runner,
memory,
augment_queries = True ,
similarity_threshold = 0.3 ,
top_k_similar = 5
)
queries = [
"What's the weather in London?" ,
"That sounds nice!" ,
"How about Paris?"
]
for query in queries:
print ( f " \n 👤 User: { query } " )
content = types.Content( role = 'user' , parts = [types.Part( text = query)])
events = runner.run( user_id = "user_123" , session_id = "session_456" , new_message = content)
for event in events:
if event.is_final_response():
print ( f "🤖 Agent: { event.content.parts[ 0 ].text } " )
if __name__ == "__main__" :
asyncio.run(main())
This complete example is available in the repository as examples/simple_tool_tracking_demo.py.
Visualizing Results in Dashboard
All the queries, tool executions, and memories from your agent are automatically visible in the Ryumem dashboard:
Chat & Query : Search and explore the knowledge graph
Episodes : View all stored memories and conversations
Tool Analytics : See tool execution statistics and patterns
Queries : Track query history and augmentation
Dashboard Guide Learn how to navigate and use all dashboard features