375 lines
20 KiB
Markdown
375 lines
20 KiB
Markdown
---
|
|
phase: 05-hindsight-memory-provider
|
|
plan: 01
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified:
|
|
- ~/.hermes/hindsight/config.json
|
|
- ~/.hermes/.env
|
|
- ~/.hermes/config.yaml
|
|
autonomous: true
|
|
requirements:
|
|
- MEM-01
|
|
user_setup: []
|
|
|
|
must_haves:
|
|
truths:
|
|
- "`hermes config get memory.provider` returns `hindsight`"
|
|
- "`~/.hermes/hindsight/config.json` exists with all locked config keys from D-04 through D-10"
|
|
- "`grep HINDSIGHT_LLM_API_KEY ~/.hermes/.env` returns the env var with the same value as OPENROUTER_API_KEY"
|
|
- "Hindsight daemon starts on first session init (verifiable via `~/.hermes/logs/hindsight-embed.log`)"
|
|
- "Agent has all 3 hindsight tools available (hindsight_retain, hindsight_recall, hindsight_reflect) in hybrid mode"
|
|
artifacts:
|
|
- path: "~/.hermes/hindsight/config.json"
|
|
provides: "Hindsight memory provider configuration with latency-optimized settings"
|
|
contains: "mode: local_embedded, recall_budget: low, retain_every_n_turns: 5, retain_async: true, memory_mode: hybrid"
|
|
- path: "~/.hermes/.env"
|
|
provides: "HINDSIGHT_LLM_API_KEY env var for daemon LLM extraction"
|
|
contains: "HINDSIGHT_LLM_API_KEY=sk-or-v1-"
|
|
- path: "~/.hermes/config.yaml"
|
|
provides: "memory.provider set to hindsight"
|
|
key_links:
|
|
- from: "~/.hermes/hindsight/config.json"
|
|
to: "~/.hermes/.env"
|
|
via: "HINDSIGHT_LLM_API_KEY env var in daemon startup"
|
|
pattern: "HINDSIGHT_LLM_API_KEY"
|
|
- from: "~/.hermes/config.yaml"
|
|
to: "plugins/memory/hindsight/__init__.py"
|
|
via: "memory.provider: hindsight activates HindsightMemoryProvider"
|
|
pattern: "memory.provider.*hindsight"
|
|
---
|
|
|
|
<objective>
|
|
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`
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/Users/bapung/.config/opencode/gsd-core/workflows/execute-plan.md
|
|
@/Users/bapung/.config/opencode/gsd-core/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@/Users/bapung/Razer/ngn-agent/.planning/phases/05-hindsight-memory-provider/05-CONTEXT.md
|
|
@/Users/bapung/Razer/ngn-agent/.planning/phases/05-hindsight-memory-provider/05-RESEARCH.md
|
|
|
|
# Existing state to read before modifying
|
|
@/Users/bapung/.hermes/config.yaml
|
|
@/Users/bapung/.hermes/.env
|
|
@/Users/bapung/.hermes/hermes-agent/plugins/memory/hindsight/README.md
|
|
|
|
# Critical constraint — single provider only
|
|
@/Users/bapung/.hermes/hermes-agent/plugins/memory/__init__.py
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Create Hindsight config.json and add HINDSIGHT_LLM_API_KEY to .env</name>
|
|
<files>
|
|
~/.hermes/hindsight/config.json (create)
|
|
~/.hermes/.env (append)
|
|
</files>
|
|
<read_first>
|
|
@/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)
|
|
</read_first>
|
|
<action>
|
|
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).
|
|
</action>
|
|
<verify>
|
|
<automated>
|
|
test -f ~/.hermes/hindsight/config.json && echo "config.json EXISTS" || echo "config.json MISSING"
|
|
|
|
# Validate JSON syntax
|
|
python3 -c "import json; json.load(open('$HOME/.hermes/hindsight/config.json')); print('JSON VALID')"
|
|
|
|
# Verify all locked keys are present
|
|
python3 -c "
|
|
import json
|
|
c = json.load(open('$HOME/.hermes/hindsight/config.json'))
|
|
checks = {
|
|
'mode': c.get('mode') == 'local_embedded',
|
|
'llm_provider': c.get('llm_provider') == 'openrouter',
|
|
'llm_base_url': c.get('llm_base_url') == 'https://openrouter.ai/api/v1',
|
|
'llm_model': c.get('llm_model') == 'qwen/qwen3.5-9b',
|
|
'bank_id': c.get('bank_id') == 'hermes',
|
|
'recall_budget': c.get('recall_budget') == 'low',
|
|
'recall_prefetch_method': c.get('recall_prefetch_method') == 'recall',
|
|
'auto_recall': c.get('auto_recall') == True,
|
|
'recall_types': c.get('recall_types') == 'observation',
|
|
'auto_retain': c.get('auto_retain') == True,
|
|
'retain_async': c.get('retain_async') == True,
|
|
'retain_every_n_turns': c.get('retain_every_n_turns') == 5,
|
|
'memory_mode': c.get('memory_mode') == 'hybrid',
|
|
}
|
|
all_ok = all(checks.values())
|
|
for k, v in checks.items():
|
|
status = 'OK' if v else 'FAIL'
|
|
print(f' [{status}] {k}: {c.get(k)}')
|
|
assert all_ok, 'Config validation FAILED'
|
|
print('ALL CHECKS PASSED')
|
|
"
|
|
|
|
# Verify HINDSIGHT_LLM_API_KEY exists in .env and matches OPENROUTER_API_KEY
|
|
OR_KEY=$(grep '^OPENROUTER_API_KEY=' ~/.hermes/.env | cut -d= -f2-)
|
|
HL_KEY=$(grep '^HINDSIGHT_LLM_API_KEY=' ~/.hermes/.env | cut -d= -f2-)
|
|
if [ "$OR_KEY" = "$HL_KEY" ]; then echo "ENV KEY MATCH: $OR_KEY"; else echo "ENV KEY MISMATCH"; fi
|
|
</automated>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- `~/.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
|
|
</acceptance_criteria>
|
|
<done>Hindsight config.json created with all 13 locked settings, env var added matching existing OpenRouter key</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Set memory.provider to hindsight, restart gateway, and verify full memory provider activation</name>
|
|
<files>
|
|
~/.hermes/config.yaml (modified via `hermes config set`)
|
|
</files>
|
|
<read_first>
|
|
@/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)
|
|
</read_first>
|
|
<action>
|
|
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 "================================"
|
|
```
|
|
</action>
|
|
<verify>
|
|
<automated>
|
|
# 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>
|
|
</verify>
|
|
<acceptance_criteria>
|
|
- `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
|
|
</acceptance_criteria>
|
|
<done>Hindsight memory provider is set as the active external provider, gateway restarted, all verifications pass</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
## 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`) |
|
|
| Hermes config | `~/.hermes/config.yaml` | Changed `memory.provider` from `""` to `hindsight` |
|
|
|
|
### New env vars
|
|
| Env Var | Value | Source |
|
|
|---------|-------|--------|
|
|
| `HINDSIGHT_LLM_API_KEY` | `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` | 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. |
|
|
| T-05-02 | Denial of Service | Daemon startup failure / PostgreSQL embedded crash | mitigate | 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. |
|
|
| T-05-SC | Tampering | Python package installations (`hindsight-all`, `hindsight-client`, `hindsight-embed`, `hindsight-api-slim`) | mitigate | 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. |
|
|
</threat_model>
|
|
|
|
<verification>
|
|
Run after all tasks complete:
|
|
|
|
```bash
|
|
echo "=== Phase 5 Full Verification ==="
|
|
echo "--- Step 1: Provider Check ---"
|
|
hermes config get memory.provider
|
|
|
|
echo "--- Step 2: Config File ---"
|
|
python3 -c "import json; c=json.load(open('$HOME/.hermes/hindsight/config.json')); print('mode:', c['mode']); print('budget:', c['recall_budget']); print('async retain:', c['retain_async']); print('every_n:', c['retain_every_n_turns']); print('memory_mode:', c['memory_mode'])"
|
|
|
|
echo "--- Step 3: Env Var ---"
|
|
grep '^HINDSIGHT_LLM_API_KEY=' ~/.hermes/.env | grep -o '^HINDSIGHT_LLM_API_KEY=sk-or-v1-' && echo "Format OK"
|
|
|
|
echo "--- Step 4: Package ---"
|
|
uv pip show hindsight-all --python ~/.hermes/hermes-agent/venv/bin/python 2>/dev/null | grep -E '(Name|Version)'
|
|
|
|
echo "--- Step 5: Daemon Binary ---"
|
|
ls -la ~/.hermes/hermes-agent/venv/bin/hindsight-embed 2>/dev/null
|
|
|
|
echo "--- Step 6: Daemon Profile (pre-existing) ---"
|
|
ls -la ~/.hindsight/profiles/hermes.env 2>/dev/null
|
|
|
|
echo "--- Step 7: Provider Conflict Check ---"
|
|
grep -i "Rejected memory provider" ~/.hermes/hermes-agent/logs/*.log 2>/dev/null || echo "No conflicts"
|
|
|
|
echo "=== Verification Complete ==="
|
|
```
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
1. `hermes config get memory.provider` returns `hindsight` — provider activated
|
|
2. `~/.hermes/hindsight/config.json` exists with valid JSON containing all 13 locked settings — config complete
|
|
3. `grep HINDSIGHT_LLM_API_KEY ~/.hermes/.env` returns the env var matching OPENROUTER_API_KEY — LLM extraction configured
|
|
4. `~/.hermes/hermes-agent/venv/bin/hindsight-embed` binary exists — daemon ready for first session start
|
|
5. No "Rejected memory provider" warnings in gateway logs — no provider conflict
|
|
6. 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>
|
|
|
|
<output>
|
|
Create `.planning/phases/05-hindsight-memory-provider/05-01-SUMMARY.md` when done
|
|
</output>
|