ADE's memory system lets agents retain knowledge across sessions. It is a unified store with three scopes (project, agent, mission), three tiers (pinned, active, fading), and a lifecycle that decays, consolidates, and promotes entries over time. Memory operates automatically in the background; agents and the user rarely touch the raw store.
Memory is owned by the runtime daemon that owns the project. The unified
store, embedding worker, hybrid search, lifecycle sweep, batch
consolidation, knowledge capture, episodic summaries, procedural
learning, and skill export all run inside ade serve for that project.
Writes from the desktop renderer and ADE CLI go through the runtime's
JSON-RPC surface; the renderer is a viewer over ade.memory.*
channels.
Remote runtimes have memory and embeddings disabled in v1. The
static remote runtime build does not bundle onnxruntime-node, so the
embedding model cannot load and the hybrid search service refuses to
run. Remote-bound projects therefore:
- Have no
unified_memorieswrites from agents on the remote host —memoryAddreturns rejected, and the turn-level memory guard treatsrequiredturns as if no embeddings exist. - Cannot consolidate, decay, or promote — lifecycle and consolidation jobs are no-ops.
- Cannot run procedural learning or compaction-flush hooks for memory.
- Skip
.ade/memory/MEMORY.mdregeneration.
For projects that round-trip between a local Mac runtime and a remote
Linux runtime, all memory state lives in the local runtime's database.
The remote runtime's unified_memories table is empty by design.
Memory shown in Settings -> Memory always reflects the runtime that owns the active project binding. Switching to a remote project hides embedding-dependent surfaces.
| Path | Role |
|---|---|
apps/desktop/src/main/services/memory/memoryService.ts |
Core CRUD, dedup, write gates, tier and status logic. Entry point for all other memory services. |
apps/desktop/src/main/services/memory/hybridSearchService.ts |
BM25 + cosine vector search + MMR re-ranking. Used by memorySearch when embeddings are available. |
apps/desktop/src/main/services/memory/embeddingService.ts / embeddingWorkerService.ts |
Local embedding model (Xenova/all-MiniLM-L6-v2, 384 dims). Generates vectors and queues pending writes. The worker uses a smaller batch size while sessions are active and defers a cold embedding-model load for 60s when active sessions are running, so a first memory write does not compete with interactive agent work. |
apps/desktop/src/main/services/memory/memoryLifecycleService.ts |
Daily sweep: decay, demotion, promotion, archival by scope limits. |
apps/desktop/src/main/services/memory/batchConsolidationService.ts |
Weekly consolidation: cluster similar entries and merge via AI. |
apps/desktop/src/main/services/memory/knowledgeCaptureService.ts |
Captures conventions/patterns/gotchas from interventions, error clusters, PR feedback, and failures. |
apps/desktop/src/main/services/memory/episodicSummaryService.ts |
Post-session episode extraction (what was attempted, what worked, what failed). |
apps/desktop/src/main/services/memory/proceduralLearningService.ts |
Distills repeatable workflows from episodes into Procedures; exports skill files. |
apps/desktop/src/main/services/memory/humanWorkDigestService.ts |
Generates change digests when the user commits outside ADE. |
apps/desktop/src/main/services/memory/compactionFlushPrompt.ts |
DEFAULT_FLUSH_PROMPT fed into the Claude SDK PreCompact hook so durable findings can be saved before compaction. |
apps/desktop/src/main/services/memory/memoryBriefingService.ts |
Assembles briefings that get injected into agent prompts. |
apps/desktop/src/main/services/memory/memoryFilesService.ts |
Generates .ade/memory/MEMORY.md and topic files from promoted memories. |
apps/desktop/src/main/services/memory/memoryRepairService.ts |
Schema migrations and integrity repairs. |
apps/desktop/src/main/services/memory/skillRegistryService.ts |
Tracks the skill files indexed into memory. |
apps/desktop/src/main/services/memory/missionMemoryLifecycleService.ts |
Mission-specific: promotes high-value mission memories to project scope on success. |
apps/desktop/src/main/services/ai/tools/memoryTools.ts |
Agent-facing memorySearch / memoryAdd / memoryPin tools. |
apps/desktop/src/shared/types/memory.ts |
Shared types (MemoryScope, MemoryTier, MemoryCategory, digest types). |
SQL schema lives in apps/desktop/src/main/services/state/kvDb.ts.
| Scope | Purpose | Limit |
|---|---|---|
project |
Visible to every agent and mission in the project. Conventions, patterns, gotchas, decisions that apply project-wide. | 2000 |
agent |
Private to one agent identity (CTO or worker). Individual learnings, preferences, habits. | 500 per agent |
mission |
Scoped to a single mission. Task-specific context. High-value entries are promoted to project scope on mission success. | 200 per mission |
The write API also accepts "user" and "lane" as input; these
normalize to agent and mission respectively in
normalizeScope().
| Tier | Meaning |
|---|---|
| 1 (Pinned) | Always included in briefings. Reserved for the most critical knowledge. Can be pinned manually or by the system. |
| 2 (Active) | Included when budget allows. Recently accessed or high-confidence. |
| 3 (Fading) | Included only in deep searches. Entries decay to this tier when not accessed. |
The MemoryCategory enum (in memoryService.ts):
fact-- concrete facts or invariants.preference-- user or project preferences. Evergreen (exempt from decay).pattern-- implementation patterns (write-gated in strict mode).decision-- architectural or product decisions (write-gated).gotcha-- non-obvious pitfalls (write-gated).convention-- coding or workflow conventions (write-gated, evergreen).episode-- post-session episodic memories.procedure-- distilled workflows with confidence tracking.digest-- change digests (not stored as rows now; surfaced via the briefing service directly).handoff-- handoff summaries.
Four categories (convention, pattern, gotcha, decision) are the
"strict write" set. writeMode: "strict" forces stricter dedup and
confidence checks on them.
candidate-- recently written, not yet promoted. Lower retrieval priority.promoted-- accepted for retrieval.archived-- removed from retrieval but kept for audit.
memoryService.writeMemory(opts):
- Validate
scope,category,importance. - Compute a
dedupeKeyand run Jaccard similarity against existing entries (threshold 0.85); duplicates merge into the existing entry rather than creating a new row. - Honor scope+category allowlists.
- Enforce write-gate rules (strict write mode stricter rejection of code-derivable content: raw diffs, stack traces, session summaries, git history output, file-path dumps).
- Insert/update the
unified_memoriesrow, update FTS, enqueue an embedding job. - Emit
onMemoryUpsertedcallback. - Return
WriteMemoryResultwithaccepted,memory,deduped,mergedIntoId,reason.
memoryService.search(opts) returns a ranked list:
- When
hybridSearchServiceis available and embeddings exist, uses BM25 + cosine + MMR (see embeddings). - Otherwise falls back to lexical FTS.
memoryService.listMemories(opts) performs filtered retrieval without
ranking; used by the UI's Memory tab and by lifecycle services.
In addition to the SQLite store, ADE generates project memory bootstrap
files under .ade/memory/:
MEMORY.md-- condensed overview for Claude-style auto-load.- Topic files such as
conventions.md,gotchas.md,procedures.md.
These are derived from promoted memory by memoryFilesService.ts and
auto-loaded into chats and worker briefings in bounded form.
Chat classifies each user turn by intent (none, soft, required).
When a turn is required (fix, debug, implement, refactor), mutating
tools (bash, writeFile, editFile) are blocked until the agent has
called memorySearch. The guard state is TurnMemoryPolicyState in
memoryTools.ts; explicitSearchPerformed flips to true on any
memorySearch invocation.
soft turns auto-inject memory context but do not block mutations.
meta turns (greetings, thanks) skip memory altogether.
See the Tool System doc for how the gate applies.
Agent conversations
-> compaction flush (pre-compaction memoryAdd)
-> episodic summary (post-session extraction)
-> procedural learning (multi-episode pattern distillation)
-> skill export (.ade/skills/ materialization)
External changes
-> git head watcher detects new commits
-> human work digest (change summary -> briefing context + sync status)
Failures and feedback
-> mission/agent failures trigger captureFailureGotcha
-> knowledge capture extracts gotchas, conventions, patterns
from interventions, error clusters, and PR feedback
Lifecycle jobs:
- Decay -- every memory has an access score; decay is geometric
with a 30-day half-life. Evergreen categories (
preference,convention) and pinned entries are exempt. - Sweep -- daily. Applies decay, demotes entries below threshold, promotes confident candidates, archives entries exceeding scope limits.
- Consolidation -- weekly (
batchConsolidationService.ts). Clusters similar entries by scope and category, merges via an AI call, archives the originals.
Distinct from the unified store: a small structured document that
carries the CTO's standing identity state. See
agents/identity-and-personas for
the full flow. The CTO also has a memoryUpdateCore tool to overwrite
the core memory block (workers get the same tool for their own core
memory).
All channels are invoke-style and prefixed ade.memory.*. Defined in
apps/desktop/src/shared/ipc.ts, handled in
apps/desktop/src/main/services/ipc/registerIpc.ts.
| Channel | Purpose |
|---|---|
ade.memory.add |
Write a memory (delegates to memoryService.writeMemory). |
ade.memory.pin |
Pin an entry to Tier 1. |
ade.memory.updateCore |
Overwrite CTO/agent core memory. |
ade.memory.getBudget |
Report scope usage vs. limit. |
ade.memory.getCandidates |
List candidate-status memories (for manual promotion). |
ade.memory.promote |
Promote a candidate to promoted. |
ade.memory.promoteMissionEntry |
Promote a mission-scoped entry to project scope. |
ade.memory.archive |
Archive an entry. |
ade.memory.search |
Search (hybrid when embeddings available, else lexical). |
ade.memory.list |
Filtered list (no ranking). |
ade.memory.listMissionEntries |
Mission-specific listing. |
ade.memory.listProcedures |
List procedure memories with details. |
ade.memory.getProcedureDetail |
Fetch one procedure with full markdown + history. |
ade.memory.exportProcedureSkill |
Materialise a procedure as a skill file. |
ade.memory.listIndexedSkills |
List skill files indexed into memory. |
ade.memory.reindexSkills |
Re-scan .ade/skills/ and the legacy commands dir. |
ade.memory.syncKnowledge |
Run human-work-digest sync now. |
ade.memory.getKnowledgeSyncStatus |
Current KnowledgeSyncStatus. |
ade.memory.healthStats |
Scope usage, last sweep, last consolidation, embedding status. |
ade.memory.downloadEmbeddingModel |
Trigger embedding model download. |
ade.memory.runSweep / ade.memory.sweepStatus |
Manual sweep + status. |
ade.memory.runConsolidation / ade.memory.consolidationStatus |
Manual consolidation + status. |
- Settings -> Memory -- browse, search, pin, delete. Shows scope usage, last sweep, last consolidation, embedding status.
- Settings -> Context & Docs -> Skill Files -- manages file-backed skill entries separately from generic memories.
- Chat system notices -- memory loads (bootstrap, topic files) and
guard fires surface as
system_noticeevents withnoticeKind: "memory". - Work-log summaries --
memoryAddandmemorySearchtool calls render in the work log like any other tool.
- Dedup by Jaccard. Threshold 0.85 is empirical; lowering it causes aggressive merging, raising it causes growth toward limits.
- Embedding queue during model load. When the embedding model is
still loading, new memories queue rather than drop. If the model has
not started and a session is active,
embeddingWorkerService.tsdefers the cold start byDEFAULT_ACTIVE_SESSION_COLD_START_DEFER_MS(60s) and reschedules the queue. Missing the drain or reschedule causes silent loss of embeddings. - Evergreen exemption order. Decay skips evergreen categories before checking the importance threshold, so raising an evergreen entry's importance does not affect its decay (it is already exempt).
- Sweep promotion criteria. Candidates promote when confidence exceeds a threshold and they have been accessed at least once. Changing thresholds mid-session can abruptly promote or demote large batches.
- FTS triggers. Inserts, deletes, and updates on
unified_memoriesfire triggers that keepunified_memories_ftsin sync. Schema migrations that skip the triggers leave FTS stale and searches return stale rows. - Write gate rejection is silent by design. Agents get
durability: "rejected"when a write is gated; there is no error event so the agent must check the return value. If the agent assumes success, it will report to the user as if the write succeeded. - Briefing injection bounded. The briefing service caps each
section to a budget; long memory lists silently truncate. See
memoryBriefingService.tsBUDGET_LIMITS. - Knowledge capture dedup via ledger. The
memory_capture_ledgerkeeps one row per (source_type, source_key) to prevent duplicate captures. Dropping that dedup doubles gotchas on replayed interventions.
- Storage -- SQLite schema, indexes, triggers, write gates.
- Compaction -- compaction flush, episodic summary, procedural learning, consolidation.
- Embeddings -- local embedding model, hybrid search, health monitoring.
- Chat Tool System --
memorySearch/memoryAdd/memoryPin/memoryUpdateCoretool definitions. - Agents Identity and Personas -- CTO core memory document, agent core memory.