diff options
| author | batsumaru <> | 2026-09-15 18:08:05 +0900 |
|---|---|---|
| committer | batsumaru <> | 2026-09-15 18:08:05 +0900 |
| commit | d164005eb54dfc97a5827524948e804a37779f7c (patch) | |
| tree | f3233476182352ff2bde07551c32136fc9c1798b | |
| parent | 796c8978eaaf080146ba41ec49c75f3c7f3cf404 (diff) | |
Refined long-term memory
| -rw-r--r-- | agent.toml | 130 | ||||
| -rw-r--r-- | personal_agent/llm.py | 2 | ||||
| -rw-r--r-- | personal_agent/tools/memory.py | 60 |
3 files changed, 163 insertions, 29 deletions
@@ -52,24 +52,136 @@ ongoing objective, replace the current task with the new objective. Do not create a task merely because a conversation has multiple turns. """ working_memory = """ -Maintain working memory as the current state of the task, not as a transcript -of everything the user has ever said. +Working memory is temporary state used to track the current task or +conversation. It is not persistent memory and should not be used for +information that should survive the current conversation. -Store information when it is likely to remain relevant to the current task. +Use working_memory_add_fact for stable information that is relevant to the +current task or ongoing conversation. -When the user changes, corrects, or replaces previously stored information: +Use working_memory_add_note for temporary information that may help with the +current task. + +When the user changes, corrects, or replaces previously stored working-memory +information: - treat the new information as authoritative; - remove or update the stale information rather than keeping both; - do not preserve contradictory facts or notes as separate entries. -Use facts for stable task-relevant information and decisions. -Use notes for temporary information that may help with ongoing work. +Use working-memory facts for stable task-relevant information and working-memory +notes for temporary information that may help with ongoing work. Do not store every conversational detail. Do not store temporary side conversations unless they are relevant to the current task. -Before adding a fact or note, consider whether an existing memory entry -describes the same piece of information. If the user is revising that -information, remove the stale entry before adding the new one. +Before adding a working-memory fact or note, consider whether an existing +working-memory entry describes the same piece of information. If the user is +revising that information, remove the stale entry before adding the new one. + +For durable user preferences, facts, decisions, goals, relationships, or +meaningful past experiences that should remain useful after the current +conversation, use the long-term-memory tools instead. +""" +long_term_memory = """ +Long-term memory is persistent information that should remain useful after +the current conversation ends. Use it selectively, but save information when +it clearly meets the criteria below. + +SEMANTIC MEMORY: +When the user states a durable personal fact, preference, decision, goal, +relationship, or other persistent information about themselves, save it with +memory_save using category "semantic". + +Examples: +- "C++ is my preferred language for systems programming." -> save +- "I prefer dark themes." -> save +- "I've decided to use PostgreSQL for this project." -> save if the decision + is durable and relevant beyond the current task + +Do not save information when the user explicitly indicates uncertainty, +temporariness, or mere consideration. +Examples: +- "I'm thinking about using Rust." -> do not save +- "I might switch to Rust." -> do not save +- "I'm trying Rust this week." -> do not save unless the user indicates it + is a durable preference + +EPISODIC MEMORY: +When the user describes a meaningful past event or experience that is likely +to be useful in future conversations, save it with memory_save using category +"episodic". + +Do not save ordinary daily events or trivial anecdotes merely because they +happened. + +WORKING MEMORY VS LONG-TERM MEMORY: +Working memory contains information needed for the current task or ongoing +conversation. Long-term memory contains information that should remain useful +after the current task or conversation ends. + +Use working-memory tools for information that is relevant to the current task. + +Use long-term memory tools for information that should persist beyond the +current task or conversation. + +Do not store the same information in both working memory and long-term memory +unless it serves two genuinely different purposes. + +If information is saved as long-term memory, do not also call +memory_add_fact or memory_add_note for the same information unless that +information is independently necessary for the current task. + +UPDATING EXISTING MEMORY: +When the user changes, corrects, replaces, or supersedes a durable fact or +preference, the new information replaces the old information. + +Before saving a replacement: +1. Search for existing memories about the subject. +2. Use broad, simple search queries based on the key subject or entity. +3. Do not assume one search query will find every relevant memory. +4. If a search does not find the expected old memory, perform additional + searches using the important specific terms from the user's statement. +5. Identify memories that represent the old or superseded value. +6. Delete those stale memories with memory_delete. +7. Save the new value with memory_save. + +For example, if the user says: +"I've changed my preferred systems programming language from C++ to Rust." + +You should: +1. Search for the existing programming-language preference. +2. If necessary, separately search for "C++" and "Rust" to find relevant + existing memories. +3. Delete the stale C++ preference. +4. Save the current Rust preference. + +Do not preserve old preference values merely because they were previously true. +Long-term semantic memory represents the user's current durable state, not a +history of superseded preferences. + +Do not create a combined historical memory such as: +"Previously preferred C++, now prefers Rust" +unless the user explicitly asks to remember the history itself. + +When replacing a preference, save the new preference as a normal current-state +statement, for example: +"Rust is my preferred language for systems programming." + +Do not delete unrelated memories merely because they mention the same general +subject. Delete only memories that represent the superseded information. + +RETRIEVAL: +Use memory_search when existing long-term memory may be relevant to answering +the user's request or carrying out their task. + +When a user explicitly asks what you remember, use memory_search rather than +relying only on the current conversation or working memory. + +When searching for an existing memory to update, prefer broad searches using +the main subject rather than a highly specific sentence or phrase. If the +result appears incomplete, search again using important specific terms. + +Do not search merely because every conversational turn could theoretically +relate to memory. """ diff --git a/personal_agent/llm.py b/personal_agent/llm.py index 960e798..418c478 100644 --- a/personal_agent/llm.py +++ b/personal_agent/llm.py @@ -25,7 +25,7 @@ class LLM: self, messages: list[dict[str, object]], tools: list[dict[str, object]] | None = None, - max_tokens: int = 256, + max_tokens: int = 512, ) -> LLMResponse: payload: dict[str, object] = { "messages": messages, diff --git a/personal_agent/tools/memory.py b/personal_agent/tools/memory.py index 851a69d..c84202f 100644 --- a/personal_agent/tools/memory.py +++ b/personal_agent/tools/memory.py @@ -62,11 +62,16 @@ class MemoryAddFactTool(Tool): @property def name(self) -> str: - return "memory_add_fact" + return "working_memory_add_fact" @property def description(self) -> str: - return "Add a useful fact to the current working memory." + return ( + "Add a fact to the current task's working memory. Working memory is " + "temporary and is used to track information needed during the current " + "task or conversation. Do not use this for durable user preferences " + "or facts that should survive the conversation." + ) @property def schema(self) -> dict[str, object]: @@ -98,11 +103,16 @@ class MemoryAddNoteTool(Tool): @property def name(self) -> str: - return "memory_add_note" + return "working_memory_add_note" @property def description(self) -> str: - return "Add a useful note to the current working memory." + return ( + "Add a temporary note to the current task's working memory. Use this " + "for information that may help with the current task or conversation. " + "Do not use this for durable information that should survive the " + "conversation." + ) @property def schema(self) -> dict[str, object]: @@ -134,11 +144,15 @@ class MemoryRemoveFactTool(Tool): @property def name(self) -> str: - return "memory_remove_fact" + return "working_memory_remove_fact" @property def description(self) -> str: - return "Remove a fact from the working memory when it is no longer true or relevant." + return ( + "Remove a fact from the current task's working memory. This only " + "changes temporary working memory; it does not delete persistent " + "long-term memory." + ) @property def schema(self) -> dict[str, object]: @@ -170,11 +184,15 @@ class MemoryRemoveNoteTool(Tool): @property def name(self) -> str: - return "memory_remove_note" + return "working_memory_remove_note" @property def description(self) -> str: - return "Remove a note from the working memory when it is no longer true or relevant." + return ( + "Remove a note from the current task's working memory. This only " + "changes temporary working memory; it does not delete persistent " + "long-term memory." + ) @property def schema(self) -> dict[str, object]: @@ -206,14 +224,15 @@ class LongTermMemorySaveTool(Tool): @property def name(self) -> str: - return "memory_save" + return "long_term_memory_save" @property def description(self) -> str: return ( - "Save durable information for use across future conversations. " - "Use semantic for stable facts or preferences, and episodic for " - "meaningful past events." + "Save persistent information for use in future conversations. Use " + "this for durable user preferences, facts, decisions, goals, " + "relationships, or meaningful past experiences. This is long-term " + "memory, not temporary working memory." ) @property @@ -267,14 +286,16 @@ class LongTermMemorySearchTool(Tool): @property def name(self) -> str: - return "memory_search" + return "long_term_memory_search" @property def description(self) -> str: return ( - "Search long-term memory for information relevant to the current " - "conversation. Use semantic for stable facts or preferences, and " - "episodic for meaningful past events." + "Search persistent long-term memories from previous conversations. " + "Use this when information from past conversations may be relevant, " + "when the user asks what you remember, or when checking whether a " + "durable fact or preference is already stored. This does not search " + "working memory." ) @property @@ -351,13 +372,14 @@ class LongTermMemoryDeleteTool(Tool): @property def name(self) -> str: - return "memory_delete" + return "long_term_memory_delete" @property def description(self) -> str: return ( - "Delete a long-term memory by its exact ID. Only delete a memory " - "when its ID is known from a previous memory search or save result." + "Delete a specific persistent long-term memory by its ID. This " + "deletes long-term memory, not working memory. When replacing or " + "forgetting an existing memory, search for it first to obtain its ID." ) @property |
