Summary
The observation extraction pipeline captures its own internal processing prompts as observations. These accumulate over time and get injected back into context via true_memory_context, wasting tokens and injecting stale user directives into new sessions.
Two symptoms, one root cause
Symptom 1: Internal prompts stored as observations
Every tool execution triggers an observation extraction flow:
- Tool output →
pending_messages queue
- LLM analyzes the output with the prompt:
<task>Analyze the following tool output and extract a structured observation.</task>
- Extracted observation →
observations table
Bug: The internal extraction prompt itself (from step 2) gets captured as an observation with tool_name="chat.message" and stored in the database. The title field becomes "User request: <task>\nAnalyze the following tool output..." and the narrative contains the raw prompt + tool output.
Symptom 2: Garbage observations pollute context injection
The true_memory_context injection retrieves relevant observations and injects them into the prompt. These internal prompts are retrieved alongside legitimate observations, causing:
- Token waste: Each garbage observation is ~2KB of narrative text
- Stale directive injection: Old user directives like
[search-mode], [analyze-mode], or one-off instructions get re-injected into new sessions, interfering with current behavior
- Progressive degradation: Gets worse over time as more garbage accumulates
Evidence
In my project database (~/.open-mem/memory.db), out of 4710 total observations, 2330 (49%) were "User request:" type observations — all internal extraction prompts. Sample:
title: "User request: <task>\nAnalyze the following tool output and extract a struc..."
narrative: "<task>\nAnalyze the following tool output and extract a structured observation.\n</task>\n\n<tool_name>todowrite</tool_name>\n\n<tool_output>..."
type: discovery
tool_name: chat.message
The remaining 2380 legitimate observations (bugfix, change, feature, decision, real discovery) were unaffected.
Temporary workaround
Periodically run:
UPDATE observations SET deleted_at = datetime('now')
WHERE title LIKE 'User request:%' AND deleted_at IS NULL;
Suggested fix
The observation extraction pipeline should filter out messages where the content matches the internal extraction prompt pattern before inserting into the observations table. Specifically, skip any message whose content starts with <task>\nAnalyze the following tool output (the extraction prompt template).
Environment
- open-mem: v0.14.2
- OpenCode with oh-my-openagent plugin
Summary
The observation extraction pipeline captures its own internal processing prompts as observations. These accumulate over time and get injected back into context via
true_memory_context, wasting tokens and injecting stale user directives into new sessions.Two symptoms, one root cause
Symptom 1: Internal prompts stored as observations
Every tool execution triggers an observation extraction flow:
pending_messagesqueue<task>Analyze the following tool output and extract a structured observation.</task>observationstableBug: The internal extraction prompt itself (from step 2) gets captured as an observation with
tool_name="chat.message"and stored in the database. Thetitlefield becomes"User request: <task>\nAnalyze the following tool output..."and thenarrativecontains the raw prompt + tool output.Symptom 2: Garbage observations pollute context injection
The
true_memory_contextinjection retrieves relevant observations and injects them into the prompt. These internal prompts are retrieved alongside legitimate observations, causing:[search-mode],[analyze-mode], or one-off instructions get re-injected into new sessions, interfering with current behaviorEvidence
In my project database (
~/.open-mem/memory.db), out of 4710 total observations, 2330 (49%) were"User request:"type observations — all internal extraction prompts. Sample:The remaining 2380 legitimate observations (bugfix, change, feature, decision, real discovery) were unaffected.
Temporary workaround
Periodically run:
Suggested fix
The observation extraction pipeline should filter out messages where the content matches the internal extraction prompt pattern before inserting into the
observationstable. Specifically, skip any message whose content starts with<task>\nAnalyze the following tool output(the extraction prompt template).Environment