Package path: offdev/micro-agent-go/internal/memory
Last updated: 2026-03-26
The memory package provides:
| Component | Purpose | Backend |
|---|---|---|
SessionStore |
In-memory conversation history per session | sync.RWMutex + map |
MilvusStore (via OpenStore) |
Persistent long-term memory across sessions | Milvus + github.com/milvus-io/milvus-sdk-go/v2 |
| SQLite (cron only) | Tick persistence for the heartbeat channel | modernc.org/sqlite in internal/channel/cron |
The MEMORY_DB / memory.path config value is the SQLite path used only by the cron channel for cron_ticks, not for long-term memory.
Both SessionStore and MilvusStore are safe for concurrent use.
Manages *core.Conversation objects keyed by session ID. Conversations are created on first
access and persist in memory for the lifetime of the process.
store := memory.NewSessionStore(0) // 0 = unlimited messages
conv := store.GetOrCreate("chat-session-1")
store.Put("chat-session-1", conv) // trims to maxMsgs if configured
store.Delete("chat-session-1")Sliding window: When maxMsgs > 0, Put trims the oldest non-system messages beyond the limit. The
system message (first message with Role == RoleSystem) is always preserved.
System prompt loading: At startup, internal/app builds the supervisor's system prompt from:
SYSTEM.md— path is the parent of the configured workdir (e.g.~/.micro-agent/SYSTEM.md). If present, its content replaces the default fallback instructions; if absent, the fallback is used.AGENTS.md— path is the configured workdir (e.g.~/.micro-agent/workdir/AGENTS.md). If present, its content is appended to the system prompt (after SYSTEM.md or fallback). Example content lives underexamples/workdir/.
Context compaction: Resolved in internal/config (nested JSON + env); see docs/config.md.
default.max_messages/AGENT_MAX_MESSAGES: Applied inSessionStore.Putas a sliding window (0= unlimited).default.compaction_strategy/COMPACTION_STRATEGY:truncate(default) orsummarize.truncate: no extra compaction after a turn; only the sliding window above applies whenmax_messages > 0.summarize: after each successful agent run, if estimated tokens (len(content)/4per message) exceedCOMPACTION_THRESHOLD,internal/apprunsrunSummarizeCompaction: keeps the system message (if any), replaces the middle of the history with one assistant message containing a summary, and keeps the last 10 messages. Uses a non-streamingSupervisor.Runon a synthetic conversation (seeinternal/app/compaction.go).
default.compaction_threshold/COMPACTION_THRESHOLD: Token threshold for summarization; when unset or<= 0, the runtime uses0.75 * AGENT_MAX_TOKENS.
Long-term memory is a core.MemoryStore backed by Milvus. internal/memory.OpenStore connects using config.Config (MILVUS_ADDR and optional auth/database/collection fields).
The MilvusStore uses a single collection (default name memories) with fields:
key VarChar PRIMARY KEY -- unique memory key
content VarChar -- stored text content
embedding FloatVector -- semantic embedding from EmbedFunc
tags VarChar -- JSON-encoded []string
ts Int64 -- Unix milliseconds
agent_id VarChar -- optional agent identifier
String fields have bounded lengths (key/agent_id ≈ 256, content ≈ 8192, tags ≈ 2048) to keep the schema efficient.
On first use the store:
- Probes the embedding dimension once via the configured
EmbedFunc. - Creates the collection with a
FloatVectorembeddingfield at that dimension. - Creates a
FLATindex onembedding.
Vector search uses the Milvus COSINE metric over this index.
internal/app wires the store as:
var embed memory.EmbedFunc
if cfg.MemoryEmbed {
embed = provider.Embed
}
store, err := memory.OpenStore(cfg, embed)- When
embedis nil (MEMORY_EMBED=falseor embeddings not used),OpenStorereturns(nil, nil)and the agent runs without long-term memory tools. - When
embedis non-nil butMILVUS_ADDRis empty,OpenStorereturns an error; the app logs a warning and continues without long-term memory. - When
embedis non-nil and Milvus is configured,MilvusStore.Savecallsembed(content)ifMemory.Embeddingis empty; vectors are stored in theembeddingfield.
The JSON memory.backend field is accepted for compatibility but not read by internal/config resolution; long-term memory is always Milvus when embeddings are enabled and Milvus is reachable.
Search(ctx, query, topK, opts):
- Generates a query embedding via
EmbedFunc(query). - Calls Milvus
Searchonembeddingwith metricCOSINEand indexFLAT. - Requests
key,content,tags,ts, andagent_idas output fields. - Reconstructs
[]core.Memoryfrom the result set.
When opts.TagsInclude is non-empty, the store filters client-side: tags is JSON-encoded []string, and only memories whose tag set intersects opts.TagsInclude are kept. The memory_search tool exposes this via an optional tags parameter.
type EmbedFunc func(ctx context.Context, text string) ([]float32, error)llamacpp.Provider.Embed satisfies this and calls POST /v1/embeddings on the llama-server sidecar.