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)

ConcernChoiceReason
Python version3.11Performance over 3.10; 3.12 not yet stable across ML libs
Web frameworkFastAPI 0.110+Native async, automatic OpenAPI, DI
ORMSQLAlchemy 2.0 (async)Type-safe async queries, pgvector support
MigrationsAlembicStandard SQLAlchemy companion
Configpydantic-settings v2Typed, validated .env support
Testingpytest + pytest-asyncioasyncio_mode="auto"
Lintingruff + mypy --strictSingle tool, fast
Task queueCelery 5 + Redis brokerIndustry standard
gRPCgrpcio + betterprotoDataclass codegen, mypy-friendly
HTTP clienthttpx (async)Better typing than aiohttp
Embeddingssentence-transformers 2.xHuggingFace model flexibility
Packagingpyproject.toml + uvFast installs

ADR register (Phase 3)

ADRTopicMilestoneStatus
ADR-0052Memory schema v2 expand (HNSW, quality columns)3.1.1Accepted
ADR-0033Embedding service design3.2.1Pending (reserved; may renumber)
ADR-0035Vector search / IVFFlat tuning3.3.4Superseded intent — prefer HNSW (ADR-0052)
ADR-0036Memory extraction strategy3.4.3Pending
ADR-0037Conflict detection + resolution3.4.5Pending
ADR-0038Context assembly gRPC contract3.5.1Pending (note: ADR-0038 may already be used in Phase 2.5 index — verify before publishing)
ADR-0045Token budget calculator3.5.2Pending (note: ADR-0045 may already be used — verify before publishing)
ADR-0040Management API auth middleware3.6.1Occupied (Anthropic adapter) — pick next free ID
ADR-0041MinIO session archive format3.7.1Occupied (capability registry) — pick next free ID
ADR-0042Memory write pipeline + PII3.3.2Pending (verify free ID)

3.1.1 note: reserved placeholder “ADR-0032 memory data model” was not published; the expand shipped as ADR-0052 / migration 000017.

Pending rows are reserved IDs only. They do not appear in the ADR sidebar / meta.json until the milestone writes and indexes the ADR (same pattern as ADR-0036 / ADR-0037). Numbers in older planning tables collide with Phase 2.5 ADRs — always take the next free number from web/content/docs/adr/meta.json.

Log pivots in findings. When an ADR merges, add it under docs/adr.

Architectural decisions

DecisionRationale
Expand memories (000017) instead of greenfield CREATEFoundations already shipped in 000014–000016 (ADR-0047–0049)
HNSW (not IVFFlat) as starting ANN indexAvoid live IVFFlat→HNSW cutover; greenfield table
Defer categoryprimary_category renameZero runtime benefit until app writers; keep 000015 trigger
CI Postgres = pinned pgvector 0.8.6-pg16 digestMutable :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 timeoutIf assembly exceeds ~45ms, proxy continues with directive-only context
betterproto for Python gRPCDataclass stubs vs protobuf message objects
Celery + Redis for workersAt-least-once delivery; idempotent tasks required
MinIO for session archivesPostgres 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)

  1. HNSW ef_search per query — tune in Track B load tests (schema defaults m=16, ef_construction=64).
  2. Embedding GPU in dev compose — CPU default; document optional GPU profile in ENVIRONMENT_VARIABLES.md.
  3. Dashboard chart library — Recharts vs Tremor; lock in 3.8.5 before analytics pages multiply.
Edit on GitHub

Last updated on

On this page

0%