Skip to main content

Active Memory

Active memory is an optional plugin-owned blocking memory sub-agent that runs before the main reply for eligible conversational sessions. It exists because most memory systems are capable but reactive. They rely on the main agent to decide when to search memory, or on the user to say things like “remember this” or “search memory.” By then, the moment where memory would have made the reply feel natural has already passed. Active memory gives the system one bounded chance to surface relevant memory before the main reply is generated.

Paste This Into Your Agent

Paste this into your agent if you want it to enable Active Memory with a self-contained, safe-default setup:
This turns the plugin on for the main agent, keeps it limited to direct-message style sessions by default, lets it inherit the current session model first, and uses the configured fallback model only if no explicit or inherited model is available. After that, restart the gateway:
To inspect it live in a conversation:

Turn active memory on

The safest setup is:
  1. enable the plugin
  2. target one conversational agent
  3. keep logging on only while tuning
Start with this in velaclaw.json:
Then restart the gateway:
What this means:
  • plugins.entries.active-memory.enabled: true turns the plugin on
  • config.agents: ["main"] opts only the main agent into active memory
  • config.allowedChatTypes: ["direct"] keeps active memory on for direct-message style sessions only by default
  • if config.model is unset, active memory inherits the current session model first
  • config.modelFallback optionally provides your own fallback provider/model for recall
  • config.promptStyle: "balanced" uses the default general-purpose prompt style for recent mode
  • active memory still runs only on eligible interactive persistent chat sessions

How to see it

Active memory injects a hidden untrusted prompt prefix for the model. It does not expose raw <active_memory_plugin>...</active_memory_plugin> tags in the normal client-visible reply.

Session toggle

Use the plugin command when you want to pause or resume active memory for the current chat session without editing config:
This is session-scoped. It does not change plugins.entries.active-memory.enabled, agent targeting, or other global configuration. If you want the command to write config and pause or resume active memory for all sessions, use the explicit global form:
The global form writes plugins.entries.active-memory.config.enabled. It leaves plugins.entries.active-memory.enabled on so the command remains available to turn active memory back on later. If you want to see what active memory is doing in a live session, turn on the session toggles that match the output you want:
With those enabled, Velaclaw can show:
  • an active memory status line such as Active Memory: status=ok elapsed=842ms query=recent summary=34 chars when /verbose on
  • a readable debug summary such as Active Memory Debug: Lemon pepper wings with blue cheese. when /trace on
Those lines are derived from the same active memory pass that feeds the hidden prompt prefix, but they are formatted for humans instead of exposing raw prompt markup. They are sent as a follow-up diagnostic message after the normal assistant reply so channel clients like Telegram do not flash a separate pre-reply diagnostic bubble. If you also enable /trace raw, the traced Model Input (User Role) block will show the hidden Active Memory prefix as:
By default, the blocking memory sub-agent transcript is temporary and deleted after the run completes. Example flow:
Expected visible reply shape:

When it runs

Active memory uses two gates:
  1. Config opt-in The plugin must be enabled, and the current agent id must appear in plugins.entries.active-memory.config.agents.
  2. Strict runtime eligibility Even when enabled and targeted, active memory only runs for eligible interactive persistent chat sessions.
The actual rule is:
If any of those fail, active memory does not run.

Session types

config.allowedChatTypes controls which kinds of conversations may run Active Memory at all. The default is:
That means Active Memory runs by default in direct-message style sessions, but not in group or channel sessions unless you opt them in explicitly. Examples:

Where it runs

Active memory is a conversational enrichment feature, not a platform-wide inference feature.

Why use it

Use active memory when:
  • the session is persistent and user-facing
  • the agent has meaningful long-term memory to search
  • continuity and personalization matter more than raw prompt determinism
It works especially well for:
  • stable preferences
  • recurring habits
  • long-term user context that should surface naturally
It is a poor fit for:
  • automation
  • internal workers
  • one-shot API tasks
  • places where hidden personalization would be surprising

How it works

The runtime shape is: The blocking memory sub-agent can use only:
  • memory_search
  • memory_get
If the connection is weak, it should return NONE.

Query modes

config.queryMode controls how much conversation the blocking memory sub-agent sees.

Prompt styles

config.promptStyle controls how eager or strict the blocking memory sub-agent is when deciding whether to return memory. Available styles:
  • balanced: general-purpose default for recent mode
  • strict: least eager; best when you want very little bleed from nearby context
  • contextual: most continuity-friendly; best when conversation history should matter more
  • recall-heavy: more willing to surface memory on softer but still plausible matches
  • precision-heavy: aggressively prefers NONE unless the match is obvious
  • preference-only: optimized for favorites, habits, routines, taste, and recurring personal facts
Default mapping when config.promptStyle is unset:
If you set config.promptStyle explicitly, that override wins. Example:

Model fallback policy

If config.model is unset, Active Memory tries to resolve a model in this order:
config.modelFallback controls the configured fallback step. Optional custom fallback:
If no explicit, inherited, or configured fallback model resolves, Active Memory skips recall for that turn. config.modelFallbackPolicy is retained only as a deprecated compatibility field for older configs. It no longer changes runtime behavior.

Advanced escape hatches

These options are intentionally not part of the recommended setup. config.thinking can override the blocking memory sub-agent thinking level:
Default:
Do not enable this by default. Active Memory runs in the reply path, so extra thinking time directly increases user-visible latency. config.promptAppend adds extra operator instructions after the default Active Memory prompt and before the conversation context:
config.promptOverride replaces the default Active Memory prompt. Velaclaw still appends the conversation context afterward:
Prompt customization is not recommended unless you are deliberately testing a different recall contract. The default prompt is tuned to return either NONE or compact user-fact context for the main model.

