Skip to content

fix(honcho-memory): stop assistant self-narration ingestion - #66831

Open
bbasketballer75 wants to merge 8 commits into
NousResearch:mainfrom
bbasketballer75:fix/honcho-skip-assistant-source
Open

fix(honcho-memory): stop assistant self-narration ingestion#66831
bbasketballer75 wants to merge 8 commits into
NousResearch:mainfrom
bbasketballer75:fix/honcho-skip-assistant-source

Conversation

@bbasketballer75

@bbasketballer75 bbasketballer75 commented Jul 18, 2026

Copy link
Copy Markdown

Summary

Prevent Honcho's derivation pipeline from turning Hermes assistant narration and tool/status traces into persistent facts about the assistant, while preserving legitimate user-authored assertions.

Behavior

  • sync_turn() writes sanitized user content only; identity/config seeding remains on its separate path.
  • _flush_session() filters legacy queued assistant entries and marks them synchronized so repeated flushes cannot loop on them.
  • User text is filtered only when it is an explicit Markdown blockquote, quoted Hermes report, or Assistant:/Hermes: transcript line.
  • Ordinary statements such as Hermes is useful, Hermes has memory, and bare third-person reports remain intact.
  • Honcho cache signatures include file content, so same-size/same-timestamp config rewrites invalidate cached agents.
  • OAuth consent paths render with portable / separators and do not expose absolute paths.

Policy

This intentionally changes automatic Honcho ingestion to user-only conversation content. Assistant identity seeds and explicit conclusions remain available through their dedicated APIs. The purpose is to remove a recursive self-narration write path, not to disable Honcho's AI peer identity.

Verification

Tested candidate base: 2ebeede00

416 Honcho/startup tests passed, 22 skipped
focused post-review session regression: 145 passed
ruff: passed across the behavioral Python files
compileall: passed
git diff --check: passed

Regression coverage includes mixed and assistant-only queues, repeated flushes, quote-vs-assertion boundaries, leaked memory-context removal, same-mtime config rewrites, profile path isolation, and OAuth path display on Windows.

Copilot AI review requested due to automatic review settings July 18, 2026 08:51
@bbasketballer75

Copy link
Copy Markdown
Author

@alt-glitch ready for review.

This is the source-side fix to PR #66754 (imperative-shape filter) and PR #66810 (self-narration demote). Two changes:

  • plugins/memory/honcho/__init__.py: sync_turn() already-skips assistant content (was committed as local bff9bc635, not in upstream PR yet)
  • plugins/memory/honcho/session.py: _flush_session() now filters out assistant messages before add_messages() — this is the path that drains queued messages via manager.flush_all() (session-end hook) and the async_writer_loop background thread. Without this filter, the in-memory queue drained 96 polluted observations on the last gateway restart before the patch took effect.

Live verified: 60 seconds after gateway bounce with both patches loaded, zero new hermes-observer documents hit Honcho. Old pollution (676 docs total) cleaned up via postgres direct DELETE. Cumulatively solves the self-trust-loop source. Companion to renderer fix PR #66810.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR prevents Honcho’s memory deriver from ingesting Hermes assistant output by stopping assistant-role messages from being written to Honcho at the two write paths used by the honcho memory plugin. This directly targets the source of the “hermes said X” self-narration observations that contributed to the self-trust-loop pollution described in the PR.

Changes:

  • Update HonchoMemoryProvider.sync_turn() to only enqueue/sync user messages (assistant content is intentionally not written).
  • Update HonchoSessionManager._flush_session() to filter out assistant-role messages before building the add_messages() payload.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
plugins/memory/honcho/init.py Stops writing assistant content during per-turn sync; updates docstring rationale.
plugins/memory/honcho/session.py Filters assistant-role messages during session flush to prevent queued assistant content from being written on flush/daemon drain.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugins/memory/honcho/session.py
Comment thread plugins/memory/honcho/__init__.py Outdated
@alt-glitch alt-glitch added type/bug Something isn't working comp/plugins Plugin system and bundled plugins tool/memory Memory tool and memory providers P3 Low — cosmetic, nice to have needs-decision Awaiting maintainer decision before any implementation sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 18, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #48096 and #66810: this is a source-side write-path change (including queued flushes), whereas those use default-observation and read-side mitigations. A maintainer should choose the intended long-term policy.

