Pydantic AI integration for Zep
Project description
Zep Pydantic AI Integration
A memory integration package that gives Pydantic AI agents long-term memory powered by Zep. User turns are persisted to Zep and relevant context from Zep's temporal knowledge graph is injected into the model prompt on every turn -- using Pydantic AI's native ProcessHistory capability -- plus an on-demand graph-search tool.
Installation
pip install zep-pydantic-ai
See SETUP.md for how to sign up for Zep, create an API key, configure your environment, and run the example.
Quick Start
import asyncio
from pydantic_ai import Agent
from pydantic_ai.capabilities import ProcessHistory
from zep_cloud.client import AsyncZep
from zep_pydantic_ai import (
ZepDeps,
zep_history_processor,
create_zep_search_tool,
persist_run,
)
zep = AsyncZep(api_key="your-zep-api-key")
agent = Agent(
"openai:gpt-4o-mini",
deps_type=ZepDeps,
capabilities=[ProcessHistory(zep_history_processor)],
tools=[create_zep_search_tool()],
instructions="You are a helpful assistant with long-term memory.",
)
async def main() -> None:
deps = ZepDeps(
client=zep,
user_id="user_123",
thread_id="thread_abc",
first_name="Jane",
last_name="Smith",
)
result = await agent.run("What did I tell you about my project?", deps=deps)
print(result.output)
# Persist the assistant's reply (the user turn was already persisted).
await persist_run(deps, result.new_messages())
asyncio.run(main())
How It Works
The integration plugs into Pydantic AI through three components.
ZepDeps
A dataclass used as the agent's deps_type. It carries the Zep client and the
user/thread identity (plus optional name, email, and display names). Construct
one per conversation and pass it to agent.run(..., deps=deps); the history
processor and the search tool both reach it via RunContext.deps. The Zep user
and thread are created lazily on first use -- you do not have to pre-create
them.
zep_history_processor
Registered via capabilities=[ProcessHistory(zep_history_processor)]. Pydantic
AI runs a history processor immediately before every model request. On the
user's turn this processor:
- resolves the Zep client and identity from
ctx.deps; - lazily creates the Zep user and thread;
- persists the latest user message via
thread.add_messages(return_context=True)-- folding the write and context retrieval into a single round-trip; - prepends Zep's returned context block to the message history as a system message.
A subtle but important detail: ProcessHistory fires once per model request,
not once per run. A single
agent.run that makes a tool call invokes the processor more than once with the
same user turn. The processor therefore dedupes by the latest user message
text per (user_id, thread_id): it persists and retrieves on the first sight
of a turn, caches the context, and replays the cached context on re-invocations
without writing to Zep again. This prevents duplicate episodes.
create_zep_search_tool
A factory that returns a model-callable @agent.tool over graph.search. The
model decides when to search the knowledge graph for specific facts, entities,
or prior episodes. By default it searches the current user's graph; pass
graph_id=... to target a shared standalone graph (e.g. a documentation
knowledge base). Search parameters (scope, reranker, limit) are pinned at
construction time.
persist_run
Call after agent.run with result.new_messages() to persist the assistant's
reply to the Zep thread. Only assistant text is sent -- the user turn (already
persisted by the processor) and any tool-call/tool-return scaffolding are
skipped, so Zep sees one clean assistant message per turn.
Public API
ZepDeps
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
client |
AsyncZep |
Yes | -- | Initialised Zep async client (caller owns its lifecycle) |
user_id |
str |
Yes | -- | Zep user ID (one user graph) |
thread_id |
str |
Yes | -- | Zep thread ID for the conversation |
first_name |
str |
No | None |
User first name (recommended; anchors the user node) |
last_name |
str |
No | None |
User last name |
email |
str |
No | None |
User email (helps identity resolution) |
user_name |
str |
No | None |
Display name for persisted user messages (defaults to first + last) |
assistant_name |
str |
No | "Assistant" |
Display name for persisted assistant messages |
ignore_roles |
list[str] |
No | None |
Roles to exclude from graph ingestion |
create_zep_search_tool
| Parameter | Type | Default | Description |
|---|---|---|---|
graph_id |
str |
None |
Standalone graph to search; when unset, searches the current user's graph |
scope |
"edges" | "nodes" | "episodes" | "observations" | "thread_summaries" | "auto" |
"edges" |
What to search |
reranker |
"rrf" | "mmr" | "node_distance" | "episode_mentions" | "cross_encoder" |
"rrf" |
Result ordering (ignored for scope="auto") |
limit |
int |
10 |
Maximum results (clamped to Zep's ceiling of 50) |
name |
str |
"zep_search" |
Tool name exposed to the model |
Features
- Native
ProcessHistorycapability -- the current Pydantic AI hook, not the deprecatedhistory_processors=kwarg - Single round-trip -- persist + retrieve context in one
add_messagescall - Once-per-request dedupe -- correct under tool-calling runs that re-invoke the processor
- Lazy resource creation -- Zep user and thread created on first use
- On-demand graph search -- model-callable tool over
graph.search - Graceful error handling -- Zep failures are logged but never crash the agent run
- Fully typed -- ships type hints; passes
mypy --strict-style checks
Error Handling
Every Zep call is wrapped: a Zep outage, auth failure, or transient error is logged and the agent run continues. When persistence fails the turn is not cached, so the next model request retries it.
Configuration
export ZEP_API_KEY="your-zep-api-key"
export OPENAI_API_KEY="your-openai-api-key" # or another provider supported by Pydantic AI
Examples
See the examples/ directory:
- basic_agent.py -- fact seeding and memory recall with the history processor + search tool.
Development
make install # uv sync --extra dev
make format # ruff format
make lint # ruff check
make type-check # mypy src/
make test # pytest
make all # format + lint + type-check + test
make build # uv build
Requirements
- Python 3.11+
pydantic-ai>=1.107,<2zep-cloud>=3.23.0
Support
License
Apache 2.0 - see LICENSE for details.
Contributing
Contributions are welcome! Please see our Contributing Guide for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zep_pydantic_ai-0.1.0.tar.gz.
File metadata
- Download URL: zep_pydantic_ai-0.1.0.tar.gz
- Upload date:
- Size: 27.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b18132b176dc64990c28bc1e27daab2ca346e8019344cdbeedcff792ac991454
|
|
| MD5 |
91d76767a52eeee95270879e13a475ed
|
|
| BLAKE2b-256 |
88cd3418bbf2a43a37a8f79c6084d60f3b725303fcd5e4c136bb07eaf52c9306
|
Provenance
The following attestation bundles were made for zep_pydantic_ai-0.1.0.tar.gz:
Publisher:
release-integrations.yml on getzep/zep
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zep_pydantic_ai-0.1.0.tar.gz -
Subject digest:
b18132b176dc64990c28bc1e27daab2ca346e8019344cdbeedcff792ac991454 - Sigstore transparency entry: 2011062404
- Sigstore integration time:
-
Permalink:
getzep/zep@826c5492d9cc3a7caf92a9870529f29b5a8546e3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/getzep
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-integrations.yml@826c5492d9cc3a7caf92a9870529f29b5a8546e3 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file zep_pydantic_ai-0.1.0-py3-none-any.whl.
File metadata
- Download URL: zep_pydantic_ai-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
33582744295a7dbc6ae7c71cdc4cb5f9bbb5a3c776e1613e80fc28da9a6e90be
|
|
| MD5 |
19d660d266028e01281d55eb623a6b66
|
|
| BLAKE2b-256 |
d70a58a491c12e07916a9570145c6581a4ba5068df604c3003d614469f1e6578
|
Provenance
The following attestation bundles were made for zep_pydantic_ai-0.1.0-py3-none-any.whl:
Publisher:
release-integrations.yml on getzep/zep
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zep_pydantic_ai-0.1.0-py3-none-any.whl -
Subject digest:
33582744295a7dbc6ae7c71cdc4cb5f9bbb5a3c776e1613e80fc28da9a6e90be - Sigstore transparency entry: 2011062482
- Sigstore integration time:
-
Permalink:
getzep/zep@826c5492d9cc3a7caf92a9870529f29b5a8546e3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/getzep
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-integrations.yml@826c5492d9cc3a7caf92a9870529f29b5a8546e3 -
Trigger Event:
workflow_dispatch
-
Statement type: