Skip to content

fix(honcho plugin): gateway-restart dedup prevents duplicate messages#17153

Closed
kaishi00 wants to merge 1 commit into
NousResearch:mainfrom
kaishi00:fix/honcho-plugin-gateway-restart-dedup
Closed

fix(honcho plugin): gateway-restart dedup prevents duplicate messages#17153
kaishi00 wants to merge 1 commit into
NousResearch:mainfrom
kaishi00:fix/honcho-plugin-gateway-restart-dedup

Conversation

@kaishi00

Copy link
Copy Markdown

Problem

When the Hermes gateway restarts mid-conversation, the Honcho plugin replays the current turn's messages to Honcho — creating duplicate entries for messages that were already synced before the restart.

Root cause: HonchoSessionManager uses an in-memory _cache (dict) that is lost on restart. After restart:

  1. get_or_create() loads existing Honcho messages → marks them _synced: True
  2. Gateway feeds the same turn data to sync_turn() again
  3. New unsynced copies are created from the same content
  4. _flush_session() sends them all to Honcho → duplicates

Fix

Added content-hash dedup to _flush_session() in plugins/memory/honcho/session.py:

  • Before calling honcho_session.add_messages(), query the last 100 existing Honcho messages
  • Build MD5 hashes of peer_id + content for each
  • Skip any new message whose hash matches an existing one (mark as synced without re-sending)
  • Log skipped count: "Honcho dedup: skipped N duplicate(s) (gateway restart protection)"
  • Best-effort: if context() query fails, send all messages (no data loss risk)

Bonus: Peer name priority swap

Also fixed get_or_create() so config.peerName takes priority over runtime user_id. For single-user setups (private Discord DMs), the configured peer identity should always win over derived Discord numeric IDs.

Changes

File What
plugins/memory/honcho/session.py Dedup logic in _flush_session() + peer priority swap in get_or_create()

Testing

  • Running on production instance with self-hosted Honco (localhost:8000)
  • Gateway restarted multiple times during debugging — zero duplicates after fix
  • Existing sessions continue working; dedup is transparent to callers

Prevents duplicate messages when the Hermes gateway restarts and replays
the current turn to sync_turn(). After restart, the in-memory session cache
is empty and get_or_create() reloads existing Honcho messages as synced,
but the gateway may still feed the same turn data, creating unsynced copies
of messages that Honcho already has.

Fix: before calling add_messages(), query last 100 existing Honcho
messages, build MD5 content hashes (peer_id + content), skip any new
message whose hash matches. Best-effort: if context() query fails,
sends all messages without dedup (no data loss risk).

Also swaps peer_name priority: config.peerName wins over runtime user_id
for single-user setups where configured identity should always be used.
@alt-glitch alt-glitch added P3 Low — cosmetic, nice to have type/bug Something isn't working comp/plugins Plugin system and bundled plugins comp/gateway Gateway runner, session dispatch, delivery labels Apr 28, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #9404 / #9422 — this PR implements the gateway-restart dedup portion of the Honcho session-write dedup feature request. Also related to #8424 (Honcho orphan sessions).

@teknium1

teknium1 commented May 5, 2026

Copy link
Copy Markdown
Contributor

Closing as superseded.

The peer-name priority swap (config.peer_name > runtime user_id) is already available on current main as an opt-in via pinPeerName (PR #14984). That design preserves multi-user Discord/Telegram memory scoping by default while letting single-user deployments opt in. Your PR's unconditional swap would regress the multi-user case and collide with pin_peer_name.

The gateway-restart dedup is an interesting idea but has a few issues worth sorting out before landing:

  • Adds an O(N) Honcho context() query on every _flush_session — meaningful latency on every turn
  • MD5 of peer_id:content without timestamp/turn scoping can drop legitimate repeated messages (e.g. user says "yes" twice)
  • The genuine bug (cache-reload-as-synced after restart) is better fixed on the read side (track a persistence watermark) than on the write side (dedup every flush)

Happy to revisit the dedup approach separately if you have evidence the duplicate-message issue is still happening on current main with pinPeerName.

@teknium1 teknium1 closed this May 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants