Skip to content

Prevent Hermes progress cleanup from deleting durable tool-call events #1392

Description

@Datawav

Problem

On a newly installed Hermes Marmot connector, tool-call rows can appear during a turn and then become deleted-message tombstones after the final answer arrives. This is confusing in a durable encrypted conversation: the rows look like ordinary conversation history while work is running, then the agent appears to retract many messages at once.

The current integration crosses two different lifecycle models:

  • Hermes 0.19.0 treats progress bubbles as temporary presentation and, when cleanup_progress resolves true, collects their message IDs and calls the platform adapter's delete_message after successful final delivery (setup, post-delivery cleanup).
  • The Marmot adapter converts tool progress into durable kind-1202 agent-operation events (routing, durable send). Its generic delete_message implementation forwards a successful cleanup request to MDK's real message-deletion API (adapter delete).
  • The installer/config helper pins several Marmot-specific display defaults but does not pin cleanup_progress, so a pre-existing global Hermes value can be inherited by the new platform entry (config projection).

The report is a runtime observation. The source audit confirms the incompatible cleanup boundary and inheritance path; the exact message-ID handoff that triggers the observed deletes should be captured by the regression test rather than inferred from the UI.

Expected behavior

A default Hermes Marmot install must not inherit a generic temporary-progress cleanup policy that turns durable kind-1202 operation history into delete events. Tool progress may be disabled, retained as durable operation history, or represented through a genuinely ephemeral presentation path, but it must not unexpectedly become a set of agent-authored tombstones after final delivery.

Explicit user deletion of a Marmot message must continue to use the existing delete API.

Acceptance criteria

  • The Hermes Marmot installer/config helper writes an explicit platform-scoped cleanup_progress: false default, without changing unrelated global or other-platform display settings.
  • Reinstall/upgrade replaces a stale inherited Marmot cleanup default with the safe platform default while preserving an explicit, documented Marmot-specific operator choice if opt-in cleanup remains supported.
  • Kind-1202 agent-operation events are never deleted merely because a turn reached successful final delivery under the default installed configuration.
  • If Marmot supports opt-in progress cleanup, its lifecycle is defined explicitly: identify which returned ID represents the logical progress surface, which durable event IDs may be targeted, and how retries, partial sends, failed turns, gateway restarts, and post-delivery callbacks behave. Do not infer cleanup targets from synthetic marmot-tool-progress:* IDs.
  • Direct, user-requested message deletion remains unchanged and is not conflated with progress cleanup.

Regression coverage

  • Extend integrations/hermes/marmot/tests/test_configure_gateway.py with an existing config that has global display.cleanup_progress: true; after configuration, Marmot resolves to the safe platform value while the global and other-platform values remain unchanged.
  • Add a real Hermes registration/turn-boundary integration test using the pinned hermes-agent.lock runtime: emit multiple tool calls, complete the turn successfully, run post-delivery callbacks, and assert that no DeleteMessage request targets their kind-1202 event IDs under default install settings.
  • Cover failed turns (progress remains available), reinstall/upgrade behavior, an explicit Marmot cleanup opt-in if retained, and a separate direct-delete test proving the ordinary deletion tool still reaches the intended durable message.

Related work

This is a standalone connector bug. No open MDK tracking issue has a completion rule that requires this fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    MEDIUMbugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions