summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--agent.toml130
-rw-r--r--personal_agent/llm.py2
-rw-r--r--personal_agent/tools/memory.py60
3 files changed, 163 insertions, 29 deletions
diff --git a/agent.toml b/agent.toml
index fac365a..d7873df 100644
--- a/agent.toml
+++ b/agent.toml
@@ -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