Skip to content

Latest commit

 

History

History
122 lines (83 loc) · 5.62 KB

File metadata and controls

122 lines (83 loc) · 5.62 KB

memory — Session and Long-Term Memory

Package path: offdev/micro-agent-go/internal/memory
Last updated: 2026-03-26


Overview

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.


SessionStore

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 under examples/workdir/.

Context compaction: Resolved in internal/config (nested JSON + env); see docs/config.md.

  • default.max_messages / AGENT_MAX_MESSAGES: Applied in SessionStore.Put as a sliding window (0 = unlimited).
  • default.compaction_strategy / COMPACTION_STRATEGY: truncate (default) or summarize.
    • truncate: no extra compaction after a turn; only the sliding window above applies when max_messages > 0.
    • summarize: after each successful agent run, if estimated tokens (len(content)/4 per message) exceed COMPACTION_THRESHOLD, internal/app runs runSummarizeCompaction: 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-streaming Supervisor.Run on a synthetic conversation (see internal/app/compaction.go).
  • default.compaction_threshold / COMPACTION_THRESHOLD: Token threshold for summarization; when unset or <= 0, the runtime uses 0.75 * AGENT_MAX_TOKENS.

Long-Term Memory (Milvus)

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).

Collection schema

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.

Index and metric

On first use the store:

  1. Probes the embedding dimension once via the configured EmbedFunc.
  2. Creates the collection with a FloatVector embedding field at that dimension.
  3. Creates a FLAT index on embedding.

Vector search uses the Milvus COSINE metric over this index.

Constructor and embedding flow

internal/app wires the store as:

var embed memory.EmbedFunc
if cfg.MemoryEmbed {
    embed = provider.Embed
}
store, err := memory.OpenStore(cfg, embed)
  • When embed is nil (MEMORY_EMBED=false or embeddings not used), OpenStore returns (nil, nil) and the agent runs without long-term memory tools.
  • When embed is non-nil but MILVUS_ADDR is empty, OpenStore returns an error; the app logs a warning and continues without long-term memory.
  • When embed is non-nil and Milvus is configured, MilvusStore.Save calls embed(content) if Memory.Embedding is empty; vectors are stored in the embedding field.

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 and tag filtering

Search(ctx, query, topK, opts):

  1. Generates a query embedding via EmbedFunc(query).
  2. Calls Milvus Search on embedding with metric COSINE and index FLAT.
  3. Requests key, content, tags, ts, and agent_id as output fields.
  4. Reconstructs []core.Memory from 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.

EmbedFunc

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.