Architecture¶
Last updated: 2026-02-26
Summary¶
Lerim is a file-first continual learning layer for coding agents.
- Ingest sessions from local agent adapters.
- Lead runtime takes only
trace_pathand creates one per-run workspace folder. - Orchestration runs on
pydantic-aiwith typed tools and read-only subagent delegation. - Extraction/summarization run through
dspy.RLMtool calls and writeextract.json+summary.json. - Lead decides
add|update|no-opby deterministic prompt policy and writes markdown files (decision,learning) plus one episodicsummary. - Run evidence is stored as flat artifacts in the workspace folder.
- Retrieve with project-first scope and global fallback.
Runtime prerequisites¶
dspy.RLM runs through DSPy's Deno/Pyodide interpreter. Install Deno on host machines that run extraction.
System flow¶
flowchart TD
A["Adapters (claude/codex/cursor/opencode)"] --> B["Session Catalog + Queue"]
B --> C["Lead Agent (LerimAgent / pydantic-ai) with trace_path"]
C --> D["Workspace Artifacts (.lerim/workspace/run_id)"]
D --> E["extract.json + summary.json + memory_actions.json"]
C --> F["Project Memory .lerim/memory/*"]
C --> O["Explorer subagent (read-only)"]
C --> P["Runtime write-boundary checks"]
F --> H["Files Search (default)"]
H --> L["chat / memory search"]
M["maintain"] --> N["Agent-led: scan, merge, archive, consolidate, report"]
Storage model¶
Canonical memory files:
.lerim/memory/decisions/*.md.lerim/memory/learnings/*.md.lerim/memory/summaries/YYYYMMDD/HHMMSS/{slug}.md.lerim/memory/archived/decisions/*.md(soft-deleted).lerim/memory/archived/learnings/*.md(soft-deleted)
Trace archive:
.lerim/meta/traces/sessions/<agent>/<run_id>.jsonl
Run workspace artifacts:
.lerim/workspace/sync-<YYYYMMDD-HHMMSS>-<shortid>/— extract.json, summary.json, memory_actions.json, agent.log, subagents.log, session.log.lerim/workspace/maintain-<YYYYMMDD-HHMMSS>-<shortid>/— maintain_actions.json, agent.log, subagents.log
Index folder (reserved for future FTS/vector/graph):
.lerim/index/fts.sqlite3.lerim/index/graph.sqlite3.lerim/index/vectors.lance/
Scope resolution¶
Config precedence (low to high priority):
src/lerim/config/default.toml(shipped with package)~/.lerim/config.toml(user global)<repo>/.lerim/config.toml(project overrides)LERIM_CONFIGenv var path (explicit override, for CI/tests)
API keys come from environment variables only (ZAI_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY, optional ANTHROPIC_API_KEY).
Memory scope modes:
project_fallback_global(default)project_onlyglobal_only
Runtime paths¶
Sync path¶
sync: discover/index sessions, run lead by trace_path, write run artifacts to workspace folder, run lead decision (add|update|no-op), write memory + summaries.
Maintain path¶
maintain: agent-led offline memory refinement. Scans existing memories, merges duplicates, archives low-value entries, consolidates related memories. Soft-deletes to archived/ via the write tool. Single agent run with comprehensive prompt.
Query path¶
query (chat, memory search): read-only path.
Agent architecture¶
Lead agent¶
The lead agent (PydanticAI) orchestrates all flows. It is the only component allowed to write memory files.
- Runtime tools:
read,glob,grep,write,edit,extract_pipeline,summarize_pipeline - Write boundary: runtime tools deny writes outside
memory_rootand workspace roots - All file operations use Python tools (no shell/subprocess)
Explorer subagent¶
Read-only agent delegated from the lead for candidate gathering:
- Tools:
read,glob,greponly - Cannot write — no write or edit tools
DSPy pipelines¶
Called as tools from the lead agent:
- Extraction (
MemoryExtractSignature): transcript -> structured memory candidates - Summarization (
TraceSummarySignature): transcript -> structured summary with frontmatter
Both run through dspy.RLM with role-configured models.
Observability¶
Stderr logging is minimal (short status lines via loguru). Detailed agent tracing uses OpenTelemetry through PydanticAI's built-in instrumentation (logfire SDK).
When tracing is enabled (LERIM_TRACING=1 or [tracing] enabled = true):
- Each
agent.run_sync()emits a trace with spans for model requests, tool calls, and timing - Token usage is recorded per span
- Optional
include_httpx = truecaptures raw HTTP request/response bodies - Traces are sent to Logfire cloud (free tier) — view at logfire.pydantic.dev
- DSPy pipelines run with
verbose=False; their LLM calls are visible via httpx spans when enabled
Security boundaries¶
- Runtime tools deny
writeandeditoutsidememory_rootand workspace roots - Memory writes are normalized to canonical markdown frontmatter and filename rules
- All file operations use Python tools (no shell/subprocess)
- Explorer subagent is read-only (
read,glob,greponly)