LemonMemory. Document
(lemon_memory v0.1.0)
View Source
Normalized memory document extracted from a finalized run.
A memory document captures the key facts about a run in a compact, searchable
form, separate from the full conversation payload stored in RunHistoryStore.
Fields
:doc_id- Unique document identifier (prefixed"mem_"):run_id- Source run ID:session_key- Session the run belongs to:agent_id- Agent that executed the run:workspace_key- Workspace the run was executed in (nil if unknown):scope- Memory scope::session,:workspace,:agent, or:global:started_at_ms- Run start timestamp in milliseconds:ingested_at_ms- When this document was written to the memory store:prompt_summary- Truncated prompt text (for FTS):answer_summary- Truncated answer text (for FTS):tools_used- List of tool name strings used during the run:provider- LLM provider name (e.g."anthropic"):model- LLM model name (e.g."claude-opus-4-6"):outcome- Outcome label inferred byLemonCore.RunOutcome.infer/1:meta- Arbitrary metadata map
Scopes
The four memory scopes follow docs/assistant_bootstrap_contract.md:
| Scope | Lifetime | Key field used |
|---|---|---|
:session | Single agent run | session_key |
:workspace | Workspace lifetime | workspace_key |
:agent | Agent lifetime | agent_id |
:global | Installation lifetime | none (all documents) |
Summary
Functions
Build a Document from a finalized run record and its summary.
The byte cap new/1 and from_run/4 apply to each summary field.
Build a Document directly from its fields, applying the same invariants the
ingest path relies on.
Types
@type outcome() :: :unknown | :success | :partial | :failure | :aborted
@type scope() :: :session | :workspace | :agent | :global
@type t() :: %LemonMemory.Document{ agent_id: binary(), answer_summary: binary(), doc_id: binary(), ingested_at_ms: integer(), meta: map(), model: binary() | nil, outcome: outcome(), prompt_summary: binary(), provider: binary() | nil, run_id: binary(), scope: scope(), session_key: binary(), started_at_ms: integer(), tools_used: [binary()], workspace_key: binary() | nil }
Functions
Build a Document from a finalized run record and its summary.
Extracts normalized fields from the run summary. Unknown or missing fields are replaced with safe defaults so ingest never raises.
@spec max_summary_bytes() :: pos_integer()
The byte cap new/1 and from_run/4 apply to each summary field.
Build a Document directly from its fields, applying the same invariants the
ingest path relies on.
Use this when you drive LemonAgent yourself and want to record a memory
without the router's run-record shape that from_run/4 expects. It differs
from building the struct by hand in two ways that matter:
- Summaries are truncated.
prompt_summaryandanswer_summaryare capped at 2000 bytes (on a UTF-8 boundary), exactly asfrom_run/4does. Building the struct by hand skips this, silently indexing whole transcripts into the FTS table. - Identity is validated.
session_keyandagent_idare required and must be non-empty binaries — they areNOT NULLin the store and are what scope a search, so a missing one is a programming error, not a row the store should quietly reject.
Everything else is defaulted: doc_id (a fresh "mem_"-prefixed id) and
run_id are generated when absent, ingested_at_ms defaults to now,
started_at_ms to ingested_at_ms, and scope to :session.
Accepts a map or keyword list. Raises ArgumentError on a missing or invalid
required field, or an unknown scope.
Examples
iex> doc = LemonMemory.Document.new(session_key: "agent:demo:main", agent_id: "demo",
...> prompt_summary: "hi", answer_summary: "hello")
iex> {doc.scope, doc.answer_summary, String.starts_with?(doc.doc_id, "mem_")}
{:session, "hello", true}