Gateway auto-resume on a non-interactive platform (webhook) acknowledges restoration instead of completing the interrupted turn
Version
Hermes v2026.7.1 (0.18.0). Code path present unchanged at least since 0.13.0's session-resume feature.
Summary
When the gateway is interrupted mid-turn (SIGTERM drain / restart) and marks a session resume_pending, the next boot re-runs the session via _schedule_resume_pending_sessions(), which synthesizes an empty-text internal MessageEvent. The resume [System note] then tells the model to "report to the user that the session was restored successfully and ask what they would like to do next" and to "skip any unfinished work from the conversation history."
That guidance is correct for an interactive platform (CLI/Telegram/Slack DM), where a human is waiting and can answer "what next?". It is wrong for a non-interactive platform such as webhook, where there is no responder: the resumed turn emits a short "session restored" acknowledgement that goes nowhere, and — because it is told to skip unfinished work — it abandons the interrupted task instead of finishing it.
Where
gateway/run.py, the _is_resume_pending branch (~L17517-17549 in v2026.7.1):
if message:
_resume_guidance = "Address the user's NEW message below FIRST ..."
else:
_resume_guidance = (
"Report to the user that the session was restored "
"successfully and ask what they would like to do next."
)
message = (
f"[System note: The previous turn was interrupted by {_reason_phrase}; "
f"the gateway is now back online. Any restart/shutdown command in the "
f"history has already run — do NOT re-execute or verify it. {_resume_guidance} "
f"Do NOT re-execute old tool calls — skip any unfinished work from the "
f"conversation history.]"
+ (f"\n\n{message}" if message else "")
)
Reproduce
- Run the gateway with a
webhook platform adapter connected.
- Send a webhook event that kicks off a long-running agent task (multiple tool turns).
- While it is mid-task, send SIGTERM (drain) so the session is marked
resume_pending, then let the process exit and restart.
- On boot,
_schedule_resume_pending_sessions() re-runs the session.
Observed: the resumed turn is 1 API call producing a short "session restored" text response (finish_reason=stop, no tool calls); the interrupted task is not completed and no downstream output is produced.
Expected: on a non-interactive platform, the resumed turn should continue and complete the interrupted task (re-run the remaining tool work), not emit an interactive "restored" acknowledgement.
Suggested fix
Make the empty-message resume guidance platform-aware. For interactive platforms keep the current "report restored / ask what next" behaviour. For non-interactive platforms (webhook, and any adapter without a live responder), instruct the model to continue and complete the interrupted turn, and drop the "skip any unfinished work" clause for that case (keep the "a restart/shutdown command already ran, don't re-run it" caveat). Idempotency of the completed work is the integration's responsibility (dedup on the downstream write).
Impact
Session-resume marks + re-schedules correctly, but for webhook integrations the interrupted work is silently dropped on resume — the operator must re-trigger manually. This defeats the practical value of resume_pending for automated (non-interactive) gateway workloads.
Related
Environment note
Observed on a webhook-only gateway deployment (single-pod, EKS). Session marking + boot re-scheduling work correctly (fresh Scheduled auto-resume for N session(s) on boot); only the resumed turn's behaviour is wrong for the non-interactive case.
Gateway auto-resume on a non-interactive platform (webhook) acknowledges restoration instead of completing the interrupted turn
Version
Hermes v2026.7.1 (0.18.0). Code path present unchanged at least since 0.13.0's session-resume feature.
Summary
When the gateway is interrupted mid-turn (SIGTERM drain / restart) and marks a session
resume_pending, the next boot re-runs the session via_schedule_resume_pending_sessions(), which synthesizes an empty-text internalMessageEvent. The resume[System note]then tells the model to "report to the user that the session was restored successfully and ask what they would like to do next" and to "skip any unfinished work from the conversation history."That guidance is correct for an interactive platform (CLI/Telegram/Slack DM), where a human is waiting and can answer "what next?". It is wrong for a non-interactive platform such as
webhook, where there is no responder: the resumed turn emits a short "session restored" acknowledgement that goes nowhere, and — because it is told to skip unfinished work — it abandons the interrupted task instead of finishing it.Where
gateway/run.py, the_is_resume_pendingbranch (~L17517-17549 in v2026.7.1):Reproduce
webhookplatform adapter connected.resume_pending, then let the process exit and restart._schedule_resume_pending_sessions()re-runs the session.Observed: the resumed turn is 1 API call producing a short "session restored" text response (
finish_reason=stop, no tool calls); the interrupted task is not completed and no downstream output is produced.Expected: on a non-interactive platform, the resumed turn should continue and complete the interrupted task (re-run the remaining tool work), not emit an interactive "restored" acknowledgement.
Suggested fix
Make the empty-message resume guidance platform-aware. For interactive platforms keep the current "report restored / ask what next" behaviour. For non-interactive platforms (webhook, and any adapter without a live responder), instruct the model to continue and complete the interrupted turn, and drop the "skip any unfinished work" clause for that case (keep the "a restart/shutdown command already ran, don't re-run it" caveat). Idempotency of the completed work is the integration's responsibility (dedup on the downstream write).
Impact
Session-resume marks + re-schedules correctly, but for webhook integrations the interrupted work is silently dropped on resume — the operator must re-trigger manually. This defeats the practical value of
resume_pendingfor automated (non-interactive) gateway workloads.Related
resume_pendingmarker this builds on. That fix makes the session recoverable; this issue is the next layer: the recovered non-interactive session doesn't complete the interrupted work._resume_guidanceempty-message branch is interactive-only, so non-interactive (webhook) resumes acknowledge restoration and skip the work.Environment note
Observed on a webhook-only gateway deployment (single-pod, EKS). Session marking + boot re-scheduling work correctly (fresh
Scheduled auto-resume for N session(s)on boot); only the resumed turn's behaviour is wrong for the non-interactive case.