feat(memory): SQL-backed DatabaseMemoryService with scratchpad for durable agent memory
- Langage dominant
- Python
- Étoiles
- 21.5k
- Forks
- 4k
- Merge moyen
- 1 j 14 h
- PR mergées (30 j)
- 37
Description
## Summary
The ADK currently ships only `InMemoryMemoryService` (volatile, keyword-only, test-only) and cloud-specific Vertex AI services. There is no durable, self-hosted memory option for production deployments that do not use Vertex AI.
## Problem
Developers running ADK agents on-premise or against non-Google cloud providers have no way to persist agent memory across process restarts without writing their own implementation from scratch.
## Proposed Solution
Add `DatabaseMemoryService` — a `BaseMemoryService` implementation backed by any SQLAlchemy-supported async database (SQLite, PostgreSQL, MySQL, MariaDB, Spanner via the existing SQLAlchemy adapter).
### Core features
- **Durable memory** — events and direct `MemoryEntry` writes are stored in a SQL table (`adk_memory_entries`) that survives process restarts
- **Idempotent session ingest** — `add_session_to_memory` is safe to call multiple times (DELETE + re-INSERT)
- **Delta ingest** — `add_events_to_memory` skips already-stored `event_id`s
- **Pluggable search** — `MemorySearchBackend` ABC allows swapping in FTS or vector-embedding backends; ships with `KeywordSearchBackend` (LIKE/ILIKE, AND-first → OR-fallback)
- **Scratchpad** — a KV store (`adk_scratchpad_kv`) and append-only log (`adk_scratchpad_log`) for intermediate working memory during task execution, exposed as four `BaseTool` subclasses agents can call directly
### Zero-config for SQLite
```python
from google.adk.memory import DatabaseMemoryService
svc = DatabaseMemoryService("sqlite+aiosqlite:///:memory:") # tests / local dev
svc = DatabaseMemoryService("postgresql+asyncpg://user:pass@host/db") # production
```
### New public API surface
| Symbol | Module |
|--------|--------|
| `DatabaseMemoryService` | `google.adk.memory` |
| `MemorySearchBackend` | `google.adk.memory` |
| `KeywordSearchBackend` | `google.adk.memory` |
| `scratchpad_get_tool` | `google.adk.tools.scratchpad_tool` |
| `scratchpad_set_tool` | `google.adk.tools.scratchpad_tool` |
| `scratchpad_append_log_tool` | `google.adk.tools.scratchpad_tool` |
| `scratchpad_get_log_tool` | `google.adk.tools.scratchpad_tool` |
## Test coverage
38 unit tests using `sqlite+aiosqlite:///:memory:` (no external DB required):
- All `BaseMemoryService` methods
- Scratchpad KV and log operations
- All 4 tool happy-paths and wrong-service error paths
- Multi-user isolation and session scoping
## Files changed
```
src/google/adk/memory/schemas/__init__.py (new)
src/google/adk/memory/schemas/memory_schema.py (new)
src/google/adk/memory/memory_search_backend.py (new)
src/google/adk/memory/database_memory_service.py (new)
src/google/adk/tools/scratchpad_tool.py (new)
src/google/adk/memory/__init__.py (modified — adds exports)
tests/unittests/memory/test_database_memory_service.py (new)
```
## Related
Complements the existing `DatabaseSessionService` which follows the same SQLAlchemy async pattern.
Guide de contribution
Ouvrir le guide de contribution
Évaluation
Cette issue n'a pas encore été évaluée.