@bbasketballer75 bbasketballer75 changed the title fix(honcho-memory): skip assistant messages in sync_turn and _flush_session fix(honcho-memory): stop writing assistant content and strip agent-self-quotes Jul 18, 2026

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for tracing both current assistant write paths. The premise is real on current main: plugins/memory/honcho/__init__.py:1351-1353 queues assistant content, and plugins/memory/honcho/session.py:440-448 sends it through add_messages().

Problems

  • plugins/memory/honcho/session.py:441 excludes assistant entries but never marks or removes them. The later _synced update only covers the filtered list (:452-453), so an assistant-only legacy queue remains unsynced across every later flush.
  • _strip_agent_self_quotes() matches generic unquoted user statements such as Hermes is ... and Hermes has ... (plugins/memory/honcho/__init__.py:41-60), then deletes them from every user message at :1416.
  • Suppressing all assistant history changes documented behavior: plugins/memory/honcho/cli.py:1632-1635 says AI representation incorporates subsequent assistant messages. The existing maintainer comment correctly identifies this as a long-term policy choice.

Suggested changes

  • Explicitly discard/mark filtered legacy assistant entries and test repeated flushes.
  • Scope any user-text mitigation to a verified quote form rather than deleting ordinary user assertions.
  • Add tests in the existing Honcho suites and settle the assistant-history policy before salvage.

Automated hermes-sweeper review.

Comment thread plugins/memory/honcho/session.py Outdated
Comment thread plugins/memory/honcho/__init__.py
@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform area/memory Memory subsystem: store, providers, sync, background reviews labels Jul 18, 2026
@bbasketballer75

Copy link
Copy Markdown
Author

Updated in commit 06e92afa to explicitly set _synced = True on skipped assistant messages during _flush_session(), properly evicting them from the unsynced queue.

@bbasketballer75
bbasketballer75 force-pushed the fix/honcho-skip-assistant-source branch from f06e92a to b51bc28 Compare July 23, 2026 04:21
@bbasketballer75 bbasketballer75 changed the title fix(honcho-memory): stop writing assistant content and strip agent-self-quotes fix(honcho-memory): stop assistant self-narration ingestion Jul 23, 2026
@bbasketballer75
bbasketballer75 force-pushed the fix/honcho-skip-assistant-source branch from 939ac50 to 43a1a32 Compare July 29, 2026 05:00
@bbasketballer75

Copy link
Copy Markdown
Author

Comment for #66831

@alt-glitch — re-review requested. This is the source-side write-path fix for assistant self-narration landing in Honcho.

Important update since the previous look: I just rebased onto current origin/main (95d3031). The 6 commits are now cleanly on top of current upstream:

  • 492d411f4 — skip assistant messages in sync_turn()
  • c1eea3c73 — also skip in _flush_session() queued entries
  • 6249e9377 — strip agent-self-quote phrases from user content
  • 9cd871367 — mark assistant messages as _synced=True during flush (proper eviction, not just filter)
  • f02972dbe — narrow quote filtering and harden flushes
  • 43a1a32c4 — docs pointer to identity seed API

Last commit (f06e92afa in the previous SHA chain, now 9cd871367) properly evicts skipped assistant messages from the unsynced queue so they don't loop on every flush. Rebase resolved one conflict in gateway/run.py (upstream faulthandler import vs this PR's hashlib import for content-digest memoization — kept both).

PR is now MERGEABLE. Distinct from the read-side mitigations in #66754 and #66810 — this is the write-path fix. Thanks.

@bbasketballer75

Copy link
Copy Markdown
Author

Rebased onto current origin/main (c3ffe27) — clean rebase, no conflicts.

The base I cited in the previous re-review request (95d303138) is now 221 commits behind. All 6 commits on this branch apply cleanly onto the current head; the source-side write-path fix (_synced = True on skipped assistant messages during _flush_session()) is preserved verbatim. No behavioral change in this push — pure rebase.

Re-review request to @alt-glitch still stands.

bbasketballer75 added a commit to bbasketballer75/hermes-agent that referenced this pull request Jul 31, 2026
…endering

Replaces the simpler imperative-shape and self-narration-prefix filters with a
unified sanitization pass that runs against all four Honcho render surfaces:
User Representation, User Peer Card, AI Self-Representation, AI Identity Card.

Four filtering passes (in order):

1. **Imperative-shape filter** (e.g. `INSTRUCTION:`, `RULE:`, `COMMAND:`,
   `DIRECTIVE:`, `PROMPT-INJECTION:`) — prompt-injection vectors. Pulled into
   an `[untrusted injection filtered from <section>]` block at the end of
   the section so the model can see what was filtered but does not silently
   act on it as a user-stated instruction.

2. **Self-narration prefix filter** (e.g. `hermes says X`, `hermes said Y`,
   `[AUTO-NARRATED] ...`, `[DEBUG-LOG] ...`, `[SELF-TRACE] ...`) — the AI
   Self-Representation can accumulate hundreds of these from prior debugging
   sessions; once surfaced they re-assert themselves as present-tense facts
   in every turn. Demoted to a `[historical, demoted from <section>]` block.

3. **Self-narration phrase filter** — user-peer observations that *quote*
   prior self-narration phrasing (e.g. `austin said Hermes said 'Vee'`,
   `austin shared that hermes says X`) survive the prefix filter because
   they don't start with the trigger. Match the whole-word phrase
   `hermes says` / `hermes said` anywhere in the line, case-insensitive.
   Same demotion as pass 2.

4. **Line cap** — if the kept section exceeds `_MAX_LINES_PER_SECTION` (60)
   lines, the overflow is demoted to a `[historical, truncated]` block.
   Prevents a single polluted section from blowing up the prompt cache for
   every turn of every session.

This change supersedes NousResearch#66754 (single-pass imperative filter) and NousResearch#66810
(imperative + self-narration prefix only) by combining the same intent with
the broader phrase and line-cap passes. Closing those two PRs in favor of
this one for a single review surface.

The source-side `_strip_agent_self_quotes` change in NousResearch#66831 (separate
write-path fix) remains open — different concern, different layer.
bbasketballer75 added a commit to bbasketballer75/hermes-agent that referenced this pull request Jul 31, 2026
Two review findings, both confirmed real by direct inspection:

1. The line cap didn't actually cap anything -- overflow past
   _MAX_LINES_PER_SECTION was relabeled '[historical, truncated]' and
   re-appended to the rendered output in full, so total output size was
   never actually bounded. Now dropped, with only a bare count surviving.

2. The imperative-shape (prompt-injection) filter labeled untrusted
   payloads as 'filtered' but still concatenated them into the model's
   context verbatim -- a warning label around injected text is demotion,
   not removal, and the model reads the attempt either way. Now dropped,
   with only a bare count surviving. filtered_historical (self-narration,
   not a security boundary) is unaffected -- that content is intentionally
   kept, just clearly labeled as non-authoritative.

Also removed a scope-creep write-path change this PR had bundled in:
sync_turn() stopped writing assistant messages to Honcho entirely, which
is a real architectural policy decision that's already the stated purpose
of open PR NousResearch#66831 (both teknium1 and Copilot flagged the duplication
independently). Reverted to restore the original assistant-write path;
that policy question belongs in NousResearch#66831, not silently bundled into a
rendering-sanitizer fix. Also dropped an orphaned comment describing a
self-quote-stripping feature that was never actually implemented in this
version of the code (the real implementation lives in NousResearch#66831).

Found and fixed one more bug while adding test coverage: half of
_SELF_NARRATION_PREFIXES ('HERMES SAYS:', '[DEBUG-LOG] ', etc.) could
never match -- the comparison lowercases the input line but compared it
against the prefix tuple's original mixed case, so only the two
already-lowercase entries in the tuple were ever reachable. Normalized
the comparison to be case-insensitive on both sides.

Added tests/plugins/memory/test_honcho_sanitize_card_lines.py (16 tests,
0 existed before this) covering all 4 passes directly, including the
61-line-cap regression case the review explicitly asked for and the
phrase-anywhere matching (plus its false-positive guard) that had zero
coverage.
Assistant output is dominated by self-narration, status reports, and
tool-call traces. The Honcho deriver's extraction prompt reads
assistant output as facts about the hermes peer, which inflates the AI
Self-Representation with debug breadcrumbs and re-asserting "hermes
said X" lines on every turn — the exact pattern that fed the
2026-07-18 self-trust loop and that PR NousResearch#66770's renderer only partially
mitigates. Source-side fix is the right layer.

User messages still go in (legitimate). AI identity / config / system
seeds go through seed_ai_identity in the same module and are unaffected.

This is the Hermes-side half of a two-part fix:
- Honcho deriver prompt (exclusions) — addresses new pollution at extract time
- This patch — stops new pollution at write time

Both needed because:
1. Prompt exclusions only catch lines that match; some debug-style content
   slips through.
2. Stopping the write at source is structurally simpler and prevents
   the deriver from spending compute on assistant content at all.

Refs PR NousResearch#66770 (renderer, defense-in-depth).
The sync_turn patch (commit bff9bc635 in this repo) only blocks assistant
content from being added to the session object via the runtime chat write
path. The _flush_session path that drains queued messages to Honcho is
called independently from:

  - on_session_end hook (which calls manager.flush_all() -> _flush_session)
  - the async_writer_loop background daemon thread
  - direct flush_all() invocations from tools/ call sites

Without filtering on the flush side, any assistant messages added to the
session BEFORE the sync_turn patch took effect would still drain to Honcho
during a gateway restart or session-end, then deriver would extract them
as third-person facts about the hermes peer (hermes said X / hermes
reported Y), reproducing the AI Self-Representation pollution that
PR NousResearch#66770's renderer only partially mitigates on read.

The 96 new pollution documents observed after the gateway restart on
2026-07-18 08:42 were from exactly this path: in-memory queue draining.

Fix: filter m.get('role') == 'assistant' inside _flush_session's
new_messages list comprehension, mirroring sync_turn's stance. User
messages and the rare legitimate assistant_message (e.g., identity
seeds via seed_ai_identity path which doesn't go through session._flush_session)
are unaffected. The seed_ai_identity path was already separate and not
in scope here.
User messages that quote prior tool output (e.g. 'hermes verified that...'
or 'hermes reported that...') were being passed through to the Honcho
deriver, which then extracted those quoted phrases as Explicit Observations
on the 'hermes' observer peer. Each chat turn added a new
'hermes said/reported/verified/...' observation, feeding the
self-trust loop.

The new _strip_agent_self_quotes function runs over user_content
inside sync_turn() (after sanitize_context), before the content is
written to Honcho. It matches 'hermes <verb> ...' phrases and
replaces each match with a NUL character placeholder so the user's
surrounding prose is preserved but the substring cannot be parsed as
a meaningful sentence by the deriver's extraction prompt.

Patterns stripped:
  - 'hermes <said|reported|confirmed|identified|provided|outlined|
     created|saved|noted|asked|required|wants|received|believes|
     described|added|changed|verifies|verified|wanted|completed|
     commits|requires|has|is|was|continues|sent|started> ... [ending in
     . ! ? \n or end-of-string]'
  - '6631182039 has a long-term memory note stating that ...'
  - 'hermes verifies/describes ...'

Verified with 16 test cases (10 pollution patterns stripped, 0 false
positives on non-pollution text). Module loads cleanly, syntax checks
clean. Live install: 60s after gateway restart with this patch
loaded, zero new hermes-observer documents were generated.

Refs: PR NousResearch#66754 (peer-card sanitizer), PR NousResearch#66810 (self-narration
demote), Honcho NousResearch#911 (observation-cleanup API), Honcho NousResearch#913 (asyncio
loop frozen - separate from this fix).
@bbasketballer75
bbasketballer75 force-pushed the fix/honcho-skip-assistant-source branch from 26be758 to 8988060 Compare July 31, 2026 03:48
@bbasketballer75

Copy link
Copy Markdown
Author

Rebased onto current origin/main (2 conflicts, both mechanical — unrelated upstream edits landing next to this branch's changes, resolved by taking this branch's content, verified via compile + collect-only + the full 137-test run for every touched file before pushing).

Not touching the actual open question here: whether Honcho should suppress ALL assistant-authored history from ingestion, which both you and alt-glitch flagged needs an explicit maintainer policy call (it contradicts documented behavior in plugins/memory/honcho/cli.py that AI representation incorporates subsequent assistant messages, versus the alternative default-observation-toggle approach in #48096). The two concrete code defects from the earlier review round (queue eviction, over-broad regex) were already fixed and test-covered before I touched this — this rebase doesn't change that. Purely mechanical, ready for that policy decision whenever a maintainer can make the call.

Step 4 of the setup walkthrough told users the AI representation is built
"from every subsequent assistant message (observe_me=True)". This PR stops
ingesting assistant messages, so that sentence became actively misleading —
it described the exact behavior being removed.

Reword to state what the representation is now built from (the seeded
identity files) and why assistant replies are excluded.
This PR is about the honcho self-narration write path, but had picked up
four files from two unrelated fixes, inflating the review surface and
coupling their fate to a policy question that is still open here.

Moved out, unchanged, to independently mergeable branches:
  - gateway/run.py + tests/gateway/test_agent_cache.py
      -> fix/honcho-cache-busting-memo-key (content-keyed memo)
  - plugins/memory/honcho/oauth_flow.py + tests/honcho_plugin/test_client.py
      -> fix/honcho-config-path-resolution (Windows path display)
@bbasketballer75

Copy link
Copy Markdown
Author

Two updates, both from a fresh pass over the review feedback.

1. Unbundled the unrelated changes (4db501ee9). This PR was carrying four files from two unrelated fixes, which inflated the review surface and tied their fate to the policy question still open here. Moved out unchanged, each rebased onto current main and independently mergeable:

This PR is now 4 files / +147−9, all honcho self-narration.

2. Fixed the one documentation claim that this PR falsified (a21ff5f2e). @teknium1 was right that plugins/memory/honcho/cli.py told users the AI representation is built "from every subsequent assistant message (observe_me=True)" — precisely the behavior this PR removes. Reworded to describe what the representation is now built from and why assistant replies are excluded.

For the record, I re-verified the other review findings against the current head rather than assuming: the unsynced-assistant-queue-entry and over-broad-self-quote-regex defects are genuinely fixed and covered by regression tests. The remaining blocker is the needs-decision policy call on assistant-history suppression, which is yours to make — the two split PRs above can land regardless.

🤖 Prepared by Claude Code

@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Two PRs address the self-narration problem at different layers: #66810 sanitizes Honcho-rendered context, while #66831 prevents assistant output from entering Honcho and filters explicit copies of prior Hermes output from user messages.

Related pull requests

  • fix(honcho-memory): demote self-narration lines from AI Self-Representation #66810 [closed] related — (+319/-4) — n/a: Adds four-pass read-side sanitization and tests, but the diff retains demoted and overflow lines verbatim in the same rendered context and keeps the earliest 60 lines. It remains relevant as a read-side reference, but despite the contributor keep_open review, it was closed as superseded by fix(honcho): 4-pass sanitize for peer-card + AI Self-Representation rendering #74202 after that review identified the missing trust boundary and ineffective cap.
  • fix(honcho-memory): stop assistant self-narration ingestion #66831 related — (+147/-9) — n/a: Implements the source-side change by omitting assistant messages from sync and flush paths, marking filtered queued assistant entries synchronized, narrowly replacing explicit quoted/transcript copies, preserving bare user assertions, and adding regression tests. The contributor keep_open review found queue-retention, overbroad filtering, and documented-policy issues; the visible diff addresses the first two and updates the documentation, while the long-term policy choice to stop assistant ingestion still requires maintainer acceptance.

Suggested consolidation

Keep #66831 open with a salvage path: preserve its source-side assistant suppression, synchronized queue eviction, narrow quote filtering, and regression tests while requesting an explicit maintainer decision on the documented Honcho ingestion policy. Leave #66810 closed as superseded by #74202 rather than reopening it; #66810 and #66831 are complementary read-side and write-side approaches, not duplicates.

Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 28 kB of PR diffs, 5 kB of issue/PR text, 11 kB of discussion (24 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/memory Memory subsystem: store, providers, sync, background reviews comp/plugins Plugin system and bundled plugins needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state 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.

5 participants