Skip to content

External memory sync should skip interrupted turns #15218

@yepyhun

Description

@yepyhun

Summary

External memory providers currently receive sync_all(original_user_message, final_response) for a turn whenever final_response and original_user_message are present. The sync path does not appear to exclude interrupted turns.

This can cause an external memory provider to persist an incomplete/interrupted exchange as if it were a completed conversational turn.

Why this matters

Memory providers need a clean boundary between:

  • a completed assistant turn that is safe to persist as conversational evidence; and
  • an interrupted/reset/cancelled turn whose final state is not reliable durable memory.

If an interrupted turn is mirrored into an external memory backend, downstream recall can treat partial assistant output, partial tool processing, or aborted work as durable conversation truth.

Current behavior in vanilla Hermes

In run_agent.py, after clear_interrupt() has been called, the external memory sync path is guarded by self._memory_manager and final_response and original_user_message, but not by the interrupted state itself:

# External memory provider: sync the completed turn + queue next prefetch.
# Use original_user_message (clean input) — user_message may contain
# injected skill content that bloats / breaks provider queries.
if self._memory_manager and final_response and original_user_message:
    try:
        self._memory_manager.sync_all(original_user_message, final_response)
        self._memory_manager.queue_prefetch_all(original_user_message)
    except Exception:
        pass

Expected behavior

External memory providers should not be asked to persist interrupted turns as completed conversation turns.

A minimal fix could be one of:

  • preserve an interrupted / was_interrupted local before clearing interrupt state and gate sync on not was_interrupted; or
  • expose a structured turn status to memory providers so they can skip non-final turns.

Suggested acceptance criteria

  • Interrupted turns do not call MemoryManager.sync_all(...) as completed turns.
  • Normal completed turns still sync as before.
  • There is a regression test for interrupted-turn memory sync behavior.
  • The fix is generic and does not depend on any specific external memory provider.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/agentCore agent loop, run_agent.py, prompt buildertool/memoryMemory tool and memory providerstype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions