NousResearch/hermes-agent

Missing memory write bridge in sequential tool execution

Cluster 10174. Data as of

Nothing open on GitHub. Fix merged in #10507 on 15 Apr 2026. Check it covers your case.

The short answer

0open issues
0open PRs
3items grouped
Known?
Yes. 3 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #10507. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this resolved, deciding PR #10507. That is separate from the fix event.
Still open
Nothing open on GitHub.

Multiple fixes addressing the absence of an on_memory_write bridge in the _execute_tool_calls_sequential code path. The members appear to be duplicate or closely related attempts at the same patch.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #10507 fix: add on_memory_write bridge to sequential tool execution path

    merged to main

    files: run_agent.py, tests/agent/test_memory_provider.py

    Show the diff
    • run_agent.py
      @@ -7466,6 +7466,16 @@ def _execute_tool_calls_sequential(self, assistant_message, messages: list, effe
                           old_text=function_args.get("old_text"),
                           store=self._memory_store,
                       )
      +                # Bridge: notify external memory provider of built-in memory writes
      +                if self._memory_manager and function_args.get("action") in ("add", "replace"):
      +                    try:
      +                        self._memory_manager.on_memory_write(
      +                            function_args.get("action", ""),
      +                            target,
      +                            function_args.get("content", ""),
      +                        )
      +                    except Exception:
      +                        pass
                       tool_duration = time.time() - tool_start_time
                       if self._should_emit_quiet_tool_messages():
                           self._vprint(f"  {_get_cute_tool_message_impl('memory', function_args, tool_duration, result=function_result)}")
    • tests/agent/test_memory_provider.py
      @@ -736,3 +736,61 @@ def test_on_session_end_tolerates_failure(self):
               mgr.add_provider(bad)
       
               mgr.on_session_end([])  # must not raise
      +
      +
      +# ---------------------------------------------------------------------------
      +# on_memory_write bridge — must fire from both concurrent AND sequential paths
      +# ---------------------------------------------------------------------------
      +
      +
      +class TestOnMemoryWriteBridge:
      +    """Verify that MemoryManager.on_memory_write is called when built-in
      +    memory writes happen.  This is a regression test for #10174 where the
      +    sequential tool execution path (_execute_tool_calls_sequential) was
      +    missing the bridge call, so single memory tool calls never notified
      +    external memory providers.
      +    """
      +
      +    def test_on_memory_write_add(self):
      +        """on_memory_write fires for 'add' actions."""
      +        mgr = MemoryManager()
      +        p = FakeMemoryProvider("ext")
      +        mgr.add_provider(p)
      +
      +        mgr.on_memory_write("add", "memory", "new fact")
      +        assert p.memory_writes == [("add", "memory", "new fact")]
      +
      +    def test_on_memory_write_replace(self):
      +        """on_memory_write fires for 'replace' actions."""
      +        mgr = MemoryManager()
      +        p = FakeMemoryProvider("ext")
      +        mgr.add_provider(p)
      +
      +        mgr.on_memory_write("replace", "user", "updated pref")
      +        assert p.memory_writes == [("replace", "user", "updated pref")]
      +
      +    def test_on_memory_write_remove_not_bridged(self):
      +        """The bridge intentionally skips 'remove' — only add/replace notify."""
      +        # This tests the contract that run_agent.py checks:
      +        #   function_args.get("action") in ("add", "replace")
      +        mgr = MemoryManager()
      +        p = FakeMemoryProvider("ext")
      +        mgr.add_provider(p)
      +
      +        # Manager itself doesn't filter — run_agent.py does.
      +        # But providers should handle remove gracefully.
      +        mgr.on_memory_write("remove", "memory", "old fact")
      +        assert p.memory_writes == [("remove", "memory", "old fact")]
      +
      +    def test_on_memory_write_tolerates_provider_failure(self):
      +        """If a provider's on_memory_write raises, others still get notified."""
      +        mgr = MemoryManager()
      +        bad = FakeMemoryProvider("builtin")
      +        bad.on_memory_write = MagicMock(side_effect=RuntimeError("boom"))
      +        good = FakeMemoryProvider("good")
      +        mgr.add_provider(bad)
      +        mgr.add_provider(good)
      +
      +        mgr.on_memory_write("add", "user", "test")
      +        # Good provider still received the call despite bad provider crashing
      +        assert good.memory_writes == [("add", "user", "test")]

1 PR closed without merging

From the close comments: other 1

  • #10178 fix: add on_memory_write bridge to sequential tool path · other
Closed issues · 1
  • Closed#10174fix: on_memory_write bridge missing in _execute_tool_calls_sequential
How this cluster was grouped
  • Link evidence (structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
  • Pairwise link density 0.67: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Merged PRs
#10507
Closed issues
1
Attempts
1 PR closed without merging
Fix link checked
15 Apr 2026. This confirmation is old and may be out of date (a revert or reopen would not have invalidated it here); re-verify.

For your agent

The same facts, typed.