mirror of
https://github.com/vectorize-io/hindsight.git
synced 2026-09-14 19:31:49 +08:00
77f80dc6f4
Closes the SQL-injection advisory GHSA-82m5-3pcp-hccq, which covers agno <= 2.6.5. The lockfile held 2.6.5 — the last vulnerable release. `agno` is unpinned in pyproject.toml, so this is a lockfile-only change: `uv lock --upgrade-package agno`. Worth noting for anyone triaging the same advisory: GitHub reports no patched version for it, which reads as unfixable. That is stale — the advisory covers `<= 2.6.5` and agno has since released 3.0.5, which is outside the range. The fix is a major version bump rather than a patch release, which is presumably why no patched version was recorded. ## 2.x -> 3.x The integration's runtime imports are `agno.run.base.RunContext` and `agno.tools.toolkit.Toolkit`; both still resolve. `agno.agent.Agent` and `agno.models.openai.OpenAIChat` appear only in the module docstring's usage example and inside a function body, so they are not imported at load time. agno 3.x makes `openai` an optional extra, so `from agno.models.openai import OpenAIChat` now raises unless `openai` is installed. That affects the docstring example, not this package: nothing here imports it at runtime, and the integration does not declare `openai` as a dependency in either version. Transitively: adds prompt-toolkit, questionary and wcwidth; drops python-multipart and smmap. ## Tests 162 passed, 10 failed — identical to `origin/main` before the bump, test for test. Those 10 are a pre-existing mismatch where the suite asserts on `Hindsight(...)` calls without the `user_agent` kwarg the client now sends, which is unrelated to agno and not addressed here. Verified by running the same suite in a clean worktree of `origin/main` and diffing the failure lists: no difference. Claude-Session: https://claude.ai/code/session_01SK2htrNEFAj2VuxKWqFavo
hindsight-agno
Persistent memory tools for Agno agents via Hindsight. Give your agents long-term memory with retain, recall, and reflect — using Agno's native Toolkit pattern.
Features
- Native Toolkit - Extends Agno's
Toolkitbase class, just likeMem0Tools - Memory Instructions - Pre-recall memories for injection into
Agent(instructions=[...]) - Three Memory Tools - Retain (store), Recall (search), Reflect (synthesize) — include any combination
- Flexible Bank Resolution - Static bank ID,
RunContext.user_id, or custom resolver - Simple Configuration - Configure once globally, or pass a client directly
Installation
pip install hindsight-agno
Quick Start
✨ Recommended: Hindsight Cloud — free tier, no self-hosting required. Sign up and grab an API key in under a minute.
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from hindsight_agno import HindsightTools
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
tools=[HindsightTools(
bank_id="user-123",
hindsight_api_url="https://api.hindsight.vectorize.io",
api_key="hsk_...", # or set HINDSIGHT_API_KEY env var
)],
)
agent.print_response("Remember that I prefer dark mode")
agent.print_response("What are my preferences?")
The agent now has three tools it can call:
retain_memory— Store information to long-term memoryrecall_memory— Search long-term memory for relevant factsreflect_on_memory— Synthesize a reasoned answer from memories
Self-hosting (local development)
If you're running Hindsight locally with ./scripts/dev/start-api.sh, point at your local server instead:
tools=[HindsightTools(
bank_id="user-123",
hindsight_api_url="https://api.hindsight.vectorize.io",
)]
See the Hindsight installation guide for self-hosting setup.
With Memory Instructions
Pre-recall relevant memories and inject them into the system prompt:
from hindsight_agno import HindsightTools, memory_instructions
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
tools=[HindsightTools(
bank_id="user-123",
hindsight_api_url="https://api.hindsight.vectorize.io",
)],
instructions=[memory_instructions(
bank_id="user-123",
hindsight_api_url="https://api.hindsight.vectorize.io",
)],
)
Selecting Tools
Include only the tools you need:
tools = [HindsightTools(
bank_id="user-123",
hindsight_api_url="https://api.hindsight.vectorize.io",
enable_retain=True,
enable_recall=True,
enable_reflect=False, # Omit reflect
)]
Bank Resolution
The bank ID is resolved in order:
bank_resolver— Custom callable(RunContext) -> strbank_id— Static bank ID passed to constructorrun_context.user_id— Automatic per-user banks
# Per-user banks from RunContext
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
tools=[HindsightTools(hindsight_api_url="https://api.hindsight.vectorize.io")],
user_id="user-123", # Used as bank_id
)
# Custom resolver
def resolve_bank(ctx):
return f"team-{ctx.user_id}"
agent = Agent(
model=OpenAIChat(id="gpt-4o-mini"),
tools=[HindsightTools(
bank_resolver=resolve_bank,
hindsight_api_url="https://api.hindsight.vectorize.io",
)],
)
Global Configuration
Instead of passing connection details to every toolkit, configure once:
from hindsight_agno import configure, HindsightTools
configure(
hindsight_api_url="https://api.hindsight.vectorize.io",
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 toolkit without passing connection details
tools = [HindsightTools(bank_id="user-123")]
Configuration Reference
HindsightTools()
| Parameter | Default | Description |
|---|---|---|
bank_id |
None |
Static Hindsight memory bank ID |
bank_resolver |
None |
Callable (RunContext) -> str for dynamic 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 |
enable_retain |
True |
Include the retain (store) tool |
enable_recall |
True |
Include the recall (search) tool |
enable_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 |
Hindsight Cloud (https://api.hindsight.vectorize.io) |
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
- agno
- hindsight-client >= 0.4.0
- A running Hindsight API server
License
MIT