Skip to content

fix(run_agent): isolate background review fork from external memory plugins - #27190

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-48113ebb
May 17, 2026
Merged

fix(run_agent): isolate background review fork from external memory plugins#27190
teknium1 merged 1 commit into
mainfrom
hermes/hermes-48113ebb

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Background memory/skill review forks no longer leak harness prompts into external memory plugin namespaces (honcho, mem0, supermemory, etc.).

Reported by @utku — the review harness prompts (Review the conversation above and update the skill library...) were getting ingested by memory plugins as if they were real user conversation.

Root cause

_spawn_background_review() creates a fresh AIAgent to do the review. That __init__ rebuilds its own _memory_manager from memory.provider in config, scoped to the parent's session_id. Then run_conversation() triggers three ingestion sites against the user's real memory namespace:

Site What gets written
on_turn_start(turn_count, prompt) harness prompt as the turn's user message; advances cadence
prefetch_all(prompt) harness prompt as a recall query
sync_all(prompt, review_output, session_id) harness prompt + review output as a (user, assistant) pair

Changes

  • run_agent.py _spawn_background_review() — pass skip_memory=True to the fork's AIAgent(...) constructor
  • tests/run_agent/test_background_review.py — regression test asserting the kwarg is set

Why this works

skip_memory=True short-circuits both _memory_store and _memory_manager construction in __init__. The existing fork-setup block at L4310-4314 explicitly rebinds _memory_store, _memory_enabled, _user_profile_enabled, and the nudge intervals from the parent right after construction — so:

  • Built-in MEMORY.md / USER.md writes via the memory tool still land on disk ✓
  • Skill writes still work (skills don't go through MemoryManager at all) ✓
  • All three ingestion sites short-circuit on if self._memory_manager:
  • shutdown_memory_provider() on the fork becomes a no-op (nothing to shut down) ✓
  • Cached system prompt is still inherited verbatim from parent (prefix cache parity preserved) ✓

Validation

Before After
Fork _memory_manager (with honcho configured) non-None, providers=['honcho'] None
Fork _memory_store after rebinding parent's store object parent's store object (identity preserved)
Fork _memory_enabled after rebinding True True
on_turn_start / prefetch_all / sync_all gates all evaluated all short-circuit
Targeted background-review tests 28/28 pass 28/28 pass

E2E verified with a stubbed honcho provider in an isolated HERMES_HOME: with skip_memory=True the fork constructs with _memory_manager=None even though memory.provider=honcho is set in config; without it, the fork builds a manager wired to the stub.

Test plan

scripts/run_tests.sh tests/run_agent/test_background_review.py tests/run_agent/test_background_review_cache_parity.py tests/run_agent/test_background_review_toolset_restriction.py tests/run_agent/test_review_prompt_class_first.py — 28 passed.

…lugins

Pass skip_memory=True to the AIAgent constructor used by
_spawn_background_review() so the review fork's __init__ no longer
rebuilds a _memory_manager wired to honcho / mem0 / supermemory /
etc. under the parent's session_id.

Before this change, the review fork ingested its harness prompt
(the 'Review the conversation above and update the skill library...'
text) into the user's real memory namespace via three sites in
run_conversation():
  - on_turn_start(turn_count, prompt)      cadence + turn-message
  - prefetch_all(prompt)                   recall query
  - sync_all(prompt, review_output, ...)   harness + review output
                                           recorded as a
                                           (user, assistant) pair

Built-in MEMORY.md / USER.md state is still rebound from the parent
right after construction, so memory(action='add') writes from the
review continue to land on disk; only the external-plugin side
effects are removed.

Reported by @utku.
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-48113ebb vs origin/main

ruff

Total: 1 on HEAD, 1 on base (➖ 0)

🆕 New issues (1):

Rule Count
PLW1514 1
First entries
hermes_cli/send_cmd.py:61: [PLW1514] `pathlib.Path(...).read_text` without explicit `encoding` argument

✅ Fixed issues (1):

Rule Count
PLW1514 1
First entries
../../../../../tmp/lint-base/hermes_cli/send_cmd.py:61: [PLW1514] `pathlib.Path(...).read_text` without explicit `encoding` argument

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 8350 on HEAD, 8350 on base (➖ 0)

🆕 New issues (3):

Rule Count
invalid-argument-type 3
First entries
run_agent.py:14073: [invalid-argument-type] invalid-argument-type: Argument to function `_is_oauth_token` is incorrect: Expected `str`, found `str | dict[Unknown | str, Unknown | str | dict[str, str]] | Any | ... omitted 3 union elements`
run_agent.py:14076: [invalid-argument-type] invalid-argument-type: Argument to function `len` is incorrect: Expected `Sized`, found `(str & ~AlwaysFalsy) | (dict[Unknown | str, Unknown | str | dict[str, str]] & ~AlwaysFalsy) | (Any & ~AlwaysFalsy) | ... omitted 3 union elements`
run_agent.py:7770: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | dict[Unknown | str, Unknown | str | dict[str, str]] | Any | ... omitted 3 union elements`

✅ Fixed issues (3):

Rule Count
invalid-argument-type 3
First entries
run_agent.py:7754: [invalid-argument-type] invalid-argument-type: Argument to function `build_anthropic_client` is incorrect: Expected `str`, found `str | dict[Unknown, Unknown] | Any | ... omitted 3 union elements`
run_agent.py:14057: [invalid-argument-type] invalid-argument-type: Argument to function `_is_oauth_token` is incorrect: Expected `str`, found `str | dict[Unknown, Unknown] | Any | ... omitted 3 union elements`
run_agent.py:14060: [invalid-argument-type] invalid-argument-type: Argument to function `len` is incorrect: Expected `Sized`, found `(str & ~AlwaysFalsy) | (dict[Unknown, Unknown] & ~AlwaysFalsy) | (Any & ~AlwaysFalsy) | ... omitted 3 union elements`

Unchanged: 4364 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@cardtest15-coder

This comment was marked as spam.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/plugins Plugin system and bundled plugins tool/memory Memory tool and memory providers labels May 17, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competing fix: this PR and #24281 (reopen of #21511) both address #21510 — background review fork leaking harness prompts into external memory plugins. This PR takes a cleaner approach (skip_memory=True with detailed comments + regression test) while #24281 also adds defense-in-depth in the Honcho plugin itself.

@teknium1
teknium1 merged commit 973f27e into main May 17, 2026
19 of 21 checks passed
@teknium1
teknium1 deleted the hermes/hermes-48113ebb branch May 17, 2026 03:33
teknium1 added a commit that referenced this pull request May 17, 2026
…lugins (#27190)

Original commit 973f27e by Teknium targeted _spawn_background_review in
pre-refactor run_agent.py. The body now lives in
agent/background_review._spawn_background_review — re-applied there.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…lugins (NousResearch#27190)

Pass skip_memory=True to the AIAgent constructor used by
_spawn_background_review() so the review fork's __init__ no longer
rebuilds a _memory_manager wired to honcho / mem0 / supermemory /
etc. under the parent's session_id.

Before this change, the review fork ingested its harness prompt
(the 'Review the conversation above and update the skill library...'
text) into the user's real memory namespace via three sites in
run_conversation():
  - on_turn_start(turn_count, prompt)      cadence + turn-message
  - prefetch_all(prompt)                   recall query
  - sync_all(prompt, review_output, ...)   harness + review output
                                           recorded as a
                                           (user, assistant) pair

Built-in MEMORY.md / USER.md state is still rebound from the parent
right after construction, so memory(action='add') writes from the
review continue to land on disk; only the external-plugin side
effects are removed.

Reported by @utku.
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…lugins (NousResearch#27190)

Original commit 973f27e by Teknium targeted _spawn_background_review in
pre-refactor run_agent.py. The body now lives in
agent/background_review._spawn_background_review — re-applied there.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
Seven74AI pushed a commit to Seven74AI/hermes-agent that referenced this pull request Jun 13, 2026
…lugins (NousResearch#27190)

Pass skip_memory=True to the AIAgent constructor used by
_spawn_background_review() so the review fork's __init__ no longer
rebuilds a _memory_manager wired to honcho / mem0 / supermemory /
etc. under the parent's session_id.

Before this change, the review fork ingested its harness prompt
(the 'Review the conversation above and update the skill library...'
text) into the user's real memory namespace via three sites in
run_conversation():
  - on_turn_start(turn_count, prompt)      cadence + turn-message
  - prefetch_all(prompt)                   recall query
  - sync_all(prompt, review_output, ...)   harness + review output
                                           recorded as a
                                           (user, assistant) pair

Built-in MEMORY.md / USER.md state is still rebound from the parent
right after construction, so memory(action='add') writes from the
review continue to land on disk; only the external-plugin side
effects are removed.

Reported by @utku.
Seven74AI pushed a commit to Seven74AI/hermes-agent that referenced this pull request Jun 13, 2026
…lugins (NousResearch#27190)

Original commit 973f27e by Teknium targeted _spawn_background_review in
pre-refactor run_agent.py. The body now lives in
agent/background_review._spawn_background_review — re-applied there.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
alt-glitch pushed a commit that referenced this pull request Jun 14, 2026
…lugins (#27190)

Pass skip_memory=True to the AIAgent constructor used by
_spawn_background_review() so the review fork's __init__ no longer
rebuilds a _memory_manager wired to honcho / mem0 / supermemory /
etc. under the parent's session_id.

Before this change, the review fork ingested its harness prompt
(the 'Review the conversation above and update the skill library...'
text) into the user's real memory namespace via three sites in
run_conversation():
  - on_turn_start(turn_count, prompt)      cadence + turn-message
  - prefetch_all(prompt)                   recall query
  - sync_all(prompt, review_output, ...)   harness + review output
                                           recorded as a
                                           (user, assistant) pair

Built-in MEMORY.md / USER.md state is still rebound from the parent
right after construction, so memory(action='add') writes from the
review continue to land on disk; only the external-plugin side
effects are removed.

Reported by @utku.
alt-glitch pushed a commit that referenced this pull request Jun 14, 2026
…lugins (#27190)

Original commit ba371c6 by Teknium targeted _spawn_background_review in
pre-refactor run_agent.py. The body now lives in
agent/background_review._spawn_background_review — re-applied there.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
T02200059 pushed a commit to T02200059/hermes-agent that referenced this pull request Jun 18, 2026
…lugins (NousResearch#27190)

Pass skip_memory=True to the AIAgent constructor used by
_spawn_background_review() so the review fork's __init__ no longer
rebuilds a _memory_manager wired to honcho / mem0 / supermemory /
etc. under the parent's session_id.

Before this change, the review fork ingested its harness prompt
(the 'Review the conversation above and update the skill library...'
text) into the user's real memory namespace via three sites in
run_conversation():
  - on_turn_start(turn_count, prompt)      cadence + turn-message
  - prefetch_all(prompt)                   recall query
  - sync_all(prompt, review_output, ...)   harness + review output
                                           recorded as a
                                           (user, assistant) pair

Built-in MEMORY.md / USER.md state is still rebound from the parent
right after construction, so memory(action='add') writes from the
review continue to land on disk; only the external-plugin side
effects are removed.

Reported by @utku.
T02200059 pushed a commit to T02200059/hermes-agent that referenced this pull request Jun 18, 2026
…lugins (NousResearch#27190)

Original commit 9002bb9 by Teknium targeted _spawn_background_review in
pre-refactor run_agent.py. The body now lives in
agent/background_review._spawn_background_review — re-applied there.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
liuchanchen pushed a commit to liuchanchen/hermes-agent that referenced this pull request Jun 23, 2026
…lugins (NousResearch#27190)

Pass skip_memory=True to the AIAgent constructor used by
_spawn_background_review() so the review fork's __init__ no longer
rebuilds a _memory_manager wired to honcho / mem0 / supermemory /
etc. under the parent's session_id.

Before this change, the review fork ingested its harness prompt
(the 'Review the conversation above and update the skill library...'
text) into the user's real memory namespace via three sites in
run_conversation():
  - on_turn_start(turn_count, prompt)      cadence + turn-message
  - prefetch_all(prompt)                   recall query
  - sync_all(prompt, review_output, ...)   harness + review output
                                           recorded as a
                                           (user, assistant) pair

Built-in MEMORY.md / USER.md state is still rebound from the parent
right after construction, so memory(action='add') writes from the
review continue to land on disk; only the external-plugin side
effects are removed.

Reported by @utku.
liuchanchen pushed a commit to liuchanchen/hermes-agent that referenced this pull request Jun 23, 2026
…lugins (NousResearch#27190)

Original commit 0422ec6 by Teknium targeted _spawn_background_review in
pre-refactor run_agent.py. The body now lives in
agent/background_review._spawn_background_review — re-applied there.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
donbowman pushed a commit to donbowman/hermes-agent that referenced this pull request Jul 13, 2026
…lugins (NousResearch#27190)

Pass skip_memory=True to the AIAgent constructor used by
_spawn_background_review() so the review fork's __init__ no longer
rebuilds a _memory_manager wired to honcho / mem0 / supermemory /
etc. under the parent's session_id.

Before this change, the review fork ingested its harness prompt
(the 'Review the conversation above and update the skill library...'
text) into the user's real memory namespace via three sites in
run_conversation():
  - on_turn_start(turn_count, prompt)      cadence + turn-message
  - prefetch_all(prompt)                   recall query
  - sync_all(prompt, review_output, ...)   harness + review output
                                           recorded as a
                                           (user, assistant) pair

Built-in MEMORY.md / USER.md state is still rebound from the parent
right after construction, so memory(action='add') writes from the
review continue to land on disk; only the external-plugin side
effects are removed.

Reported by @utku.
donbowman pushed a commit to donbowman/hermes-agent that referenced this pull request Jul 13, 2026
…lugins (NousResearch#27190)

Original commit 973f27e by Teknium targeted _spawn_background_review in
pre-refactor run_agent.py. The body now lives in
agent/background_review._spawn_background_review — re-applied there.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…lugins (NousResearch#27190)

Pass skip_memory=True to the AIAgent constructor used by
_spawn_background_review() so the review fork's __init__ no longer
rebuilds a _memory_manager wired to honcho / mem0 / supermemory /
etc. under the parent's session_id.

Before this change, the review fork ingested its harness prompt
(the 'Review the conversation above and update the skill library...'
text) into the user's real memory namespace via three sites in
run_conversation():
  - on_turn_start(turn_count, prompt)      cadence + turn-message
  - prefetch_all(prompt)                   recall query
  - sync_all(prompt, review_output, ...)   harness + review output
                                           recorded as a
                                           (user, assistant) pair

Built-in MEMORY.md / USER.md state is still rebound from the parent
right after construction, so memory(action='add') writes from the
review continue to land on disk; only the external-plugin side
effects are removed.

Reported by @utku.
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…lugins (NousResearch#27190)

Original commit 973f27e by Teknium targeted _spawn_background_review in
pre-refactor run_agent.py. The body now lives in
agent/background_review._spawn_background_review — re-applied there.

Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have tool/memory Memory tool and memory providers type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants