Skip to content

feat(tools): trigger-phrase nudges in longterm_memory description#571

Open
qhkm wants to merge 3 commits into
mainfrom
feat/longterm-memory-nudges
Open

feat(tools): trigger-phrase nudges in longterm_memory description#571
qhkm wants to merge 3 commits into
mainfrom
feat/longterm-memory-nudges

Conversation

@qhkm
Copy link
Copy Markdown
Owner

@qhkm qhkm commented May 3, 2026

Summary

  • Rewrite the longterm_memory tool's description() to enumerate concrete "Use when" / "Do NOT use when" triggers, mirroring the pattern used by Hermes Agent's memory_tool.py.
  • Add a doc-test (test_tool_description_has_trigger_phrases) that guards the trigger block so future edits cannot silently strip it.

This is Phase 1.5 of adopting Hermes Agent's "self-improving loop" pattern — the actual nudge mechanism in Hermes is not a background agent, it's strong trigger-phrase language in tool descriptions. The model re-reads tool descriptions on every turn, so naming the triggers turns memory persistence into a reliable per-turn check rather than something the model forgets to do.

Why

Today the description is functional but only tells the model how to call the tool, not when. The model only persists memories when explicitly told to. Adding concrete trigger phrases ("don't do that again", "remember this", "I always want X") aligns the description with the situations a user actually wants persisted, and the counter-triggers ("already in CLAUDE.md", "conversation-scoped") prevent over-persistence.

Test plan

  • cargo fmt -- --check passes
  • cargo clippy -- -D warnings clean
  • cargo nextest run --lib — 3501 tests pass
  • cargo test --doc — 128 doc tests pass
  • New test_tool_description_has_trigger_phrases asserts the canonical phrases are present
  • Existing test_tool_description still passes

Reference

Closes #569

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation
    • Expanded guidance for the long-term memory tool with explicit "Use when" and "Do NOT use when" trigger phrases.
    • Added concrete examples and phrasing to show appropriate vs. inappropriate uses.
    • Clarified that the tool only persists durable corrections/preferences when they generalize beyond the current task and to consult project docs first.

Rewrite the longterm_memory tool description to enumerate concrete
"Use when" / "Do NOT use when" triggers, mirroring the pattern used by
Hermes Agent's memory_tool.py. The model re-reads tool descriptions on
every turn, so naming the triggers turns memory persistence into a
reliable per-turn check rather than something the model forgets to do.

Adds a doc-test that asserts the trigger-phrase block is present so a
future edit cannot silently strip it.

Closes #569

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e8d095e-b592-45ed-9fee-1d4ac062a8a1

📥 Commits

Reviewing files that changed from the base of the PR and between 64b5eff and 5a7321c.

📒 Files selected for processing (1)
  • src/tools/longterm_memory.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/tools/longterm_memory.rs

📝 Walkthrough

Walkthrough

The LongTermMemoryTool description was expanded into a multi-line spec with explicit "Use when:" and "Do NOT use when:" trigger phrases, plus a tip to check categories; unit tests and two docs (AGENTS.md, CLAUDE.md) were updated to assert and document the new guidance.

Long-Term Memory Tool Description Enhancement

Layer / File(s) Summary
Description Enhancement
src/tools/longterm_memory.rs
Tool description replaced a brief sentence with a multi-line spec including "Use when:" triggers (user corrections, persistent preferences, environment quirks, project conventions), "Do NOT use when:" counter-guidance (facts already in repo docs, conversation-scoped info, unsignaled persistence), canonical trigger examples, and a tip to call categories/list_categories before set.
Core Tests Updated
src/tools/longterm_memory.rs (tests)
Existing test assertions were updated to match the expanded description; string checks now look for the new sections and phrases.
New Test Added
src/tools/longterm_memory.rs (tests)
Added test_tool_description_has_trigger_phrases to assert presence of "Use when:", "Do NOT use when:", canonical trigger phrases, and repo-doc warning (AGENTS.md/CLAUDE.md/README).
Docs / Project Snapshot
AGENTS.md, CLAUDE.md
AGENTS.md and CLAUDE.md updated to mention the longterm_memory tool now advertises explicit use/counter-use trigger phrases and only persists durable items when generalized beyond current task.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A little rabbit hops and grins with glee,

"Remember this" — a kindly memory.
Use the triggers, save what's meant to stay,
Skip the ephemeral, let repo notes play.
Hopping on, the agent learns the way.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(tools): trigger-phrase nudges in longterm_memory description' clearly summarizes the main change: adding explicit trigger-phrase guidance to the longterm_memory tool description.
Linked Issues check ✅ Passed The PR fully implements all requirements from issue #569: rewrites longterm_memory description with 'Use when' and 'Do NOT use when' trigger phrases, adds assertion doc-test, includes categories guidance, and ensures all existing tests pass.
Out of Scope Changes check ✅ Passed All changes are narrowly scoped to the PR objectives: longterm_memory tool description rewrite, new doc-test for trigger-phrase assertion, and documentation updates in AGENTS.md and CLAUDE.md. No unrelated behavioral code changes introduced.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/longterm-memory-nudges

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/tools/longterm_memory.rs`:
- Around line 409-428: The test test_tool_description_has_trigger_phrases is
using logical OR (||) for multi-phrase checks so removal of one canonical phrase
can pass silently; update the assertions that currently use "desc.contains(...)
|| desc.contains(...)" to require both phrases (use &&) or split them into two
separate assert! calls so each canonical trigger phrase is enforced individually
(refer to test_tool_description_has_trigger_phrases, temp_tool, and desc to
locate the checks).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 48e99be8-d1a9-4550-9ea6-7d6dcf5f92ca

📥 Commits

Reviewing files that changed from the base of the PR and between 2c743d3 and 8585ffb.

📒 Files selected for processing (1)
  • src/tools/longterm_memory.rs

Comment thread src/tools/longterm_memory.rs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
src/tools/longterm_memory.rs (1)

420-427: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

|| assertions still allow silent phrase removal — unresolved from the previous review.

Lines 420-423 and 424-427 both use ||, so dropping all-but-one phrase per block still passes the test. The new three-way || on line 425 (AGENTS.md || CLAUDE.md || README) is actually weaker than the two-way form flagged before: any two of the three doc references can now be silently deleted without failing the guard.

The stated PR goal is "future edits cannot remove it silently", which the current assertions do not achieve.

🛡️ Proposed fix: one assertion per canonical phrase
-        assert!(
-            desc.contains("remember this") || desc.contains("don't do that again"),
-            "description should reference the canonical user-correction phrases",
-        );
-        assert!(
-            desc.contains("AGENTS.md") || desc.contains("CLAUDE.md") || desc.contains("README"),
-            "description should warn against duplicating repo-level docs",
-        );
+        assert!(
+            desc.contains("remember this"),
+            "description must contain 'remember this' trigger phrase",
+        );
+        assert!(
+            desc.contains("don't do that again"),
+            "description must contain \"don't do that again\" trigger phrase",
+        );
+        assert!(
+            desc.contains("AGENTS.md"),
+            "description must warn against duplicating AGENTS.md",
+        );
+        assert!(
+            desc.contains("CLAUDE.md"),
+            "description must warn against duplicating CLAUDE.md",
+        );
+        assert!(
+            desc.contains("README"),
+            "description must warn against duplicating README",
+        );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/tools/longterm_memory.rs` around lines 420 - 427, The current compound
assertions in longterm_memory.rs (the assert! calls that check
desc.contains(...) for the correction phrases and for repo docs) allow silent
removal of all-but-one phrase because they use ||; replace those compound checks
with separate assert! statements for each canonical phrase so each required
string is independently verified: assert that desc contains "remember this",
assert that desc contains "don't do that again", and separately assert that desc
contains "AGENTS.md", assert that desc contains "CLAUDE.md", and assert that
desc contains "README" (reference the existing assert! usage and the local
variable desc to locate where to change).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/tools/longterm_memory.rs`:
- Around line 420-427: The current compound assertions in longterm_memory.rs
(the assert! calls that check desc.contains(...) for the correction phrases and
for repo docs) allow silent removal of all-but-one phrase because they use ||;
replace those compound checks with separate assert! statements for each
canonical phrase so each required string is independently verified: assert that
desc contains "remember this", assert that desc contains "don't do that again",
and separately assert that desc contains "AGENTS.md", assert that desc contains
"CLAUDE.md", and assert that desc contains "README" (reference the existing
assert! usage and the local variable desc to locate where to change).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 48b45a9b-c42f-483c-8483-f8bb36ec98b5

📥 Commits

Reviewing files that changed from the base of the PR and between 8585ffb and 64b5eff.

📒 Files selected for processing (3)
  • AGENTS.md
  • CLAUDE.md
  • src/tools/longterm_memory.rs
✅ Files skipped from review due to trivial changes (2)
  • AGENTS.md
  • CLAUDE.md

…erts

CodeRabbit caught that `||` chains in `test_tool_description_has_trigger_phrases`
let any all-but-one canonical phrase be silently deleted while the test still
passed. The whole point of the guard is to prevent silent regression of the
trigger block, so each phrase now lives in its own `assert!` with a specific
failure message:

  - "remember this"
  - "don't do that again"
  - "AGENTS.md"
  - "CLAUDE.md"
  - "README"

No production code change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

chore(tools): trigger-phrase nudges in longterm_memory tool description

1 participant