* fix(deps): address critical and high severity security vulnerabilities Bump vulnerable dependencies to patched versions across the monorepo: Python (critical/high): - fastmcp >=2.14.0 → >=3.2.0 (SSRF, path traversal, OAuth confused deputy, command injection) - langchain-core >=1.2.11 → >=1.2.22 (path traversal in legacy load_prompt) Python (low): - cryptography >=46.0.5 → >=46.0.6 (incomplete DNS name constraint enforcement) - pygments: add >=2.20.0 pin (ReDoS via GUID regex) Node.js: - serialize-javascript ^7.0.3 → ^7.0.5 (CPU exhaustion DoS) - handlebars: add >=4.7.9 override (JS injection via AST type confusion) - path-to-regexp: add >=0.1.13 override (ReDoS via route params) - brace-expansion: add version range override (process hang/memory exhaustion) Also adds type: ignore comments for FastMCP 2.x private attribute access that ty now flags since FastMCP 3.x removed _tool_manager (guarded by try/except and hasattr at runtime). Regenerated all lock files across API, integrations, and tests. * fix(deps): add ajv v8 scoped overrides for schema-utils and ajv-keywords The global ajv ^6.14.0 override caused schema-utils and ajv-keywords to receive ajv v6, but they require ajv v8 (for dist/compile/codegen). Add scoped overrides to ensure these packages get ajv v8 while the global override remains for packages that need v6. * fix(tests): remove stateless_http from FastMCP() constructor calls FastMCP 3.x no longer accepts stateless_http in the constructor. The tests call tools directly without HTTP transport, so the parameter is not needed. * fix: update MCP tests for FastMCP 3.x _tool_manager removal FastMCP 3.x removed _tool_manager. Tests now use _local_provider._components for sync tool dict access and mcp.list_tools() for async filtered tool listing. * fix: resolve docusaurus build failures (ajv overrides + missing blog date) - Remove global ajv ^6.14.0 override and scoped ajv-keywords/schema-utils overrides that caused webpack compilation errors manifesting as "Cannot read properties of undefined (reading 'date')" during SSR and "these parameters are deprecated" warnings. Natural version resolution (v6.12.6+ for v6 consumers, v8+ for v8 consumers) already satisfies the security fix (>= 6.12.3). - Add missing date frontmatter to learning-capabilities blog post. * chore: regenerate openapi spec and docs skill |
||
|---|---|---|
| .. | ||
| hindsight_pydantic_ai | ||
| tests | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
hindsight-pydantic-ai
Persistent memory tools for Pydantic AI agents via Hindsight. Give your agents long-term memory with retain, recall, and reflect — all async-native with no thread-pool hacks.
Features
- Async-Native Tools - Uses Pydantic AI's async tool interface directly (
aretain,arecall,areflect) - Memory Instructions - Auto-inject relevant memories into every agent run via
instructions=[...] - Three Memory Tools - Retain (store), Recall (search), Reflect (synthesize) — include any combination
- Simple Configuration - Configure once globally, or pass a client directly
- Lightweight - Depends on
pydantic-ai-slimto avoid pulling in all model providers
Installation
pip install hindsight-pydantic-ai
Quick Start
from hindsight_client import Hindsight
from hindsight_pydantic_ai import create_hindsight_tools, memory_instructions
from pydantic_ai import Agent
client = Hindsight(base_url="http://localhost:8888")
agent = Agent(
"openai:gpt-4o",
tools=create_hindsight_tools(client=client, bank_id="user-123"),
instructions=[memory_instructions(client=client, bank_id="user-123")],
)
result = await agent.run("What do you remember about my preferences?")
print(result.output)
The agent now has three tools it can call:
hindsight_retain— Store information to long-term memoryhindsight_recall— Search long-term memory for relevant factshindsight_reflect— Synthesize a reasoned answer from memories
The memory_instructions callable automatically recalls relevant memories and injects them into the system prompt on every run.
Tools Only (No Auto-Injection)
If you want the agent to decide when to use memory (rather than always injecting context):
agent = Agent(
"openai:gpt-4o",
tools=create_hindsight_tools(client=client, bank_id="user-123"),
)
Instructions Only (No Tools)
If you just want memories auto-injected without giving the agent explicit memory tools:
agent = Agent(
"openai:gpt-4o",
instructions=[memory_instructions(client=client, bank_id="user-123")],
)
Selecting Tools
Include only the tools you need:
tools = create_hindsight_tools(
client=client,
bank_id="user-123",
include_retain=True,
include_recall=True,
include_reflect=False, # Omit reflect
)
Global Configuration
Instead of passing a client to every call, configure once:
from hindsight_pydantic_ai import configure, create_hindsight_tools
configure(
hindsight_api_url="http://localhost:8888",
api_key="your-api-key", # Or set HINDSIGHT_API_KEY env var
budget="mid", # Recall budget: low/mid/high
max_tokens=4096, # Max tokens for recall results
tags=["env:prod"], # Tags for stored memories
recall_tags=["scope:global"], # Tags to filter recall
recall_tags_match="any", # Tag match mode: any/all/any_strict/all_strict
)
# Now create tools without passing client — uses global config
tools = create_hindsight_tools(bank_id="user-123")
Per-Tool Overrides
Constructor arguments override global configuration:
tools = create_hindsight_tools(
bank_id="user-123",
budget="high", # Override global budget
max_tokens=8192, # Override global max_tokens
tags=["session:abc"], # Override global tags
)
Memory Instructions Options
Customize what memories get injected and how:
instructions_fn = memory_instructions(
client=client,
bank_id="user-123",
query="relevant context about the user", # What to search for
budget="low", # Keep it fast
max_results=5, # Limit injected memories
max_tokens=4096, # Max recall tokens
prefix="Relevant memories:\n", # Text before the memory list
tags=["scope:global"], # Filter by tags
tags_match="any", # Tag match mode
)
Configuration Reference
create_hindsight_tools()
| Parameter | Default | Description |
|---|---|---|
bank_id |
required | Hindsight memory bank ID |
client |
None |
Pre-configured Hindsight client |
hindsight_api_url |
None |
API URL (used if no client provided) |
api_key |
None |
API key (used if no client provided) |
budget |
"mid" |
Recall/reflect budget level (low/mid/high) |
max_tokens |
4096 |
Maximum tokens for recall results |
tags |
None |
Tags applied when storing memories |
recall_tags |
None |
Tags to filter when searching |
recall_tags_match |
"any" |
Tag matching mode |
include_retain |
True |
Include the retain (store) tool |
include_recall |
True |
Include the recall (search) tool |
include_reflect |
True |
Include the reflect (synthesize) tool |
memory_instructions()
| Parameter | Default | Description |
|---|---|---|
bank_id |
required | Hindsight memory bank ID |
client |
None |
Pre-configured Hindsight client |
hindsight_api_url |
None |
API URL (used if no client provided) |
api_key |
None |
API key (used if no client provided) |
query |
"relevant context about the user" |
Recall query for memory injection |
budget |
"low" |
Recall budget level |
max_results |
5 |
Maximum memories to inject |
max_tokens |
4096 |
Maximum tokens for recall results |
prefix |
"Relevant memories:\n" |
Text prepended before memory list |
tags |
None |
Tags to filter recall results |
tags_match |
"any" |
Tag matching mode |
configure()
| Parameter | Default | Description |
|---|---|---|
hindsight_api_url |
Production API | Hindsight API URL |
api_key |
HINDSIGHT_API_KEY env |
API key for authentication |
budget |
"mid" |
Default recall budget level |
max_tokens |
4096 |
Default max tokens for recall |
tags |
None |
Default tags for retain operations |
recall_tags |
None |
Default tags to filter recall |
recall_tags_match |
"any" |
Default tag matching mode |
verbose |
False |
Enable verbose logging |
Requirements
- Python >= 3.10
- pydantic-ai-slim >= 1.0.0
- hindsight-client >= 0.4.0
- A running Hindsight API server
License
MIT