Hindsight Memory
Hindsight retain/recall memory integration for Agent Zero using lifecycle hooks.
README
Hindsight Memory for Agent Zero
Hindsight Memory connects Agent Zero to a self-hosted Hindsight memory service so conversations can use durable long-term memory.
The plugin can:
- recall relevant memories before an Agent Zero response,
- inject those memories as context into the prompt,
- retain useful conversation context after a response,
- answer explicit memory questions through agent-callable tools,
- fail open when Hindsight is unavailable so Agent Zero keeps working.
It is designed for private or self-hosted memory deployments. Do not point it at an untrusted public Hindsight endpoint for private conversations.
Status
| Item | Current value |
|---|---|
| Plugin ID | a0hindsight |
| Version | 0.4.0 |
| Runtime type | Agent Zero user plugin |
| Settings scope | Per agent profile, per project |
| Default memory mode | hybrid |
| Default bank strategy | a0:v2:project:<slug>-<hash> (project-scoped) |
| Default service URL | http://host.docker.internal:8888 |
| Repository | git@github.com:Jehu/a0-hindsight.git |
Implemented:
- automatic prompt-time recall,
- background retain,
- dynamic agent-profile bank IDs,
- settings UI,
- retain filtering and redaction baseline,
- Hindsight bank mission configuration,
- optional Hindsight Reflect path,
- agent tools for recall, reflect, and retain,
- deadline, cache, and circuit-breaker safeguards,
- optional Bearer API key auth (settings, env var, A0 secrets store),
- automatic project and repo tagging on retains.
Requirements
You need:
- Agent Zero with user-plugin support.
- A reachable Hindsight API service.
- Network access from the Agent Zero container to Hindsight.
The plugin expects compatible Hindsight endpoints for:
| Endpoint | Purpose |
|---|---|
GET /health |
Health check |
PUT /v1/default/banks/{bank_id} |
Apply bank-level missions/settings |
POST /v1/default/banks/{bank_id}/memories/recall |
Raw memory recall |
POST /v1/default/banks/{bank_id}/reflect |
Synthesized memory answers |
POST /v1/default/banks/{bank_id}/memories |
Retain memories |
Default local service URL:
http://host.docker.internal:8888
Authentication
The plugin sends requests without auth headers by default, which works with
unsecured local deployments. For secured Hindsight instances (for example an
ApiKeyTenantExtension fronting a shared central bank), enable Bearer auth:
Authorization: Bearer <key>
The key is resolved in this order:
api_keysetting,HINDSIGHT_API_KEYenvironment variable,- Agent Zero secrets store (
usr/secrets.env, plus project secrets).
An empty key keeps the legacy no-auth behavior. The key is only used in HTTP headers and never appears in logs or retained metadata.
Installation
Clone the plugin into Agent Zero's user plugin directory:
git clone git@github.com:Jehu/a0-hindsight.git /a0/usr/plugins/a0hindsight
The manifest must be located at:
/a0/usr/plugins/a0hindsight/plugin.yaml
Then restart Agent Zero or refresh the plugin list. The plugin should appear as:
a0hindsight
Enable it through the Agent Zero Plugins UI. A local runtime toggle may also exist:
/a0/usr/plugins/a0hindsight/.toggle-1
Runtime toggle files, local config, caches, and .env files are intentionally not part of the repository.
How it works
The plugin participates in two main lifecycle points:
- Before the model response: it can recall relevant memories from Hindsight and inject them into the system prompt as context.
- After the model response: it can retain recent conversation context in Hindsight for future use.
Hindsight is treated as helpful context, not as a hard dependency. If the service is slow or offline, the plugin logs the issue and Agent Zero continues without memory context.
Memory modes
memory_mode controls how the plugin participates in a turn.
| Mode | Automatic prompt recall | Agent-callable tools | Recommended use |
|---|---|---|---|
context |
yes | no | Quiet automatic memory context only |
tools |
no | yes | No automatic injection; agent uses memory only when needed |
hybrid |
yes | yes | Recommended default: fast context plus explicit tools |
off |
no | no | Fully disable memory behavior without disabling the plugin |
Default:
memory_mode: "hybrid"
The plugin does not use keyword matching or an extra LLM classifier to decide when to switch between recall and reflect. The behavior is explicit:
- automatic recall uses the configured
recall_method, - high-quality synthesized memory answers are available through the
hindsight_reflecttool, - users or agents can explicitly call memory tools when needed.
Agent tools
When memory_mode is tools or hybrid, the plugin exposes three tools.
| Tool | Purpose | Typical use |
|---|---|---|
hindsight_recall |
Raw Hindsight recall | Fast lookup of matching memories |
hindsight_reflect |
Synthesized answer from Hindsight memory | Questions like “what do you remember about my preferences?” |
hindsight_retain |
Explicit durable memory write | Store an important preference, decision, or project fact |
hindsight_recall
Use for fast retrieval of matching memories.
Common arguments:
| Argument | Description |
|---|---|
query |
Required memory search query |
bank_id |
Optional override; defaults to the agent-profile bank |
budget |
Optional Hindsight budget, e.g. low, mid, high |
max_tokens |
Optional response budget |
types |
Optional memory types, e.g. world |
tags |
Optional tag filter |
tags_match |
any or all |
hindsight_reflect
Use for explicit memory questions where a synthesized answer is better than raw snippets.
Common arguments:
| Argument | Description |
|---|---|
query |
Required memory question |
bank_id |
Optional override |
budget |
Optional Hindsight budget |
max_tokens |
Optional answer budget |
fact_types |
Optional memory types to consider |
tags |
Optional tag filter |
include_facts |
Include supporting evidence when available |
Reflect is slower than raw recall, but it can answer natural preference questions better than simple similarity search.
hindsight_retain
Use to explicitly store a durable fact.
Common arguments:
| Argument | Description |
|---|---|
content |
Required text to store |
context |
Optional retain context/instruction |
bank_id |
Optional override |
tags |
Optional tags |
document_prefix |
Optional document ID prefix |
async_mode |
Queue retain work asynchronously when supported |
Store only durable information: user preferences, project facts, stable decisions, and reusable constraints. Do not store secrets.
Settings UI
The plugin provides a configuration panel in Agent Zero settings for agent profiles because plugin.yaml contains:
settings_sections:
- agent
per_agent_config: true
Use the Settings modal Save button to persist changes.
The UI covers:
- plugin enablement,
- memory mode,
- Hindsight base URL and API key,
- bank ID override and bank ID prefix,
- bank missions for reflect, retain, and observations,
- recall deadlines, budget, tags, types, cache, and circuit breaker,
- retain policy, context size, async mode, redaction/noise controls,
- automatic project and repo tagging toggles,
- observability settings.
Configuration reference
Defaults live in:
/a0/usr/plugins/a0hindsight/default_config.yaml
Important settings:
| Setting | Default | Purpose |
|---|---|---|
enabled |
true |
Master plugin switch |
memory_mode |
hybrid |
Controls automatic context and tool availability |
base_url |
http://host.docker.internal:8888 |
Hindsight API base URL |
api_key |
empty | Optional Bearer token for API auth; falls back to HINDSIGHT_API_KEY env var |
bank_id |
empty | Optional explicit bank ID override |
bank_config_timeout_seconds |
5 |
Timeout for applying bank-level settings |
reflect_mission |
see config | Mission used by Hindsight Reflect |
retain_mission |
see config | Mission used by Hindsight retain/extraction |
retain_extraction_mode |
custom |
Hindsight retain extraction mode; empty = keep bank default, no bank override (recommended for shared banks) |
retain_project_tag |
true |
Tag retains from an active project with project:<name> (coding-agents compatible) |
retain_repo_tags |
true |
Add repo:<name> tags for git repos referenced by file paths in the retained content (multi-repo aware) |
retain_custom_instructions |
see config | Durable-memory extraction guidance |
enable_observations |
true |
Enables Hindsight observation consolidation |
observations_mission |
see config | Guides observation synthesis |
recall_enabled |
true |
Enables prompt-time recall when context mode is active |
retain_enabled |
true |
Enables retain after responses |
recall_mode |
deadline |
Fail-open recall mode for prompt path |
recall_method |
recall |
recall for raw recall or reflect for synthesized prompt injection |
recall_deadline_ms |
2200 |
Normal prompt-path recall deadline |
recall_http_timeout_seconds |
3.0 |
Hindsight recall HTTP timeout |
recall_force_deadline_ms |
3200 |
Longer deadline for forced memory questions |
recall_timeout_seconds |
3 |
Legacy compatibility field |
recall_budget |
low |
Hindsight recall budget |
recall_max_tokens |
400 |
Maximum recall/reflect result budget |
recall_query_max_chars |
800 |
Local query length cap |
recall_types |
observation |
Memory types used by default recall |
prefer_observations |
true |
Ask Hindsight to prefer observations when available |
recall_tags |
agent-zero, hindsight |
Tags used for recall filtering |
recall_tags_match |
any |
Recall tag match mode |
retain_tags |
agent-zero, hindsight |
Tags applied to retained content |
retain_async |
true |
Queue retain work asynchronously when supported |
retain_timeout_seconds |
12 |
Retain HTTP timeout |
retain_context_chars |
5000 |
Retained conversation character cap |
retain_min_chars |
80 |
Skip retain below this size |
retain_document_prefix |
a0-chat |
Prefix for retained documents |
inject_heading |
Hindsight recalled memories |
Heading for injected prompt context |
log_enabled |
true |
Emit Agent Zero log entries |
observability_verbose |
true |
Include detailed log fields |
retain_policy_enabled |
true |
Apply local retain filtering |
retain_skip_if_no_user_message |
true |
Skip retain for no-user turns |
retain_strip_tool_results |
true |
Collapse obvious tool-result noise |
retain_max_tool_result_chars |
400 |
Max preserved chars for collapsed tool blocks |
retain_recent_history_chars |
5000 |
Recent-history cap for retain policy |
Retain-side reflect is reserved for a future rollout:
| Setting | Default | Note |
|---|---|---|
reflect_enabled |
false |
Retain-side rollout flag; not needed for hindsight_reflect tool |
For most users, leave this advanced flag unchanged.
Bank ID strategy
By default, memories are scoped by Agent Zero project (shared across agent profiles within the same project):
a0:v2:project:<project_slug>-<hash>
For the default agent0 profile, the bank is:
a0:v2:project:hindsight_implementation-<hash>
You can override this with bank_id if you want a fixed bank. If bank_id is non-empty, it fully replaces the dynamic strategy.
Project-scoped routing is the default (bank_scope: project). Set bank_scope: agent for a per-agent-profile bank, or explicit to require bank_id.
Recall behavior and latency safeguards
Prompt-time recall is designed to be safe for interactive use:
- Trivial acknowledgements can be skipped by conditional recall.
- Normal recall waits only up to
recall_deadline_ms. - Explicit forced recall can use
recall_force_deadline_ms. - Hindsight HTTP calls have their own timeout.
- Exact cache hits are used only for identical query and settings dimensions.
- Repeated service failures open a circuit breaker to avoid repeated slow failures.
- Misses, failures, and deadline misses fail open.
This means Hindsight can improve context, but should not block normal Agent Zero operation.
Retain behavior
Retain runs after responses and is asynchronous by default.
Before content is sent to Hindsight, the plugin can:
- skip no-user turns,
- cap retained history size,
- collapse obvious large tool-result blocks,
- redact common secret-looking strings,
- skip very short content,
- attach metadata such as source, plugin name, agent profile, bank strategy, context ID, redaction count, and tool-block count.
Automatic project and repo tags
Retains are tagged with project and repository context, compatible with the
coding-agents project:{gitProject} convention:
- Project tag (
retain_project_tag, default on): every retain from an active Agent Zero project getsproject:<project-name>. This covers non-git projects too and matches coding-agents tags exactly whenever the repository name equals the project name. - Repo tags (
retain_repo_tags, default on): every git repository actually referenced by a file path in the retained conversation content adds arepo:<name>tag. Unlike a CWD-based single tag, a conversation touching several nested repositories gets several tags, and conversations without repository paths get none. The repository named after the project itself is skipped to avoid duplicating the project tag.
The repository index is cached per project (TTL 300s, scan depth 6, pruning
node_modules, venvs, and caches). Explicit tags passed to the
hindsight_retain tool bypass this enrichment.
The configured retain mission and custom instructions tell Hindsight to prefer durable facts such as:
- explicit user preferences,
- tool and workflow preferences,
- package manager preferences,
- project facts,
- stable implementation decisions,
- recurring constraints.
Observability
When log_enabled is true, the plugin writes Agent Zero log entries for important memory events, including:
- bank configuration applied or failed,
- recall skipped,
- recall started,
- recall completed with no memories,
- recall completed with injected memories,
- recall deadline miss or failure,
- retain skipped,
- retain started,
- retain completed,
- retain queued after timeout fallback,
- retain failed.
When observability_verbose is true, logs can include fields such as:
bank=<bank_id> query_chars=<n> content_chars=<n> results=<n> latency_ms=<n> redactions=<n> tool_blocks_collapsed=<n>
WebUI notifications on critical failures
The plugin raises Agent Zero WebUI notifications (with a helpful hint) when a critical Hindsight failure occurs, so degraded memory is visible without reading logs. Each notification type is de-duplicated with a 5-minute cooldown to avoid flooding the UI.
| Trigger | Hint |
|---|---|
| Circuit breaker opens | Recall paused; check that the Hindsight API and PostgreSQL are running. Auto-retries after 60s. |
| Recall connection failure | Recall could not run; verify API reachability and database health. |
| Retain failure | Memories could not be stored; verify API reachability and database health. |
Persistent JSONL file logging
Optional structured file logging (off by default) writes one JSON object per line to a rotating file. Secrets (API keys, tokens, passwords) are redacted and custom log directories are constrained to the allowed log base.
| Setting | Default | Purpose |
|---|---|---|
file_log_enabled |
false |
Enable JSONL file logging |
file_log_dir |
empty | Custom log dir (must resolve under the allowed base) |
file_log_level |
debug |
Minimum level: debug < info < util < warning < error |
file_log_max_bytes |
5000000 |
Rotation size per file |
file_log_backup_count |
3 |
Number of rotated backups to keep |
Default path: /a0/usr/logs/a0hindsight/hindsight.log.jsonl (or
$A0_LOGS_DIR/a0hindsight/ when set).
Smoke tests and verification
Run the plugin smoke script (no PYTHONPATH needed; it resolves the framework root itself):
cd /a0/usr/plugins/a0hindsight
/opt/venv-a0/bin/python execute.py
The smoke script uses the effective plugin configuration:
base_url,bank_id/bank_scope, recall parameters and the API key come from the plugin config (config.jsonviahelpers.plugins.get_plugin_config, with a directconfig.jsonfallback) and the A0 secrets store (HINDSIGHT_API_KEY).HINDSIGHT_BASE_URL/HINDSIGHT_BANK_IDenv vars still override the config.- With
bank_scope: projectand no active project (execute runs outside the agent loop), it falls back to the agent bank so the smoke test always runs. - The script removes its own directory from
sys.pathfirst, so the plugin'shelperspackage cannot shadow the framework's top-levelhelpersnamespace.
Run unit tests:
cd /a0/usr/plugins/a0hindsight
PYTHONPATH=/a0 /opt/venv-a0/bin/python -m pytest tests/ -v
99 tests passing as of v0.4.0.
Run a compile check:
cd /a0/usr/plugins/a0hindsight
PYTHONPATH=/a0 /opt/venv-a0/bin/python -m py_compile \
helpers/client.py \
helpers/repo_tags.py \
helpers/recall_policy.py \
helpers/recall_manager.py \
helpers/runtime.py \
tools/*.py
Run the recall benchmark:
cd /a0/usr/plugins/a0hindsight
PYTHONPATH=/a0 /opt/venv-a0/bin/python scripts/recall_benchmark.py \
--iterations 5 \
--output /a0/usr/workdir/hindsight_recall_benchmark.json
Benchmark queries are stored in:
scripts/recall_benchmark_queries.json
Troubleshooting
Plugin does not appear
Check:
ls /a0/usr/plugins/a0hindsight/plugin.yaml
PYTHONPATH=/a0 /opt/venv-a0/bin/python -c "import yaml; yaml.safe_load(open('/a0/usr/plugins/a0hindsight/plugin.yaml')); print('ok')"
Restart Agent Zero or refresh plugins after installing or changing manifest files.
No memories are recalled
Check:
- plugin is enabled,
memory_modeiscontextorhybrid,recall_enabledis true,base_urlpoints to a reachable Hindsight service,- the current agent profile uses the bank you expect,
- recall tags/types are not filtering out relevant memories.
Tools are unavailable
Check:
memory_modeistoolsorhybrid,- plugin is enabled,
- Agent Zero has refreshed plugin discovery after the
tools/files were added.
Reflect works but is slow
That is expected. Reflect synthesizes an answer from memory and can be much slower than raw recall. Keep automatic prompt injection on recall_method: recall for interactive speed and use hindsight_reflect for explicit memory questions.
Hindsight is offline or slow
Agent Zero should continue normally. Check Agent Zero logs for Hindsight warnings and check the Hindsight service health endpoint:
curl -s http://host.docker.internal:8888/health
Security and privacy
- Use a private, trusted Hindsight service for private conversations.
- Do not intentionally store credentials, API keys, passwords, private keys, or access tokens.
- The plugin includes basic redaction, but it is not a full data-loss-prevention system.
- Review retained memories and Hindsight service access controls according to your deployment needs.
- Treat Hindsight memories as context, not as current user instructions. Current chat instructions should take precedence.
Repository layout
plugin.yaml
README.md
default_config.yaml
execute.py
helpers/
bank_scope.py
client.py
file_logger.py
recall_cache.py
recall_circuit.py
recall_errors.py
recall_manager.py
recall_policy.py
repo_tags.py
runtime.py
hooks.py
extensions/
python/
message_loop_prompts_after/
_56_hindsight_recall.py
monologue_end/
_56_hindsight_retain.py
tools/
hindsight_recall.py
hindsight_reflect.py
hindsight_retain.py
webui/
config.html
scripts/
recall_benchmark.py
recall_benchmark_queries.json
tests/
Known limitations
- Existing memories in older banks are not migrated automatically (use the migration script in
scripts/). - Retain filtering is conservative and may still store more context than ideal.
- Reflect is intentionally explicit because it is slower than raw recall.
Roadmap
Planned improvements:
- Improve duplicate suppression and durable-memory extraction quality.
- Implement retain-side reflect (currently reserved behind
reflect_enabled).
License
Released under the MIT License. See LICENSE for the full text.