Skip to content

[DO NOT MERGE] GoodMem chat plugin for ADK#1

Closed
forrestbao wants to merge 18 commits intomainfrom
plugin
Closed

[DO NOT MERGE] GoodMem chat plugin for ADK#1
forrestbao wants to merge 18 commits intomainfrom
plugin

Conversation

@forrestbao
Copy link
Collaborator

@forrestbao forrestbao commented Jan 22, 2026

PLEASE DO NOT MERGE THIS PR. This PR is for GoodMem team to clearly see what files are changed/added. Later, we will create a formal PR and submitted to google's adk-python-community repo.

GOODMEM TEAM: Please make changes in the plugin branch.

Add GoodmemChatPlugin for persistent conversation memory using Goodmem.ai
service. The plugin automatically logs user messages and LLM responses,
retrieves relevant historical context, and augments prompts with memory.

Features:

  • Auto-logging of text messages and file attachments to Goodmem spaces
  • Context retrieval using semantic search with configurable top-k
  • Per-user memory isolation with automatic space management
  • Comprehensive error handling and debug mode
  • Support for binary attachments (PDFs, images, etc.)

File structure:

.
├── src/google/adk_community/
│   ├── __init__.py                      (modified: added plugins import)
│   └── plugins/
│       ├── __init__.py                   (modified: updated imports to use goodmem submodule)
│       └── goodmem/
│           ├── __init__.py               (new: module exports)
│           ├── goodmem_client.py         (new: 274 lines, HTTP client for Goodmem API)
│           └── goodmem.py                (new: 593 lines, plugin implementation)
│
├── tests/unittests/
│   └── plugins/
│       ├── __init__.py                   (new: test module)
│       └── test_goodmem.py               (new: 31 unit tests, 712 lines)
│
└── contributing/samples/goodmem/
    ├── README.md                         (new: overview of Goodmem integrations)
    ├── PLUGIN.md                         (new: detailed plugin documentation)
    └── goodmem_plugin_demo/
        └── agent.py                      (new: sample agent with plugin)

Test coverage: 31/31 tests passing (100%)

  • 8 tests for GoodmemClient (API operations)
  • 23 tests for GoodmemChatPlugin (lifecycle, callbacks, error handling)

Related: Follows patterns from OpenMemory (PR google#36) and Redis Sessions (PR google#32)

forrestbao and others added 5 commits January 21, 2026 15:53
Add GoodmemChatPlugin for persistent conversation memory using Goodmem.ai
service. The plugin automatically logs user messages and LLM responses,
retrieves relevant historical context, and augments prompts with memory.

Features:
- Auto-logging of text messages and file attachments to Goodmem spaces
- Context retrieval using semantic search with configurable top-k
- Per-user memory isolation with automatic space management
- Comprehensive error handling and debug mode
- Support for binary attachments (PDFs, images, etc.)

File structure:
.
├── src/google/adk_community/
│   ├── __init__.py                      (modified: added plugins import)
│   └── plugins/
│       ├── __init__.py                  (new: module exports)
│       └── goodmem.py                   (new: 736 lines, plugin implementation)
│
├── tests/unittests/
│   └── plugins/
│       ├── __init__.py                  (new: test module)
│       └── test_goodmem.py              (new: 31 unit tests, 725 lines)
│
├── contributing/samples/goodmem/
│   ├── README.md                        (new: overview and setup guide)
│   ├── PLUGIN.md                        (new: detailed plugin documentation)
│   └── agent.py                         (new: sample agent with plugin)
│
└── pyproject.toml                       (modified: added requests dependency)

Test coverage: 31/31 tests passing (100%)
- 8 tests for GoodmemClient (API operations)
- 23 tests for GoodmemChatPlugin (lifecycle, callbacks, error handling)

Related: Follows patterns from OpenMemory (PR google#36) and Redis Sessions (PR google#32)
@forrestbao forrestbao requested a review from amin3141 January 24, 2026 03:18
forrestbao and others added 5 commits January 23, 2026 22:36
- Create goodmem_client.py with GoodmemClient class
- Update goodmem.py to import GoodmemClient from goodmem_client
- Export GoodmemClient from plugins/__init__.py
- Makes GoodmemClient reusable for both plugin and tool implementations
Move goodmem.py and goodmem_client.py into plugins/goodmem/ subdirectory
and update all imports throughout the codebase. Replaced old goodmem_client.py
with the version from tools branch. All unit tests pass (31/31).

.
├── src/google/adk_community/
│   ├── __init__.py                      (modified: added plugins import)
│   └── plugins/
│       ├── __init__.py                   (modified: updated imports to use goodmem submodule)
│       └── goodmem/
│           ├── __init__.py               (new: module exports)
│           ├── goodmem_client.py          (replaced: from tools branch, 274 lines)
│           └── goodmem.py                (moved: from plugins/ to plugins/goodmem/, 593 lines)
│
├── tests/unittests/
│   └── plugins/
│       └── test_goodmem.py               (modified: updated imports and patch paths, 31 tests)
│
├── contributing/samples/goodmem/
│   ├── PLUGIN.md                         (modified: removed GoodmemClient section, added file tree)
│   └── goodmem_plugin_demo/
│       └── agent.py                      (restored: was deleted in c8a1642 by bashareid, now restored)

Legend: (M) = Modified, (A) = Added, (R) = Moved/Replaced
Critical fixes:
- Fix cross-user data leakage in after_model_callback by calling _ensure_chat_space()
- Replace assert statements with ValueError for python -O compatibility

Major fixes:
- Remove conflicting prompt rules (do not mention memory vs mention goodmem.ai)
- Fix memory block order inconsistency (now consistently appends context)
- Fix typo "memmory" -> "memory"

Medium fixes:
- Guard against empty contents list IndexError in _extract_user_content
- Fix numeric fields sent as strings in create_space (1.0, 512, 64)
- Fix debug mode behavioral difference (early return now outside debug block)

Minor fixes:
- Fix base_url documentation (should exclude /v1 suffix)

Tests added:
- test_multi_user_isolation: Verifies no cross-user data leakage
- test_debug_mode_empty_retrieval_consistency: Ensures debug doesn't alter behavior
- test_concurrent_user_race_condition: Simulates async race condition

Tests updated:
- Update validation error expectations (AssertionError -> ValueError)
- Update empty chunks behavior (early return, no memory injection)
- Update after_model_callback to verify _ensure_chat_space is called

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Critical Security Fixes:
- Eliminate cross-user data leakage by removing shared instance state
  (self.space_id and self._user_space_cache)
- Implement _get_space_id() using session state for per-request isolation
- All callbacks now use local variables instead of shared instance state

Major Bug Fixes:
- Remove conflicting prompt rules about memory attribution
- Fix memory block order inconsistency (now consistently appends)
- Fix debug mode behavioral difference with empty retrieval
- Remove typo "memmory" in prompt text
- Fix base_url documentation (should not include /v1 suffix)

Medium Priority Fixes:
- Replace assert statements with ValueError for python -O compatibility
- Guard against empty contents list in _extract_user_content()
- Change numeric fields from strings to proper types (int/float)
- Ensure after_model_callback calls _get_space_id() before logging

Performance Improvements:
- Implement multipart/form-data upload for binary files
- Remove base64 encoding overhead (33% size reduction)
- Support files up to ~1GB instead of ~750MB limit
- Strip trailing slash from base_url to prevent double-slash URLs

Code Quality:
- Replace Any type hints with proper ADK types (InvocationContext,
  CallbackContext, LlmRequest, LlmResponse, types.Content)
- Add debug messages with pretty-printed JSON (2-space indent)
- Fix deprecated datetime.utcfromtimestamp() to use timezone-aware version

Tests:
- Update all tests to work with session state instead of instance cache
- Update binary upload test to verify multipart format
- Fix async mock in concurrent race condition test
- All 34 tests passing

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@forrestbao
Copy link
Collaborator Author

This one is ready to be submit to Google.
I extensively talked with AI to find other places to fix/improve. For some, I left untouched because either we don't have a good solution yet or it is unlikely to happen. They are listed as "known limitation" in Readme:

## Known limitations
1. Backend enforces max 10,000 characters on query message. But the plugin doesn't validate this and will silently pass the rejection from Goodmem. 
2. Backend has a binary file size limit of 1GB. But the plugin doesn't validate this and will silently pass the rejection from Goodmem. 
3. Backend enforces max 50 metadata keys. But the plugin doesn't validate this and will silently pass the rejection from Goodmem. 
4. No rate limit handling. Backend returns HTTP 429 with Retry-After header. The plugin will silently ignore it. 
5. The plugin does not check whether ingesting the memory is finished -- ingestion takes a while. It will silently ignore if it eventually fails. 

Amin Ahmad and others added 4 commits January 27, 2026 11:23
- Rewrite PLUGIN.md for better structure: add callback flow section,
  reorganize prerequisites, expand limitations with specific values
- Fix incorrect docstring (ValueError not AssertionError)
- Document stdout side effect in goodmem_client
- Clarify README.md branch locations
@forrestbao
Copy link
Collaborator Author

Close this branch as we are using tools_and_plugin to submit to Google.

@forrestbao forrestbao closed this Jan 29, 2026
@forrestbao forrestbao deleted the plugin branch January 29, 2026 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants