Skip to content

[Bug]: Hook message extraction conflict when using long-term memory and RAG together #1403

@laeni

Description

@laeni

Bug Description

When both StaticLongTermMemoryHook and GenericRAGHook are attached to the same agent, they interfere with each other's message extraction logic. Each hook searches for "the last user message" to use as its query, but since both hooks inject their results as USER role messages at the end of the message list, one hook may pick up the other hook's injected message instead of the original user input.

Root Cause

This is a side effect of previous fixes:

Both hooks use "find the last USER role message" to extract the user's query:

  • StaticLongTermMemoryHook#extractLastUserMessageIndex — scans from end to start, returns the first USER role message
  • GenericRAGHook#extractQueryFromMessages — scans from end to start, returns the first USER role message's text

Since hooks execute in a chain, when the second hook runs, the first hook has already appended its USER message. The second hook then picks up that injected message as the "user query", not the actual user input.

Example flow (hooks execute by priority; both have priority 50):

  1. User sends: USER: "What is the refund policy?"
  2. StaticLongTermMemoryHook runs first:
    • extractLastUserMessageIndex finds "What is the refund policy?"
    • Appends USER (name="long_term_memory"): <long_term_memory>...</long_term_memory>
  3. GenericRAGHook runs next:
    • extractQueryFromMessages finds <long_term_memory>...</long_term_memory> ✗ — this is the memory hook's output, not the user's query!
    • Uses this as the RAG retrieval query, producing irrelevant or incorrect results

The reverse scenario is equally problematic if the RAG hook runs first.

Steps to Reproduce

  1. Configure a ReActAgent with both StaticLongTermMemoryHook and GenericRAGHook
  2. Send a user query
  3. Observe that the second-executing hook uses the first hook's injected message as its retrieval query

Expected Behavior

Each hook should extract the original user input message, not the other hook's injected context.

Suggested Fix

Give injected messages distinct name identifiers so that each hook can skip them when extracting the user query:

  • StaticLongTermMemoryHook already uses name="long_term_memory" — update extractLastUserMessageIndex to skip messages where name is "retrieved_knowledge"
  • GenericRAGHook should use name="retrieved_knowledge" (instead of the default "user") — update extractQueryFromMessages to skip messages where name is "long_term_memory"

This way each hook only considers genuine user input messages, regardless of execution order.

Related Issues

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No fields configured for Bug.

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions