Phase 3 core memory substrate
Phase 3 — Memory Engine and Operator Platform — Decision Log
Python stack choices and ADR decisions for the Memory Engine and Operator Platform phase.
Phase 3 — Decision Log
Quick decisions during Phase 3. Promote durable choices to docs/adr/ and the public ADR index when they affect multiple phases.
Python stack (non-negotiable)
| Concern | Choice | Reason |
|---|---|---|
| Python version | 3.11 | Performance over 3.10; 3.12 not yet stable across ML libs |
| Web framework | FastAPI 0.110+ | Native async, automatic OpenAPI, DI |
| ORM | SQLAlchemy 2.0 (async) | Type-safe async queries, pgvector support |
| Migrations | Alembic | Standard SQLAlchemy companion |
| Config | pydantic-settings v2 | Typed, validated .env support |
| Testing | pytest + pytest-asyncio | asyncio_mode="auto" |
| Linting | ruff + mypy --strict | Single tool, fast |
| Task queue | Celery 5 + Redis broker | Industry standard |
| gRPC | grpcio + betterproto | Dataclass codegen, mypy-friendly |
| HTTP client | httpx (async) | Better typing than aiohttp |
| Embeddings | sentence-transformers 2.x | HuggingFace model flexibility |
| Packaging | pyproject.toml + uv | Fast installs |
ADR register (Phase 3 — Accepted)
| ADR | Topic | Milestone | Status |
|---|---|---|---|
| ADR-0047 | Temporal validity columns | 3.1.1 foundation | Accepted |
| ADR-0048 | Multi-label memory_labels | 3.1.1 / 3.C.4 | Accepted |
| ADR-0049 | memory_relationships graph | 3.1.1 foundation | Accepted |
| ADR-0052 | Memory schema v2 expand (HNSW, quality columns) | 3.1.1 | Accepted |
| ADR-0053 | VectorStore + composite scoring v2 | 3.2.1 / 3.D.2 | Accepted |
| ADR-0054 | Write-path Presidio PII | 3.C.1 | Accepted |
| ADR-0055 | Exact/near dedup | 3.C.2 | Accepted |
| ADR-0056 | Temporal-interval conflict detection | 3.C.3 | Accepted |
| ADR-0057 | Write-path persistence orchestration | 3.C.5 | Accepted |
| ADR-0058 | FTS fallback trigger | 3.D.1 | Accepted |
| ADR-0059 | Hot cache read path (Redis ZSET) | 3.D.3 | Accepted |
| ADR-0060 | Memory tenant isolation + read-path PII guard | 3.E.1 | Accepted |
| ADR-0061 | Retrieval-quality CI benchmarks | 3.E.3 | Accepted |
Planning aliases not used
Early roadmap tables reserved numbers that collide with shipped Phase 2.5 ADRs. Do not reuse these for new work:
| Planning alias | Actual shipped ADR / note |
|---|---|
| “ADR-0032 memory data model” | Not published — memory expand is ADR-0052 (ADR-0032 is session data model) |
| “ADR-0033 embedding service” | Not published — ADR-0033 is ClickHouse llm_traces |
| “ADR-0035 vector / IVFFlat” | Superseded — HNSW via ADR-0052 / ADR-0053 |
| “ADR-0036 / 0037 conflict / extraction” | Not Phase 3 — conflict shipped as ADR-0056; extraction ADRs are Phase 3.5+ |
| “ADR-0040 memory schema / management API” | Occupied — ADR-0040 Anthropic adapter |
| “ADR-0041 vector store” | Occupied — ADR-0041 capability registry; vector store is ADR-0053 |
| “ADR-0042 write pipeline” | Occupied — ADR-0042; write path is ADR-0054–0057 |
Always assign the next free number from web/content/docs/adr/meta.json when publishing a new ADR.
Log pivots in findings. When an ADR merges, add it under docs/adr.
Architectural decisions
| Decision | Rationale |
|---|---|
Expand memories (000017) instead of greenfield CREATE | Foundations already shipped in 000014–000016 (ADR-0047–0049) |
| HNSW (not IVFFlat) as starting ANN index | Avoid live IVFFlat→HNSW cutover; greenfield table |
Defer category → primary_category rename | Zero runtime benefit until app writers; keep 000015 trigger |
| CI Postgres = pinned pgvector 0.8.6-pg16 digest | Mutable :pg16 tag is unsafe for migrate smoke reproducibility |
| Separate Python context assembly service (not inline in Go proxy) | Memory ranking needs NumPy, tiktoken, complex caching — wrong language for hot-path Go binary |
| gRPC for context assembly (not HTTP) | Typed contract, lower overhead than JSON for <50ms target; matches auth pattern |
| Graceful degradation on context timeout | If assembly exceeds ~45ms, proxy continues with directive-only context |
| betterproto for Python gRPC | Dataclass stubs vs protobuf message objects |
| Celery + Redis for workers | At-least-once delivery; idempotent tasks required |
| MinIO for session archives | Postgres metadata only; bulk conversation content in object storage |
| PAT auth for dashboard (Phase 3) | OAuth deferred; operators use same token model as SDK |
Pending decisions (resolve during milestones)
- HNSW
ef_searchper query — tune in Track B load tests (schema defaultsm=16,ef_construction=64). - Embedding GPU in dev compose — CPU default; document optional GPU profile in
ENVIRONMENT_VARIABLES.md. - Dashboard chart library — Recharts vs Tremor; lock in 3.8.5 before analytics pages multiply.
Edit on GitHub
Last updated on