zep-adk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zep_adk-0.1.0/.gitignore +101 -0
- zep_adk-0.1.0/CHANGELOG.md +13 -0
- zep_adk-0.1.0/Makefile +72 -0
- zep_adk-0.1.0/PKG-INFO +242 -0
- zep_adk-0.1.0/README.md +221 -0
- zep_adk-0.1.0/examples/basic_agent.py +153 -0
- zep_adk-0.1.0/pyproject.toml +88 -0
- zep_adk-0.1.0/src/zep_adk/__init__.py +74 -0
- zep_adk-0.1.0/src/zep_adk/callbacks.py +111 -0
- zep_adk-0.1.0/src/zep_adk/context_tool.py +421 -0
- zep_adk-0.1.0/src/zep_adk/exceptions.py +12 -0
- zep_adk-0.1.0/src/zep_adk/graph_search_tool.py +301 -0
- zep_adk-0.1.0/tests/test_basic.py +1500 -0
- zep_adk-0.1.0/tests/test_integration.py +458 -0
zep_adk-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# If you prefer the allow list template instead of the deny list, see community template:
|
|
2
|
+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
|
3
|
+
#
|
|
4
|
+
# Binaries for programs and plugins
|
|
5
|
+
out/
|
|
6
|
+
*.exe
|
|
7
|
+
*.exe~
|
|
8
|
+
*.dll
|
|
9
|
+
*.so
|
|
10
|
+
*.dylib
|
|
11
|
+
|
|
12
|
+
# Secrets
|
|
13
|
+
.env
|
|
14
|
+
.env.local
|
|
15
|
+
|
|
16
|
+
# Test data
|
|
17
|
+
test_data
|
|
18
|
+
|
|
19
|
+
# Test binary, built with `go test -c`
|
|
20
|
+
*.test
|
|
21
|
+
|
|
22
|
+
# Output of the go coverage tool, specifically when used with LiteIDE
|
|
23
|
+
*.out
|
|
24
|
+
|
|
25
|
+
# Dependency directories (remove the comment below to include it)
|
|
26
|
+
# vendor/
|
|
27
|
+
|
|
28
|
+
# Go workspace file
|
|
29
|
+
.idea
|
|
30
|
+
.vscode
|
|
31
|
+
|
|
32
|
+
# VSCode local history
|
|
33
|
+
.history
|
|
34
|
+
|
|
35
|
+
# Python
|
|
36
|
+
__pycache__/
|
|
37
|
+
*.py[cod]
|
|
38
|
+
*$py.class
|
|
39
|
+
*.so
|
|
40
|
+
.Python
|
|
41
|
+
build/
|
|
42
|
+
develop-eggs/
|
|
43
|
+
dist/
|
|
44
|
+
downloads/
|
|
45
|
+
eggs/
|
|
46
|
+
.eggs/
|
|
47
|
+
lib/**/*.py
|
|
48
|
+
lib/**/*.pyc
|
|
49
|
+
lib/**/__pycache__/
|
|
50
|
+
lib/**/site-packages/
|
|
51
|
+
lib64/
|
|
52
|
+
parts/
|
|
53
|
+
sdist/
|
|
54
|
+
var/
|
|
55
|
+
wheels/
|
|
56
|
+
share/python-wheels/
|
|
57
|
+
*.egg-info/
|
|
58
|
+
.installed.cfg
|
|
59
|
+
*.egg
|
|
60
|
+
MANIFEST
|
|
61
|
+
|
|
62
|
+
# Virtual environments
|
|
63
|
+
venv/
|
|
64
|
+
env/
|
|
65
|
+
ENV/
|
|
66
|
+
env.bak/
|
|
67
|
+
venv.bak/
|
|
68
|
+
.venv/
|
|
69
|
+
|
|
70
|
+
# PyCharm
|
|
71
|
+
.idea/
|
|
72
|
+
|
|
73
|
+
# Jupyter Notebook
|
|
74
|
+
.ipynb_checkpoints
|
|
75
|
+
|
|
76
|
+
# pyenv
|
|
77
|
+
.python-version
|
|
78
|
+
|
|
79
|
+
# pytest
|
|
80
|
+
.pytest_cache/
|
|
81
|
+
.coverage
|
|
82
|
+
|
|
83
|
+
# mypy
|
|
84
|
+
.mypy_cache/
|
|
85
|
+
.dmypy.json
|
|
86
|
+
dmypy.json
|
|
87
|
+
|
|
88
|
+
# UV (Python package manager)
|
|
89
|
+
uv.lock
|
|
90
|
+
.uv_cache/
|
|
91
|
+
__pypackages__/
|
|
92
|
+
|
|
93
|
+
# Log files
|
|
94
|
+
*.log
|
|
95
|
+
|
|
96
|
+
# macOS
|
|
97
|
+
.DS_Store
|
|
98
|
+
|
|
99
|
+
# Node.js
|
|
100
|
+
node_modules/
|
|
101
|
+
dist/
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-03-23)
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- `ZepContextTool` -- ADK `BaseTool` subclass that persists user messages to Zep and injects memory context into LLM prompts via `process_llm_request()`.
|
|
8
|
+
- `create_after_model_callback` -- Factory function that returns an `after_model_callback` for persisting assistant responses to Zep.
|
|
9
|
+
- Lazy Zep user and thread creation on first use.
|
|
10
|
+
- Message deduplication to prevent double-persistence during tool-use cycles.
|
|
11
|
+
- Graceful error handling that logs failures without crashing the agent.
|
|
12
|
+
- Comprehensive test suite with mocked dependencies.
|
|
13
|
+
- Working example demonstrating fact seeding and memory recall.
|
zep_adk-0.1.0/Makefile
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Makefile for zep-adk development
|
|
2
|
+
|
|
3
|
+
.PHONY: help install format lint type-check test test-cov clean build all
|
|
4
|
+
|
|
5
|
+
# Default target
|
|
6
|
+
help:
|
|
7
|
+
@echo "Available commands:"
|
|
8
|
+
@echo " install - Install package and dependencies in development mode"
|
|
9
|
+
@echo " format - Format code with ruff"
|
|
10
|
+
@echo " lint - Run linting checks"
|
|
11
|
+
@echo " type-check - Run type checking with mypy"
|
|
12
|
+
@echo " test - Run tests"
|
|
13
|
+
@echo " test-cov - Run tests with coverage report"
|
|
14
|
+
@echo " all - Run format, lint, type-check, and test"
|
|
15
|
+
@echo " build - Build the package"
|
|
16
|
+
@echo " clean - Clean build artifacts"
|
|
17
|
+
|
|
18
|
+
# Install package in development mode
|
|
19
|
+
install:
|
|
20
|
+
uv sync --extra dev
|
|
21
|
+
|
|
22
|
+
# Format code
|
|
23
|
+
format:
|
|
24
|
+
uv run ruff format .
|
|
25
|
+
|
|
26
|
+
# Run linting checks
|
|
27
|
+
lint:
|
|
28
|
+
uv run ruff check .
|
|
29
|
+
|
|
30
|
+
# Fix linting issues automatically
|
|
31
|
+
lint-fix:
|
|
32
|
+
uv run ruff check --fix .
|
|
33
|
+
|
|
34
|
+
# Run type checking
|
|
35
|
+
type-check:
|
|
36
|
+
uv run mypy src/
|
|
37
|
+
|
|
38
|
+
# Run tests
|
|
39
|
+
test:
|
|
40
|
+
uv run pytest tests/ -v
|
|
41
|
+
|
|
42
|
+
# Run tests with coverage
|
|
43
|
+
test-cov:
|
|
44
|
+
uv run pytest tests/ -v --cov=zep_adk --cov-report=term-missing --cov-report=xml
|
|
45
|
+
|
|
46
|
+
# Run all checks (the order matters: format first, then lint, then type-check, then test)
|
|
47
|
+
all: format lint type-check test
|
|
48
|
+
|
|
49
|
+
# Build the package
|
|
50
|
+
build:
|
|
51
|
+
uv build
|
|
52
|
+
|
|
53
|
+
# Clean build artifacts
|
|
54
|
+
clean:
|
|
55
|
+
rm -rf dist/
|
|
56
|
+
rm -rf build/
|
|
57
|
+
rm -rf *.egg-info/
|
|
58
|
+
rm -rf .pytest_cache/
|
|
59
|
+
rm -rf .mypy_cache/
|
|
60
|
+
rm -rf .ruff_cache/
|
|
61
|
+
find . -type d -name __pycache__ -exec rm -rf {} +
|
|
62
|
+
find . -type f -name "*.pyc" -delete
|
|
63
|
+
rm -f coverage.xml
|
|
64
|
+
rm -f .coverage
|
|
65
|
+
|
|
66
|
+
# Development workflow - run this before committing
|
|
67
|
+
pre-commit: lint-fix format lint type-check test
|
|
68
|
+
@echo "All checks passed! Ready to commit."
|
|
69
|
+
|
|
70
|
+
# CI workflow - strict checks without auto-fixing
|
|
71
|
+
ci: lint type-check test
|
|
72
|
+
@echo "CI checks passed!"
|
zep_adk-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zep-adk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Google ADK integration for Zep
|
|
5
|
+
Project-URL: Homepage, https://github.com/getzep/zep
|
|
6
|
+
Project-URL: Documentation, https://help.getzep.com
|
|
7
|
+
Project-URL: Repository, https://github.com/getzep/zep
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/getzep/zep/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/getzep/zep/blob/main/integrations/python/zep_adk/CHANGELOG.md
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Requires-Dist: google-adk>=1.0.0
|
|
12
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
13
|
+
Requires-Dist: zep-cloud>=3.0.0
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest-cov; extra == 'dev'
|
|
18
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
19
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# Zep Google ADK Integration
|
|
23
|
+
|
|
24
|
+
A memory integration package that enables [Google ADK](https://github.com/google/adk-python) agents to leverage [Zep](https://getzep.com)'s long-term memory platform for persistent conversation storage and context-aware responses.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
pip install zep-adk
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
Define one agent, shared across all users. Per-user identity is passed via ADK session state.
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import os
|
|
38
|
+
from google.adk.agents import Agent
|
|
39
|
+
from google.adk.runners import Runner
|
|
40
|
+
from google.adk.sessions import InMemorySessionService
|
|
41
|
+
from zep_cloud.client import AsyncZep
|
|
42
|
+
from zep_adk import ZepContextTool, create_after_model_callback
|
|
43
|
+
|
|
44
|
+
# Initialize Zep client
|
|
45
|
+
zep = AsyncZep(api_key=os.getenv("ZEP_API_KEY"))
|
|
46
|
+
|
|
47
|
+
# One shared agent definition
|
|
48
|
+
agent = Agent(
|
|
49
|
+
name="my_agent",
|
|
50
|
+
model="gemini-2.5-flash",
|
|
51
|
+
instruction="You are a helpful assistant with long-term memory.",
|
|
52
|
+
tools=[ZepContextTool(zep_client=zep)],
|
|
53
|
+
after_model_callback=create_after_model_callback(zep_client=zep),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
session_service = InMemorySessionService()
|
|
57
|
+
runner = Runner(agent=agent, app_name="my_app", session_service=session_service)
|
|
58
|
+
|
|
59
|
+
# Per-user session: user_id → Zep user, session_id → Zep thread
|
|
60
|
+
await session_service.create_session(
|
|
61
|
+
app_name="my_app",
|
|
62
|
+
user_id="user_123", # automatically used as Zep user ID
|
|
63
|
+
session_id="session_abc", # automatically used as Zep thread ID
|
|
64
|
+
state={
|
|
65
|
+
"zep_first_name": "Jane",
|
|
66
|
+
"zep_last_name": "Smith",
|
|
67
|
+
"zep_email": "jane@example.com", # optional
|
|
68
|
+
},
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Session State Keys
|
|
73
|
+
|
|
74
|
+
Identity is resolved at runtime from ADK session state and session metadata. The ADK `user_id` is used as the Zep user ID and the `session_id` is used as the Zep thread ID -- both automatically, no state keys needed.
|
|
75
|
+
|
|
76
|
+
Set these optional keys when creating a session to enrich the Zep user profile:
|
|
77
|
+
|
|
78
|
+
| Key | Required | Default | Description |
|
|
79
|
+
|-----|----------|---------|-------------|
|
|
80
|
+
| `zep_first_name` | Recommended | `"Anonymous"` | User's first name. Zep uses this to anchor the user's identity node in the knowledge graph. |
|
|
81
|
+
| `zep_last_name` | Optional | `"User"` | User's last name. |
|
|
82
|
+
| `zep_email` | Optional | `None` | User's email address. |
|
|
83
|
+
| `zep_user_id` | Optional | ADK `user_id` | Override the Zep user ID if it differs from the ADK user ID. |
|
|
84
|
+
| `zep_thread_id` | Optional | ADK `session_id` | Override the Zep thread ID if it differs from the ADK session ID. |
|
|
85
|
+
|
|
86
|
+
## How It Works
|
|
87
|
+
|
|
88
|
+
The integration uses two components that work together to give your ADK agent persistent memory:
|
|
89
|
+
|
|
90
|
+
### ZepContextTool
|
|
91
|
+
|
|
92
|
+
A `BaseTool` subclass that hooks into ADK's `process_llm_request()` lifecycle method (the same pattern ADK's own `PreloadMemoryTool` uses). On every LLM turn it:
|
|
93
|
+
|
|
94
|
+
1. **Extracts** the user's latest message from the invocation context.
|
|
95
|
+
2. **Resolves** the user's Zep identity from session state.
|
|
96
|
+
3. **Persists** the message to Zep via `thread.add_messages(return_context=True)` -- storing the message and retrieving relevant context in a single API call.
|
|
97
|
+
4. **Injects** the returned context (facts, relationships, prior knowledge) into the LLM's system instructions.
|
|
98
|
+
|
|
99
|
+
The tool is never called by the model directly; it modifies the outgoing LLM request before it is sent.
|
|
100
|
+
|
|
101
|
+
### create_after_model_callback
|
|
102
|
+
|
|
103
|
+
A factory function that returns an `after_model_callback` for persisting assistant responses to Zep. This ensures both sides of the conversation are stored in Zep's memory. The callback also resolves the thread ID from session state at runtime.
|
|
104
|
+
|
|
105
|
+
Both components include per-thread message deduplication to handle ADK's tool-use cycles, where the framework may call hooks multiple times per turn.
|
|
106
|
+
|
|
107
|
+
## Adding Zep to an Existing Agent
|
|
108
|
+
|
|
109
|
+
If you already have an ADK agent serving all users, adding Zep memory requires only three changes -- no restructuring needed:
|
|
110
|
+
|
|
111
|
+
1. **Add `ZepContextTool` to your agent's tools list:**
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
from zep_adk import ZepContextTool
|
|
115
|
+
|
|
116
|
+
agent = Agent(
|
|
117
|
+
name="my_existing_agent",
|
|
118
|
+
model="gemini-2.5-flash",
|
|
119
|
+
instruction="...",
|
|
120
|
+
tools=[your_existing_tool, ZepContextTool(zep_client=zep)],
|
|
121
|
+
after_model_callback=create_after_model_callback(zep_client=zep),
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
2. **Include the user's name in session state** when creating sessions (you're already creating sessions -- just add the keys):
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
await session_service.create_session(
|
|
129
|
+
app_name="my_app",
|
|
130
|
+
user_id=user_id, # automatically used as Zep user ID
|
|
131
|
+
session_id=session_id, # automatically used as Zep thread ID
|
|
132
|
+
state={
|
|
133
|
+
**your_existing_state,
|
|
134
|
+
"zep_first_name": first_name,
|
|
135
|
+
"zep_last_name": last_name,
|
|
136
|
+
},
|
|
137
|
+
)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
3. That's it. No factory function, no per-session agent instances.
|
|
141
|
+
|
|
142
|
+
## Features
|
|
143
|
+
|
|
144
|
+
- **Shared-agent architecture** -- one Agent definition serves all users
|
|
145
|
+
- **Session-state-driven identity** -- per-user configuration via ADK's standard mechanism
|
|
146
|
+
- **Single round-trip** -- persist messages and retrieve context in one API call
|
|
147
|
+
- **Lazy resource creation** -- Zep user and thread are created on first use
|
|
148
|
+
- **Per-thread deduplication** -- prevents double-persistence during tool-use cycles
|
|
149
|
+
- **Graceful error handling** -- Zep API failures are logged but never crash the agent
|
|
150
|
+
- **Context injection** -- Zep's knowledge graph context is injected as system instructions
|
|
151
|
+
- **Per-user setup hook** -- `on_user_created` callback for configuring ontology, instructions, and summaries per user
|
|
152
|
+
- **On-demand graph search** -- `ZepGraphSearchTool` lets the model actively search the knowledge graph
|
|
153
|
+
- **Configurable graph search** -- pin parameters at construction or let the model choose
|
|
154
|
+
|
|
155
|
+
## Configuration
|
|
156
|
+
|
|
157
|
+
### Environment Variables
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
# Required
|
|
161
|
+
export ZEP_API_KEY="your-zep-api-key"
|
|
162
|
+
export GOOGLE_API_KEY="your-google-api-key"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Constructor Parameters
|
|
166
|
+
|
|
167
|
+
#### ZepContextTool
|
|
168
|
+
|
|
169
|
+
| Parameter | Type | Required | Default | Description |
|
|
170
|
+
|-----------|------|----------|---------|-------------|
|
|
171
|
+
| `zep_client` | `AsyncZep` | Yes | -- | Initialised Zep async client |
|
|
172
|
+
| `context_builder` | `ContextBuilder` | No | `None` | Custom async callable for context retrieval |
|
|
173
|
+
| `ignore_roles` | `list[str]` | No | `None` | Roles to exclude from graph ingestion |
|
|
174
|
+
| `on_user_created` | `UserSetupHook` | No | `None` | Async callback fired once after a new Zep user is created. Use for per-user ontology, custom instructions, or user summary instructions. |
|
|
175
|
+
|
|
176
|
+
#### create_after_model_callback
|
|
177
|
+
|
|
178
|
+
| Parameter | Type | Required | Default | Description |
|
|
179
|
+
|-----------|------|----------|---------|-------------|
|
|
180
|
+
| `zep_client` | `AsyncZep` | Yes | -- | Initialised Zep async client |
|
|
181
|
+
| `assistant_name` | `str` | No | `"Assistant"` | Display name for the assistant in Zep |
|
|
182
|
+
| `ignore_roles` | `list[str]` | No | `None` | Roles to exclude from graph ingestion |
|
|
183
|
+
|
|
184
|
+
#### ZepGraphSearchTool
|
|
185
|
+
|
|
186
|
+
| Parameter | Type | Required | Default | Description |
|
|
187
|
+
|-----------|------|----------|---------|-------------|
|
|
188
|
+
| `zep_client` | `AsyncZep` | Yes | -- | Initialised Zep async client |
|
|
189
|
+
| `graph_id` | `str` | No | `None` | Fixed graph ID for shared-graph search |
|
|
190
|
+
| `name` | `str` | No | `"zep_graph_search"` | Tool name visible to the model |
|
|
191
|
+
| `description` | `str` | No | (default) | Tool description visible to the model |
|
|
192
|
+
| `search_filters` | `dict` | No | `None` | Zep search filters (constructor-only) |
|
|
193
|
+
| `bfs_origin_node_uuids` | `list[str]` | No | `None` | BFS seed node UUIDs (constructor-only) |
|
|
194
|
+
| `**pinned` | any | No | -- | Pin any search param: `scope`, `reranker`, `limit`, `mmr_lambda`, `center_node_uuid` |
|
|
195
|
+
|
|
196
|
+
## Examples
|
|
197
|
+
|
|
198
|
+
See the [examples/](examples/) directory for complete working examples:
|
|
199
|
+
|
|
200
|
+
- **[basic_agent.py](examples/basic_agent.py)** -- Full example with fact seeding and memory recall using the shared-agent pattern
|
|
201
|
+
|
|
202
|
+
## Development
|
|
203
|
+
|
|
204
|
+
### Setup
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
git clone https://github.com/getzep/zep.git
|
|
208
|
+
cd integrations/python/zep_adk
|
|
209
|
+
make install
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Commands
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
make format # Format code with ruff
|
|
216
|
+
make lint # Run linting checks
|
|
217
|
+
make type-check # Run mypy type checking
|
|
218
|
+
make test # Run test suite
|
|
219
|
+
make all # Run all checks
|
|
220
|
+
make pre-commit # Development workflow with auto-fixes
|
|
221
|
+
make ci # Strict CI checks
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Requirements
|
|
225
|
+
|
|
226
|
+
- Python 3.10+
|
|
227
|
+
- `zep-cloud>=3.0.0`
|
|
228
|
+
- `google-adk>=1.0.0`
|
|
229
|
+
|
|
230
|
+
## Support
|
|
231
|
+
|
|
232
|
+
- [Zep Documentation](https://help.getzep.com)
|
|
233
|
+
- [Google ADK Documentation](https://google.github.io/adk-docs/)
|
|
234
|
+
- [GitHub Issues](https://github.com/getzep/zep/issues)
|
|
235
|
+
|
|
236
|
+
## License
|
|
237
|
+
|
|
238
|
+
Apache 2.0 - see [LICENSE](LICENSE) for details.
|
|
239
|
+
|
|
240
|
+
## Contributing
|
|
241
|
+
|
|
242
|
+
Contributions are welcome! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details.
|
zep_adk-0.1.0/README.md
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Zep Google ADK Integration
|
|
2
|
+
|
|
3
|
+
A memory integration package that enables [Google ADK](https://github.com/google/adk-python) agents to leverage [Zep](https://getzep.com)'s long-term memory platform for persistent conversation storage and context-aware responses.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install zep-adk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
Define one agent, shared across all users. Per-user identity is passed via ADK session state.
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
import os
|
|
17
|
+
from google.adk.agents import Agent
|
|
18
|
+
from google.adk.runners import Runner
|
|
19
|
+
from google.adk.sessions import InMemorySessionService
|
|
20
|
+
from zep_cloud.client import AsyncZep
|
|
21
|
+
from zep_adk import ZepContextTool, create_after_model_callback
|
|
22
|
+
|
|
23
|
+
# Initialize Zep client
|
|
24
|
+
zep = AsyncZep(api_key=os.getenv("ZEP_API_KEY"))
|
|
25
|
+
|
|
26
|
+
# One shared agent definition
|
|
27
|
+
agent = Agent(
|
|
28
|
+
name="my_agent",
|
|
29
|
+
model="gemini-2.5-flash",
|
|
30
|
+
instruction="You are a helpful assistant with long-term memory.",
|
|
31
|
+
tools=[ZepContextTool(zep_client=zep)],
|
|
32
|
+
after_model_callback=create_after_model_callback(zep_client=zep),
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
session_service = InMemorySessionService()
|
|
36
|
+
runner = Runner(agent=agent, app_name="my_app", session_service=session_service)
|
|
37
|
+
|
|
38
|
+
# Per-user session: user_id → Zep user, session_id → Zep thread
|
|
39
|
+
await session_service.create_session(
|
|
40
|
+
app_name="my_app",
|
|
41
|
+
user_id="user_123", # automatically used as Zep user ID
|
|
42
|
+
session_id="session_abc", # automatically used as Zep thread ID
|
|
43
|
+
state={
|
|
44
|
+
"zep_first_name": "Jane",
|
|
45
|
+
"zep_last_name": "Smith",
|
|
46
|
+
"zep_email": "jane@example.com", # optional
|
|
47
|
+
},
|
|
48
|
+
)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Session State Keys
|
|
52
|
+
|
|
53
|
+
Identity is resolved at runtime from ADK session state and session metadata. The ADK `user_id` is used as the Zep user ID and the `session_id` is used as the Zep thread ID -- both automatically, no state keys needed.
|
|
54
|
+
|
|
55
|
+
Set these optional keys when creating a session to enrich the Zep user profile:
|
|
56
|
+
|
|
57
|
+
| Key | Required | Default | Description |
|
|
58
|
+
|-----|----------|---------|-------------|
|
|
59
|
+
| `zep_first_name` | Recommended | `"Anonymous"` | User's first name. Zep uses this to anchor the user's identity node in the knowledge graph. |
|
|
60
|
+
| `zep_last_name` | Optional | `"User"` | User's last name. |
|
|
61
|
+
| `zep_email` | Optional | `None` | User's email address. |
|
|
62
|
+
| `zep_user_id` | Optional | ADK `user_id` | Override the Zep user ID if it differs from the ADK user ID. |
|
|
63
|
+
| `zep_thread_id` | Optional | ADK `session_id` | Override the Zep thread ID if it differs from the ADK session ID. |
|
|
64
|
+
|
|
65
|
+
## How It Works
|
|
66
|
+
|
|
67
|
+
The integration uses two components that work together to give your ADK agent persistent memory:
|
|
68
|
+
|
|
69
|
+
### ZepContextTool
|
|
70
|
+
|
|
71
|
+
A `BaseTool` subclass that hooks into ADK's `process_llm_request()` lifecycle method (the same pattern ADK's own `PreloadMemoryTool` uses). On every LLM turn it:
|
|
72
|
+
|
|
73
|
+
1. **Extracts** the user's latest message from the invocation context.
|
|
74
|
+
2. **Resolves** the user's Zep identity from session state.
|
|
75
|
+
3. **Persists** the message to Zep via `thread.add_messages(return_context=True)` -- storing the message and retrieving relevant context in a single API call.
|
|
76
|
+
4. **Injects** the returned context (facts, relationships, prior knowledge) into the LLM's system instructions.
|
|
77
|
+
|
|
78
|
+
The tool is never called by the model directly; it modifies the outgoing LLM request before it is sent.
|
|
79
|
+
|
|
80
|
+
### create_after_model_callback
|
|
81
|
+
|
|
82
|
+
A factory function that returns an `after_model_callback` for persisting assistant responses to Zep. This ensures both sides of the conversation are stored in Zep's memory. The callback also resolves the thread ID from session state at runtime.
|
|
83
|
+
|
|
84
|
+
Both components include per-thread message deduplication to handle ADK's tool-use cycles, where the framework may call hooks multiple times per turn.
|
|
85
|
+
|
|
86
|
+
## Adding Zep to an Existing Agent
|
|
87
|
+
|
|
88
|
+
If you already have an ADK agent serving all users, adding Zep memory requires only three changes -- no restructuring needed:
|
|
89
|
+
|
|
90
|
+
1. **Add `ZepContextTool` to your agent's tools list:**
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from zep_adk import ZepContextTool
|
|
94
|
+
|
|
95
|
+
agent = Agent(
|
|
96
|
+
name="my_existing_agent",
|
|
97
|
+
model="gemini-2.5-flash",
|
|
98
|
+
instruction="...",
|
|
99
|
+
tools=[your_existing_tool, ZepContextTool(zep_client=zep)],
|
|
100
|
+
after_model_callback=create_after_model_callback(zep_client=zep),
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
2. **Include the user's name in session state** when creating sessions (you're already creating sessions -- just add the keys):
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
await session_service.create_session(
|
|
108
|
+
app_name="my_app",
|
|
109
|
+
user_id=user_id, # automatically used as Zep user ID
|
|
110
|
+
session_id=session_id, # automatically used as Zep thread ID
|
|
111
|
+
state={
|
|
112
|
+
**your_existing_state,
|
|
113
|
+
"zep_first_name": first_name,
|
|
114
|
+
"zep_last_name": last_name,
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
3. That's it. No factory function, no per-session agent instances.
|
|
120
|
+
|
|
121
|
+
## Features
|
|
122
|
+
|
|
123
|
+
- **Shared-agent architecture** -- one Agent definition serves all users
|
|
124
|
+
- **Session-state-driven identity** -- per-user configuration via ADK's standard mechanism
|
|
125
|
+
- **Single round-trip** -- persist messages and retrieve context in one API call
|
|
126
|
+
- **Lazy resource creation** -- Zep user and thread are created on first use
|
|
127
|
+
- **Per-thread deduplication** -- prevents double-persistence during tool-use cycles
|
|
128
|
+
- **Graceful error handling** -- Zep API failures are logged but never crash the agent
|
|
129
|
+
- **Context injection** -- Zep's knowledge graph context is injected as system instructions
|
|
130
|
+
- **Per-user setup hook** -- `on_user_created` callback for configuring ontology, instructions, and summaries per user
|
|
131
|
+
- **On-demand graph search** -- `ZepGraphSearchTool` lets the model actively search the knowledge graph
|
|
132
|
+
- **Configurable graph search** -- pin parameters at construction or let the model choose
|
|
133
|
+
|
|
134
|
+
## Configuration
|
|
135
|
+
|
|
136
|
+
### Environment Variables
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Required
|
|
140
|
+
export ZEP_API_KEY="your-zep-api-key"
|
|
141
|
+
export GOOGLE_API_KEY="your-google-api-key"
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Constructor Parameters
|
|
145
|
+
|
|
146
|
+
#### ZepContextTool
|
|
147
|
+
|
|
148
|
+
| Parameter | Type | Required | Default | Description |
|
|
149
|
+
|-----------|------|----------|---------|-------------|
|
|
150
|
+
| `zep_client` | `AsyncZep` | Yes | -- | Initialised Zep async client |
|
|
151
|
+
| `context_builder` | `ContextBuilder` | No | `None` | Custom async callable for context retrieval |
|
|
152
|
+
| `ignore_roles` | `list[str]` | No | `None` | Roles to exclude from graph ingestion |
|
|
153
|
+
| `on_user_created` | `UserSetupHook` | No | `None` | Async callback fired once after a new Zep user is created. Use for per-user ontology, custom instructions, or user summary instructions. |
|
|
154
|
+
|
|
155
|
+
#### create_after_model_callback
|
|
156
|
+
|
|
157
|
+
| Parameter | Type | Required | Default | Description |
|
|
158
|
+
|-----------|------|----------|---------|-------------|
|
|
159
|
+
| `zep_client` | `AsyncZep` | Yes | -- | Initialised Zep async client |
|
|
160
|
+
| `assistant_name` | `str` | No | `"Assistant"` | Display name for the assistant in Zep |
|
|
161
|
+
| `ignore_roles` | `list[str]` | No | `None` | Roles to exclude from graph ingestion |
|
|
162
|
+
|
|
163
|
+
#### ZepGraphSearchTool
|
|
164
|
+
|
|
165
|
+
| Parameter | Type | Required | Default | Description |
|
|
166
|
+
|-----------|------|----------|---------|-------------|
|
|
167
|
+
| `zep_client` | `AsyncZep` | Yes | -- | Initialised Zep async client |
|
|
168
|
+
| `graph_id` | `str` | No | `None` | Fixed graph ID for shared-graph search |
|
|
169
|
+
| `name` | `str` | No | `"zep_graph_search"` | Tool name visible to the model |
|
|
170
|
+
| `description` | `str` | No | (default) | Tool description visible to the model |
|
|
171
|
+
| `search_filters` | `dict` | No | `None` | Zep search filters (constructor-only) |
|
|
172
|
+
| `bfs_origin_node_uuids` | `list[str]` | No | `None` | BFS seed node UUIDs (constructor-only) |
|
|
173
|
+
| `**pinned` | any | No | -- | Pin any search param: `scope`, `reranker`, `limit`, `mmr_lambda`, `center_node_uuid` |
|
|
174
|
+
|
|
175
|
+
## Examples
|
|
176
|
+
|
|
177
|
+
See the [examples/](examples/) directory for complete working examples:
|
|
178
|
+
|
|
179
|
+
- **[basic_agent.py](examples/basic_agent.py)** -- Full example with fact seeding and memory recall using the shared-agent pattern
|
|
180
|
+
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
### Setup
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
git clone https://github.com/getzep/zep.git
|
|
187
|
+
cd integrations/python/zep_adk
|
|
188
|
+
make install
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Commands
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
make format # Format code with ruff
|
|
195
|
+
make lint # Run linting checks
|
|
196
|
+
make type-check # Run mypy type checking
|
|
197
|
+
make test # Run test suite
|
|
198
|
+
make all # Run all checks
|
|
199
|
+
make pre-commit # Development workflow with auto-fixes
|
|
200
|
+
make ci # Strict CI checks
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Requirements
|
|
204
|
+
|
|
205
|
+
- Python 3.10+
|
|
206
|
+
- `zep-cloud>=3.0.0`
|
|
207
|
+
- `google-adk>=1.0.0`
|
|
208
|
+
|
|
209
|
+
## Support
|
|
210
|
+
|
|
211
|
+
- [Zep Documentation](https://help.getzep.com)
|
|
212
|
+
- [Google ADK Documentation](https://google.github.io/adk-docs/)
|
|
213
|
+
- [GitHub Issues](https://github.com/getzep/zep/issues)
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
Apache 2.0 - see [LICENSE](LICENSE) for details.
|
|
218
|
+
|
|
219
|
+
## Contributing
|
|
220
|
+
|
|
221
|
+
Contributions are welcome! Please see our [Contributing Guide](../../../CONTRIBUTING.md) for details.
|