diff --git a/agent/prompt_builder.py b/agent/prompt_builder.py index f6e53b5b187..f1c5ab0890a 100644 --- a/agent/prompt_builder.py +++ b/agent/prompt_builder.py @@ -281,14 +281,20 @@ def build_memory_guidance(memory_enabled: bool = True, profile_enabled: bool = T "disabled, so never target='memory'. " ) return frame + ( - "Save proactively — storage has a hard character budget, and when " - "it fills, replace or consolidate stale entries in the same batch " + "Skills come first: when you learn something while doing a task — a " + "procedure, a pitfall, and the user's preferences and corrections " + "for that kind of work — record it in the skill you used or built " + "for the task (skill_manage), where it loads only when relevant. " + "Memory is the narrow exception for facts that apply to EVERY " + "session regardless of task (who the user is, environment facts, " + "standing conventions with no task home); it has a hard character " + "budget, so when it fills, replace or consolidate stale entries " "rather than skipping the save. Write entries as declarative facts, " "not instructions to yourself: 'User prefers concise responses' ✓ — " "'Always respond concisely' ✗ (imperative phrasing gets re-read as " "a directive in later sessions and can override the user's current " - "request). Route by longevity: a fact stale within a week belongs " - "in session history; procedures and workflows belong in skills." + "request). A fact stale within a week belongs in session history; " + "procedures and workflows belong in skills." ) diff --git a/tests/agent/test_prompt_builder.py b/tests/agent/test_prompt_builder.py index 6b4190f8415..4331c2bc9d2 100644 --- a/tests/agent/test_prompt_builder.py +++ b/tests/agent/test_prompt_builder.py @@ -70,7 +70,12 @@ class TestGuidanceConstants: assert "declarative facts" in MEMORY_GUIDANCE assert "imperative phrasing" in MEMORY_GUIDANCE assert "stale within a week" in MEMORY_GUIDANCE - assert "Save proactively" in MEMORY_GUIDANCE # positive posture leads + # Skills are the default home for task-learned knowledge (incl. the + # user's preferences/corrections for that work); memory is the narrow + # every-session exception. The routing rule must LEAD, not trail. + assert MEMORY_GUIDANCE.index("Skills come first") < MEMORY_GUIDANCE.index("Memory is the narrow exception") + assert "preferences and corrections" in MEMORY_GUIDANCE + assert "Save proactively" not in MEMORY_GUIDANCE assert "workflows belong" in MEMORY_GUIDANCE # The category/SKIP curricula must NOT be re-taught here. assert "PR numbers" not in MEMORY_GUIDANCE diff --git a/tools/memory_tool.py b/tools/memory_tool.py index 54dcaa71a62..eccbe82674f 100644 --- a/tools/memory_tool.py +++ b/tools/memory_tool.py @@ -1271,10 +1271,12 @@ MEMORY_SCHEMA = { "reports current/limit chars and confirms completion; one batch call finishes the " "update, so don't repeat it. Use the bare action/content/old_text fields only for a " "single lone change.\n\n" - "WHEN: save proactively when the user states a preference, correction, or personal " - "detail, or you learn a stable fact about their environment, conventions, or workflow. " - "Priority: user preferences & corrections > environment facts > procedures. The best " - "memory stops the user repeating themselves.\n\n" + "WHEN: only for facts that apply to EVERY session regardless of task: who the user " + "is, stable environment facts, standing conventions with no task home. Anything " + "learned while doing a task (procedures, pitfalls, and the user's preferences and " + "corrections for that kind of work) belongs in the task's skill via skill_manage, " + "where it loads only when relevant; memory is injected into every turn and must " + "stay small.\n\n" "IF FULL: an add is rejected with the current entries shown. Reissue as ONE batch that " "removes or shortens enough stale entries and adds the new one together.\n\n" "TARGETS: 'user' = who the user is (name, role, preferences, style). 'memory' = your "