message

Only the latest user message is sent.
Use this when:
  • you want the fastest behavior
  • you want the strongest bias toward stable preference recall
  • follow-up turns do not need conversational context
Recommended timeout:
  • start around 3000 to 5000 ms

recent

The latest user message plus a small recent conversational tail is sent.
Use this when:
  • you want a better balance of speed and conversational grounding
  • follow-up questions often depend on the last few turns
Recommended timeout:
  • start around 15000 ms

full

The full conversation is sent to the blocking memory sub-agent.
Use this when:
  • the strongest recall quality matters more than latency
  • the conversation contains important setup far back in the thread
Recommended timeout:
  • increase it substantially compared with message or recent
  • start around 15000 ms or higher depending on thread size
In general, timeout should increase with context size:

Transcript persistence

Active memory blocking memory sub-agent runs create a real session.jsonl transcript during the blocking memory sub-agent call. By default, that transcript is temporary:
  • it is written to a temp directory
  • it is used only for the blocking memory sub-agent run
  • it is deleted immediately after the run finishes
If you want to keep those blocking memory sub-agent transcripts on disk for debugging or inspection, turn persistence on explicitly:
When enabled, active memory stores transcripts in a separate directory under the target agent’s sessions folder, not in the main user conversation transcript path. The default layout is conceptually:
You can change the relative subdirectory with config.transcriptDir. Use this carefully:
  • blocking memory sub-agent transcripts can accumulate quickly on busy sessions
  • full query mode can duplicate a lot of conversation context
  • these transcripts contain hidden prompt context and recalled memories

Configuration

All active memory configuration lives under:
The most important fields are: Useful tuning fields: Start with recent.
If you want to inspect live behavior while tuning, use /verbose on for the normal status line and /trace on for the active-memory debug summary instead of looking for a separate active-memory debug command. In chat channels, those diagnostic lines are sent after the main assistant reply rather than before it. Then move to:
  • message if you want lower latency
  • full if you decide extra context is worth the slower blocking memory sub-agent

Debugging

If active memory is not showing up where you expect:
  1. Confirm the plugin is enabled under plugins.entries.active-memory.enabled.
  2. Confirm the current agent id is listed in config.agents.
  3. Confirm you are testing through an interactive persistent chat session.
  4. Turn on config.logging: true and watch the gateway logs.
  5. Verify memory search itself works with velaclaw memory status --deep.
If memory hits are noisy, tighten:
  • maxSummaryChars
If active memory is too slow:
  • lower queryMode
  • lower timeoutMs
  • reduce recent turn counts
  • reduce per-turn char caps

Common issues

Embedding provider changed unexpectedly

Active Memory uses the normal memory_search pipeline under agents.defaults.memorySearch. That means embedding-provider setup is only a requirement when your memorySearch setup requires embeddings for the behavior you want. In practice:
  • explicit provider setup is required if you want a provider that is not auto-detected, such as ollama
  • explicit provider setup is required if auto-detection does not resolve any usable embedding provider for your environment
  • explicit provider setup is highly recommended if you want deterministic provider selection instead of “first available wins”
  • explicit provider setup is usually not required if auto-detection already resolves the provider you want and that provider is stable in your deployment
If memorySearch.provider is unset, Velaclaw auto-detects the first available embedding provider. That can be confusing in real deployments:
  • a newly available API key can change which provider memory search uses
  • one command or diagnostics surface may make the selected provider look different from the path you are actually hitting during live memory sync or search bootstrap
  • hosted providers can fail with quota or rate-limit errors that only show up once Active Memory starts issuing recall searches before each reply
Active Memory can still run without embeddings when memory_search can operate in degraded lexical-only mode, which typically happens when no embedding provider can be resolved. Do not assume the same fallback on provider runtime failures such as quota exhaustion, rate limits, network/provider errors, or missing local/remote models after a provider has already been selected. In practice:
  • if no embedding provider can be resolved, memory_search may degrade to lexical-only retrieval
  • if an embedding provider is resolved and then fails at runtime, Velaclaw does not currently guarantee a lexical fallback for that request
  • if you need deterministic provider selection, pin agents.defaults.memorySearch.provider
  • if you need provider failover on runtime errors, configure agents.defaults.memorySearch.fallback explicitly
If you depend on embedding-backed recall, multimodal indexing, or a specific local/remote provider, pin the provider explicitly instead of relying on auto-detection. Common pinning examples: OpenAI:
Gemini:
Ollama:
If you expect provider failover on runtime errors such as quota exhaustion, pinning a provider alone is not enough. Configure an explicit fallback too:

Debugging provider issues

If Active Memory is slow, empty, or appears to switch providers unexpectedly:
  • watch the gateway logs while reproducing the problem; look for lines such as active-memory: ... start|done, memory sync failed (search-bootstrap), or provider-specific embedding errors
  • turn on /trace on to surface the plugin-owned Active Memory debug summary in the session
  • turn on /verbose on if you also want the normal 🧩 Active Memory: ... status line after each reply
  • run velaclaw memory status --deep to inspect the current memory-search backend and index health
  • check agents.defaults.memorySearch.provider and related auth/config to make sure the provider you expect is actually the one that can resolve at runtime
  • if you use ollama, verify the configured embedding model is installed, for example ollama list
Example debugging loop:
Example:
Or, if you want Gemini embeddings:
After changing the provider, restart the gateway and run a fresh test with /trace on so the Active Memory debug line reflects the new embedding path.