-
Notifications
You must be signed in to change notification settings - Fork 17
Add OpenMemory service integration for ADK community #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b0a4a3b
1c31107
29dbe6b
5d6cbc4
203736f
662e3f0
15b3086
4c8bb47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| # OpenMemory Sample | ||
|
|
||
| This sample demonstrates how to use OpenMemory as a self-hosted memory backend | ||
| for ADK agents using the community package. | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - Python 3.9+ (Python 3.11+ recommended) | ||
| - Docker (for running OpenMemory) | ||
| - ADK and ADK Community installed | ||
|
|
||
| ## Setup | ||
|
|
||
| ### 1. Install Dependencies | ||
|
|
||
| ```bash | ||
| pip install google-adk google-adk-community | ||
| ``` | ||
|
|
||
| ### 2. Set Up OpenMemory Server | ||
|
|
||
| Follow the [OpenMemory Quick Start Guide](https://openmemory.cavira.app/docs/quick-start) to install and configure your OpenMemory server. | ||
|
|
||
| Once OpenMemory is running, you'll need: | ||
| - The OpenMemory server URL (default: `http://localhost:8080`) | ||
| - An API key for authentication by setting OM_API_KEY=<your-secret-api-key> (configured in your OpenMemory server) | ||
|
|
||
| ### 3. Configure Environment Variables for adk | ||
|
|
||
| Create a `.env` file in this directory : | ||
|
|
||
| ```bash | ||
| # Required: Google API key for the agent | ||
| GOOGLE_API_KEY=your-google-api-key | ||
|
|
||
| # Required: OpenMemory API key for authentication | ||
| OPENMEMORY_API_KEY=your-openmemory-api-key | ||
|
|
||
| # Optional: OpenMemory base URL (defaults to http://localhost:8080) | ||
| OPENMEMORY_BASE_URL=http://localhost:8080 | ||
| ``` | ||
|
|
||
| **Note:** `OPENMEMORY_API_KEY` is required for OpenMemory authentication. | ||
|
|
||
| ## Usage | ||
|
|
||
| The sample provides an agent definition that you can use programmatically. The agent includes memory tools and auto-save functionality. | ||
|
|
||
| ```python | ||
| from google.adk_community.memory import OpenMemoryService, OpenMemoryServiceConfig | ||
| from google.adk.runners import Runner | ||
|
|
||
| # Create OpenMemory service with API key (required) | ||
| memory_service = OpenMemoryService( | ||
| base_url="http://localhost:8080", # Adjust to match your OpenMemory server URL | ||
| api_key="your-api-key" # Required - get this from your OpenMemory server configuration | ||
| ) | ||
|
|
||
| # Use with runner | ||
| runner = Runner( | ||
| app_name="my_app", | ||
| agent=root_agent, | ||
| memory_service=memory_service | ||
| ) | ||
| ``` | ||
|
|
||
| ### Advanced Configuration | ||
|
|
||
| ```python | ||
| from google.adk_community.memory import OpenMemoryService, OpenMemoryServiceConfig | ||
|
|
||
| # Custom configuration | ||
| config = OpenMemoryServiceConfig( | ||
| search_top_k=20, # Retrieve more memories per query | ||
| timeout=10.0, # Faster timeout for production | ||
| user_content_salience=0.9, # Higher importance for user messages | ||
| model_content_salience=0.75, # Medium importance for model responses | ||
| enable_metadata_tags=True # Add tags (session, app, author) for filtering | ||
| # When enabled, memories are tagged with session ID, app name, | ||
| # and author, allowing search queries to filter by app name | ||
| ) | ||
|
|
||
| memory_service = OpenMemoryService( | ||
| base_url="http://localhost:8080", # Adjust to match your OpenMemory server URL | ||
| api_key="your-api-key", # Required - get this from your OpenMemory server configuration | ||
| config=config | ||
| ) | ||
| ``` | ||
|
|
||
| ## Sample Agent | ||
|
|
||
| The sample agent (`agent.py`) includes: | ||
| - Memory tools (`load_memory_tool`, `preload_memory_tool`) for retrieving past conversations | ||
| - Auto-save callback that saves sessions to memory after each agent turn | ||
| - Time context for the agent to use current time in responses | ||
|
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you provide one sample query or script to show case how this agent works with memory?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. addressed. |
||
| ## Sample Query | ||
| - hello my name is Amy and i love gaming | ||
| - I really love fps games like GameA and GameB, but my favourite is GameC. my favourite snack is doritos. | ||
|
|
||
| Then in a new session | ||
| - tell me everything you know about me | ||
| (Agent recalled prior details ( my name, love for gaming and mentioned games ,snacks etc)) | ||
|
|
||
| ## Configuration Options | ||
|
|
||
| ### OpenMemoryServiceConfig | ||
|
|
||
| - `search_top_k` (int, default: 10): Maximum memories to retrieve per search | ||
| - `timeout` (float, default: 30.0): HTTP request timeout in seconds | ||
| - `user_content_salience` (float, default: 0.8): Importance for user messages | ||
| - `model_content_salience` (float, default: 0.7): Importance for model responses | ||
| - `default_salience` (float, default: 0.6): Fallback importance value | ||
| - `enable_metadata_tags` (bool, default: True): Include tags for filtering. When enabled, | ||
| memories are tagged with `session:{session_id}`, `app:{app_name}`, and `author:{author}`. | ||
| These tags are used to filter search results by app name, improving isolation between | ||
| different applications using the same OpenMemory instance. | ||
|
|
||
| ## Features | ||
|
|
||
| OpenMemory provides: | ||
|
|
||
| - **Multi-sector embeddings**: Factual, emotional, temporal, relational memory | ||
| - **Graceful decay curves**: Automatic reinforcement keeps relevant context sharp | ||
| - **Self-hosted**: Full data ownership, no vendor lock-in | ||
| - **High performance**: 2-3× faster than hosted alternatives | ||
| - **Cost-effective**: 6-10× cheaper than SaaS memory APIs | ||
|
|
||
| ## Learn More | ||
|
|
||
| - [OpenMemory Documentation](https://openmemory.cavira.app/) | ||
| - [OpenMemory API Reference](https://openmemory.cavira.app/docs/api/add-memory) | ||
| - [ADK Memory Documentation](https://google.github.io/adk-docs) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| from . import agent | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
|
|
||
| from datetime import datetime | ||
|
|
||
| from google.adk import Agent | ||
| from google.adk.agents.callback_context import CallbackContext | ||
| from google.adk.tools.load_memory_tool import load_memory_tool | ||
| from google.adk.tools.preload_memory_tool import preload_memory_tool | ||
|
|
||
|
|
||
| def update_current_time(callback_context: CallbackContext): | ||
| callback_context.state['_time'] = datetime.now().isoformat() | ||
|
|
||
|
|
||
| async def auto_save_session_to_memory_callback(callback_context: CallbackContext): | ||
| """Auto-saves the current session to memory after each agent turn. | ||
|
|
||
| Since there's no automatic save (saves only happen when the PATCH /memory endpoint | ||
| is called), this callback is a simple workaround for testing that saves memories | ||
| after each agent turn. | ||
| """ | ||
| if callback_context._invocation_context.memory_service: | ||
| await callback_context._invocation_context.memory_service.add_session_to_memory( | ||
| callback_context._invocation_context.session) | ||
rakshith-git marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
|
|
||
| root_agent = Agent( | ||
| model='gemini-2.5-flash', | ||
| name='open_memory_agent', | ||
| description='agent that has access to memory tools with OpenMemory.', | ||
| before_agent_callback=update_current_time, | ||
| after_agent_callback=auto_save_session_to_memory_callback, | ||
| instruction=( | ||
| 'You are an agent that helps user answer questions. You have access to memory tools.\n' | ||
| 'You can use the memory tools to look up the information in the memory. Current time: {_time}' | ||
| ), | ||
| tools=[load_memory_tool, preload_memory_tool], | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| # Copyright 2025 Google LLC | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| """Community memory services for ADK.""" | ||
|
|
||
| from .open_memory_service import OpenMemoryService | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's do lazy loading here. @wuliang229 to help provide some guidance on what's the proper way.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's do it in a separate PR. |
||
| from .open_memory_service import OpenMemoryServiceConfig | ||
|
|
||
| __all__ = [ | ||
| "OpenMemoryService", | ||
| "OpenMemoryServiceConfig", | ||
| ] | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.