# Memory Memory is OpenRath's durable knowledge plane. It mirrors the sandbox/backend architecture, but stays independent from it: sandbox backends run side effects, memory backends store and retrieve knowledge. ```text flowchart LR A["flow.Agent"] --> B["Session"] A --> C["MemoryStore"] B --> D["BackendSandbox"] C --> E["MemoryBackend"] D --> F["Backend"] ``` ## Symmetry With Sandbox Backends | Sandbox plane | Memory plane | Role | | --- | --- | --- | | `Backend` | `MemoryBackend` | Registry-selected implementation. | | `BackendSandbox` | `MemoryStore` | Refcounted live handle. | | `BackendSandboxSpec` | `MemoryStoreSpec` | User-facing open spec. | | `BackendTool*` | `MemoryOp*` | Typed dispatch payload. | | `ToolResult` | `MemoryResult` | Typed result or structured failure. | The planes do not cross-import. `flow.Agent` is the composition point because an agent may need both: a sandbox for tool execution and a memory store for durable recall. ## Local Backend The local backend ships with base `openrath` and is the default registered memory backend. It stores entries under `.openrath/memory/local/` or under an explicit configured path. | Capability | Local behavior | | --- | --- | | write/read/list/tree | Filesystem-backed Markdown entries. | | find/search | BM25 by default; optional embeddings when an embedding provider is configured. | | resource ingest | Copies or fetches local/URL resources into the memory tree. | | commit | Archives session messages and optionally extracts memories with a chat provider. | ## OpenViking Adapter The OpenViking backend is optional and belongs behind `openrath[openviking]`. The public boundary remains `memory://...`; internal OpenViking identifiers such as `viking://...` stay inside the adapter. This keeps workflows portable: ```python from rath import flow agent = flow.Agent("Use project memory.", model="gpt-5.5", memory="local") hits = agent.recall_memory("deployment notes") ``` Switching a store from local to OpenViking should change configuration, not workflow code. ## Agent Memory Lifecycle | Step | API | Notes | | --- | --- | --- | | Attach | `flow.Agent(memory=...)` | Accepts a store, store spec, backend/preset name, or `None`. | | Explicit write | `remember_memory(...)` | Best for facts the app already knows are durable. | | Recall | `recall_memory(...)` | Usually called before a model turn or by application code. | | Commit | `commit_memory(session, ...)` | Extracts durable knowledge from a transcript. | | Automatic commit | `commit_on_forward=True` | Best-effort; failures should not break the main model response path. | ## Design Boundaries | Boundary | Rule | | --- | --- | | Public URI | Use `memory://...` in user code and docs. | | Adapter URI | Keep backend-specific schemes private. | | Config | `memory.providers` selects store presets; `llm.embedding_provider` and `llm.vlm_provider` remain LLM config. | | Stability | `rath.memory` is public API; adapter internals are not. | ## Test Coverage | Behavior | Tests | | --- | --- | | op/result dataclasses | `tests/memory/unit/test_op_types.py`, `tests/memory/unit/test_results.py` | | registry/default backend | `tests/memory/unit/test_registry.py`, `tests/memory/unit/test_default_backend.py` | | local backend operations | `tests/memory/local_backend/test_local_memory_fs_ops.py`, `tests/memory/local_backend/test_local_memory_lifecycle.py` | | agent memory helpers | `tests/flow/test_agent_memory_public_api.py`, `tests/flow/test_agent_forward_memory.py` | | OpenViking adapter | `tests/memory/backends/test_openviking_io.py`, `tests/memory/backends/test_openviking_query.py` | [← Developer Notes](index.md)