Hindsight: Architecture

Level 2 (Topic). Parent hub: hindsight.

Concept

Hindsight (Vectorize.io) is the multi-agent memory platform adopted by TazLab on 2026-08-28. Unlike Mnemosyne (single-vector semantic recall over raw memory blobs), Hindsight runs an LLM extraction pipeline that decomposes ingested content into facts, entities, and relationships, then serves recall by fusing four search strategies. It is the searchable memory layer agents share across projects — the “remember for me” counterpart to the durable wiki.

Platform Capabilities (v0.9.2, verified)

  • Extraction: LLM-driven fact/entity/relationship extraction per retained document.
  • Recall: 4 strategies — semantic (pgvector), BM25, graph expansion, temporal — fused via RRF reranker.
  • Memory banks: multiple isolated banks per endpoint; every bank is addressable at /mcp/{bank_id}/.
  • Native MCP: 36 tools exposed over stateless streamable HTTP.
  • Always-on directives: bank-level rules injected into every session.
  • Mental models: living synthesis documents auto-refreshed at consolidation.
  • Knowledge base: curated document store alongside episodic memory.

Architecture: 3 Stateless Pods (namespace hindsight)

PodImageRole
hindsight-apihindsight-api:0.9.2-slimREST + MCP server on :8888 (HINDSIGHT_API_WORKER_ENABLED=false)
hindsight-workersame image, command: hindsight-workerAsync extraction/embedding pipeline; static WORKER_ID=hindsight-worker-1; metrics :8889
hindsight-dashboardhindsight-control-plane:0.9.2Control plane UI on :9999; talks to the API in-cluster

Zero PVCs by design. All state (memories, facts, vectors, operations, directives) lives in PostgreSQL — the PGO-managed tazlab-db cluster, database hindsight, dedicated schema hindsight. This is deliberate: TazLab treats full cluster destroy/create cycles as a normal operation (ephemeral-castle rebirth protocol), so a stateful memory platform must survive pod, node, and whole-cluster loss. PostgreSQL gives that survival (S3 backups) plus pgvector, while every pod can be recreated freely. Deployment specifics live in the Deployment Detail.

Bank Model

Single shared bank tazlab-common (user-ratified design of the memory-migration-hindsight project), organized in three layers:

  1. Dated memories — all legacy and operational content retained with timestamp = occurred date (never default-to-now).
  2. Doctrine as timeless memoriestimestamp="unset", tag doctrine (system-state, debts, golden rules).
  3. Bank directives — always-on rules; 8 active: secrets-no-cleartext, git-first-anti-drift, english-only, everything-logged, enterprise-grade-homelab, research-first-verify-always, dates-are-sacred, independent-review-before-build.

Plus a mental model tazlab-operating-doctrine — a living synthesis of the doctrine layer, auto-refreshed at consolidation.

Per-agent banks (hermes, tazpod, openclaw) exist alongside the shared bank for agent-private context. A multi-tenant single-bank extension was evaluated and rejected (upstream issue #1556): separate banks are simpler and avoid cross-agent leakage.

LLM/Embedding Split and Quota Reality

  • LLM extraction runs through the opencode-go gateway, model mimo-v2.5 — the same gateway Hermes uses (zen plan quota, shared).
  • Embeddings use gemini-embedding-001 at 768 dimensions, with the cluster-wide cluster/gemini/api-key. The free tier allows 1000 requests/day, shared with Mnemosyne and other consumers — the binding constraint of any bulk import.
  • The worker self-throttles on HTTP 429 (retry + backoff), but failed retain operations save content without vectors: the facts exist but are invisible to recall, and there is no self-heal. The quota wall was hit once during migration (50 failed operations, 2026-08-29 01:14–01:31 UTC, 429 RESOURCE_EXHAUSTED, recovered by retry).
  • Consequence: bulk imports use adaptive pacing — honor Google’s retryDelay plus a safety margin, never hammer.

MCP Surface (36 tools)

Main tools: retain (async; timestamp = occurred date), sync_retain, recall (4-strategy search), reflect (synthesis with optional trace), 7 mental-model tools, 3 directive tools, 7 knowledge-base tools, plus documents/operations/tags management. Access is bearer-token protected (token from Vault, never persisted).

Migration Protocols (memory-migration-hindsight)

The legacy memory migration (CRISP project memory-migration-hindsight) converts the 745-memory Mnemosyne corpus plus chronicles, reports, and doctrine into tazlab-common. Its two operational protocols:

  • mark-before-advance: per-item atomic state in import-state.json (retained_at + operation_id) before the runner advances — a kill at any point resumes losslessly and idempotently (provenance tags + metadata.legacy_id make re-runs duplicate-free).
  • done = operation completed AND searchable: a retain is “done” only when its operation completed and the content is recallable. Failed ops (429) persist content without vectors — invisible to recall — so they are retried, not marked. Batch order: chronological per-source (2024 → 2025 → 2026 → chronicles → reports → doctrine → directives/mental model).

Key discovery: the Mnemosyne writer LLM had hallucinated years — cluster “2024-05” is really Jan–Feb 2026, “2024-12” is really Dec 2025 (proven against git tags and real chat files in the obsidian.brain vault). A 4-agent independent date audit corrected 38/38 dates; the bank was purged and re-imported from corrected batches.

Live status (import-state.json, 2026-08-30):

SourceDone
session-2026-08-28 (deployment session memories)10/10
mnemosyne-corrected-2025-1217/17
mnemosyne-corrected-2026-014/4
mnemosyne-corrected-2026-0217/17
mnemosyne-2025-12 (B2)59/59
mnemosyne-2026-01 (B3)30/144 — in progress
Total137

Remaining after B3: 2026-02 (296) + later-2026 batches, 19 chronicle archives, 57 reports, doctrine (unset-timestamp), directives + mental model. Mnemosyne stays read-only until user sign-off; its decommission is a separate future project.

Known Verification Findings (deep verification 2026-08-29)

  • recall output drops entities: 381/561 units carry entity data in storage, but the recall MCP schema never returns them and no parameter exposes them (extraction works; output-schema gap).
  • occurred_start is populated only when fact text contains an explicit date; migrated items without in-text dates keep occurred_start = null while the unit date field stays correct — date-filtered recall misses them.
  • Temporal-query top ranks can be polluted by the recently-embedded session batch.
  • Bank mission is empty; source:report tag absent (reports not migrated yet).

See Also