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(
api_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 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(
api_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