Activate Hindsight as the cross-session memory provider for ngn-agent in local embedded mode with latency-optimized settings.
Purpose: Replace the limited built-in MEMORY.md/USER.md (2.2k chars, frozen per-session) with Hindsight's entity-aware knowledge graph memory for persistent cross-session recall. Pure configuration change — no code, no infrastructure, no Docker image changes.
Output:
~/.hermes/hindsight/config.json — Hindsight config with all latency-optimized settings per D-01 through D-10
~/.hermes/.env — HINDSIGHT_LLM_API_KEY env var appended (reuses existing OpenRouter key)
~/.hermes/config.yaml — memory.provider changed to hindsight
Task 1: Create Hindsight config.json and add HINDSIGHT_LLM_API_KEY to .env
~/.hermes/hindsight/config.json (create)
~/.hermes/.env (append)
@/Users/bapung/.hermes/hermes-agent/plugins/memory/hindsight/README.md (source of truth for all config keys)
@/Users/bapung/.hermes/.env (current state — must read before appending)
@/Users/bapung/Razer/ngn-agent/.planning/phases/05-hindsight-memory-provider/05-CONTEXT.md (verify locked decisions D-01 through D-10)
@/Users/bapung/Razer/ngn-agent/.planning/phases/05-hindsight-memory-provider/05-RESEARCH.md (verify exact config values)
Create `~/.hermes/hindsight/config.json` with the following EXACT content (per decisions D-01 through D-10):
```json
{
"mode": "local_embedded",
"llm_provider": "openrouter",
"llm_base_url": "https://openrouter.ai/api/v1",
"llm_model": "qwen/qwen3.5-9b",
"bank_id": "hermes",
"recall_budget": "low",
"recall_prefetch_method": "recall",
"auto_recall": true,
"recall_types": "observation",
"auto_retain": true,
"retain_async": true,
"retain_every_n_turns": 5,
"memory_mode": "hybrid"
}
```
Step-by-step:
1. Read `~/.hermes/.env` to get the current `OPENROUTER_API_KEY` value: `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`
2. Create directory: `mkdir -p ~/.hermes/hindsight`
3. Write the config.json above using Write tool (not heredoc)
4. Append `HINDSIGHT_LLM_API_KEY=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` to `~/.hermes/.env` ONLY if it doesn't already exist (grep first). Add a comment line above it: `# Hindsight — LLM API key for local embedded mode (reuses OpenRouter key)`
Key configuration rationale:
- `mode: local_embedded` (D-01): Local PostgreSQL daemon managed by Hermes. No external data send.
- `llm_provider: openrouter` (D-01): Use existing OpenRouter key. The `llm_base_url` matches OpenRouter's OpenAI-compatible endpoint.
- `llm_model: qwen/qwen3.5-9b` (D-01): Model per-provider default from plugin.
- `bank_id: hermes` (discretion): Default bank name from plugin.
- `recall_budget: low` (D-04): Fastest retrieval, minimal latency overhead per turn.
- `recall_prefetch_method: recall` (D-05): Raw fact search — no LLM synthesis in the hot path.
- `auto_recall: true` (D-06): Auto-inject context before each turn.
- `recall_types: observation` (D-07): Observations only, denser per token.
- `auto_retain: true` (D-10): Automatic retention active.
- `retain_async: true` (D-08): Processing in background, never blocks agent loop.
- `retain_every_n_turns: 5` (D-09): Extract memories every 5 turns (~80% overhead reduction).
- `memory_mode: hybrid` (D-02): Auto-inject relevant memories + expose all 3 hindsight tools (hindsight_retain, hindsight_recall, hindsight_reflect).
- No `bank_mission` or `bank_retain_mission` (discretion): Keep defaults (none).
- Do NOT set `api_url` (not needed for local_embedded mode — plugin defaults to localhost:9177).
- Do NOT set `HINDSIGHT_API_KEY` (not needed for local_embedded — that's for cloud mode).
- `~/.hermes/hindsight/config.json` exists and is valid JSON
- All 13 config keys from D-01 through D-10 are present with correct values as verified by the python validation script
- `HINDSIGHT_LLM_API_KEY=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` is in `~/.hermes/.env`
- `HINDSIGHT_LLM_API_KEY` value is identical to `OPENROUTER_API_KEY` value
Hindsight config.json created with all 13 locked settings, env var added matching existing OpenRouter key
Task 2: Set memory.provider to hindsight, restart gateway, and verify full memory provider activation
~/.hermes/config.yaml (modified via `hermes config set`)
@/Users/bapung/.hermes/hermes-agent/plugins/memory/__init__.py (read the single-provider constraint to understand the activation path)
@/Users/bapung/.hermes/config.yaml (read current memory.provider value — should be empty string before change)
Perform the following STEPS IN ORDER:
STEP 1 — Set memory provider:
Run: `hermes config set memory.provider hindsight`
This modifies `~/.hermes/config.yaml` setting `memory.provider: hindsight`.
NOTE: The current value at line 355 is `provider: ''` (empty string), meaning no external provider is set. After this command, it becomes `provider: hindsight`. The existing `memory.memory_enabled: true` and `memory.user_profile_enabled: true` remain unchanged — built-in memory continues as fallback (per D-03).
STEP 2 — Restart gateway:
Run: `hermes gateway restart`
This reloads config.yaml and activates the Hindsight provider. The plugin will:
- Detect `hindsight-all` is already installed in the venv (verified: 0.8.2)
- Read `~/.hermes/hindsight/config.json`
- Check existing `~/.hindsight/profiles/hermes.env` (already exists from previous attempt)
- Regenerate the profile env if it doesn't match config.json settings (per plugin __init__.py initialize() logic — Pitfall 5 prevention)
- The daemon will NOT start until the first session access (lazy init, not gateway restart)
STEP 3 — Verify provider is active:
Run: `hermes config get memory.provider`
Expected output: `hindsight`
Run: `hermes memory status`
Expected: Shows hindsight as the active memory provider. Output may say "not available" or similar for daemon status since daemon only starts on first session access (this is expected behavior — the provider IS registered, just the daemon hasn't been launched yet).
STEP 4 — Verify no provider conflict:
Run: `grep -i "Rejected memory provider" ~/.hermes/hermes-agent/logs/* 2>/dev/null || echo "No provider conflicts detected"`
Expected: No output (no rejections) since only one provider is set.
STEP 5 — Verify daemon readiness (check daemon binary exists in venv):
Run: `~/.hermes/hermes-agent/venv/bin/hindsight-embed --version 2>&1 || echo "(version flag not supported — this is fine)"`
Expected: Binary exists (no "not found" error).
STEP 6 — Final verification that all components are in place:
Run a comprehensive check combining config file, env var, and provider setting:
```
echo "=== Hindsight Phase 5 Verification ==="
echo "1. Config file: $(test -f ~/.hermes/hindsight/config.json && echo 'EXISTS' || echo 'MISSING')"
echo "2. Provider setting: $(hermes config get memory.provider)"
echo "3. Env var: $(grep -c '^HINDSIGHT_LLM_API_KEY=' ~/.hermes/.env | xargs -I{} echo 'FOUND ({})' )"
echo "4. Package: $(uv pip show hindsight-all --python ~/.hermes/hermes-agent/venv/bin/python 2>/dev/null | grep Version || echo 'NOT FOUND')"
echo "5. Daemon binary: $(ls ~/.hermes/hermes-agent/venv/bin/hindsight-embed 2>/dev/null && echo 'EXISTS' || echo 'NOT FOUND')"
echo "6. Daemon profile: $(ls ~/.hindsight/profiles/hermes.env 2>/dev/null && echo 'EXISTS' || echo 'NOT FOUND')"
echo "================================"
```
# Check provider is set correctly
[ "$(hermes config get memory.provider)" = "hindsight" ] && echo "Provider OK" || echo "Provider FAIL"
# Check no provider conflict in logs
LOG_DIR=~/.hermes/hermes-agent/logs
if [ -d "$LOG_DIR" ]; then
CONFLICT_COUNT=$(grep -c "Rejected memory provider" "$LOG_DIR"/*.log 2>/dev/null || echo 0)
if [ "$CONFLICT_COUNT" = "0" ]; then
echo "No provider conflict detected"
else
echo "WARNING: $CONFLICT_COUNT provider conflict(s) found"
fi
else
echo "No logs yet (no sessions started) — expected at this stage"
fi
# Full config validation using hermes config get (reads live config)
hermes config get memory.provider | grep -q hindsight || echo "CONFIG MISMATCH"
</automated>
- `hermes config get memory.provider` returns `hindsight`
- No "Rejected memory provider" warnings in logs (run `grep` check)
- `hindsight-embed` binary is present in the Hermes venv at `~/.hermes/hermes-agent/venv/bin/hindsight-embed`
- `hermes memory status` runs without errors and shows hindsight as the registered provider
Hindsight memory provider is set as the active external provider, gateway restarted, all verifications pass
Artifacts This Phase Produces
New files
Artifact
Path
Purpose
Hindsight config
~/.hermes/hindsight/config.json
All Hindsight configuration keys per D-01 through D-10
Modified files
Artifact
Path
Change
Env file
~/.hermes/.env
Added HINDSIGHT_LLM_API_KEY env var (same value as OPENROUTER_API_KEY)
Same as existing OPENROUTER_API_KEY in ~/.hermes/.env
New config keys in ~/.hermes/config.yaml
Config Key
Value
Description
memory.provider
hindsight
Enables Hindsight as the active external memory provider
New config keys in ~/.hermes/hindsight/config.json
Key
Value
Decision
mode
local_embedded
D-01
llm_provider
openrouter
D-01
llm_base_url
https://openrouter.ai/api/v1
D-01
llm_model
qwen/qwen3.5-9b
D-01
bank_id
hermes
Discretion
recall_budget
low
D-04
recall_prefetch_method
recall
D-05
auto_recall
true
D-06
recall_types
observation
D-07
auto_retain
true
D-10
retain_async
true
D-08
retain_every_n_turns
5
D-09
memory_mode
hybrid
D-02
<threat_model>
Trust Boundaries
Boundary
Description
Agent process ↔ OpenRouter API
LLM extraction calls (memory entity extraction) cross the process-to-internet boundary with conversation turn data
Agent process ↔ Local PostgreSQL (daemon)
Memory data persisted in local embedded PostgreSQL via localhost:9177 — no network boundary
Agent loop ↔ Hindsight provider
Plugin hooks (queue_prefetch, sync_turn) operate in-process with background threads
STRIDE Threat Register
Threat ID
Category
Component
Disposition
Mitigation Plan
T-05-01
Information Disclosure
OpenRouter API key reused as HINDSIGHT_LLM_API_KEY
mitigate
Key already stored in ~/.hermes/.env with 0600 permissions (existing protection). Same key reused — no new secret to manage. Key is not logged beyond daemon startup.
Daemon failure is non-fatal — agent continues with built-in memory fallback (D-03). Verify daemon log post-session-start. If daemon fails, memories are silently lost (async retain) but agent loop is unaffected.
T-05-03
Elevation of Privilege
Daemon port localhost:9177
mitigate
Daemon binds to localhost only (default). Not exposed to Docker container or network. Confirmed via README — no HINDSIGHT_API_HOST set means 0.0.0.0 is default but only reachable from host.
T-05-04
Information Disclosure
Conversation data sent to OpenRouter for LLM extraction
accept
Local embedded mode means NO external data send to Hindsight Cloud. LLM extraction calls to OpenRouter carry only the conversation turn (~70-200 chars), not full history. This is the same OpenRouter endpoint already used for primary LLM calls. Equivalent risk to existing model calls.
T-05-05
Tampering
Async retain silent failure
accept
Async retain failures are logged as warnings. Mitigation is monitoring (grep "Hindsight retain failed"). Not blocking the agent loop is intentional per D-08.
Package legitimacy verified in RESEARCH.md §Package Legitimacy Audit — all packages from Vectorize.io (same org as Hermes plugin). Already installed at version 0.8.2. No new install needed.
Residual Risk
Risk
Why Accepted
LLM extraction timeout or error causes memory loss for that turn
Async retain swallows failures; memories from that turn are lost. Mitigated by retain_every_n_turns: 5 — next retain window will capture subsequent turns.
OpenRouter rate limiting on extraction calls
Same key used for model calls and extraction; extraction happens every 5 turns (~70-200 chars), which is negligible compared to model call traffic.
hermes config get memory.provider returns hindsight — provider activated
~/.hermes/hindsight/config.json exists with valid JSON containing all 13 locked settings — config complete
grep HINDSIGHT_LLM_API_KEY ~/.hermes/.env returns the env var matching OPENROUTER_API_KEY — LLM extraction configured
~/.hermes/hermes-agent/venv/bin/hindsight-embed binary exists — daemon ready for first session start
No "Rejected memory provider" warnings in gateway logs — no provider conflict
Built-in MEMORY.md/USER.md continues working in parallel (no config changes to memory_enabled/user_profile_enabled) — fallback preserved per D-03
</success_criteria>
Create `.planning/phases/05-hindsight-memory-provider/05-01-SUMMARY.md` when done