Skip to content

fix(hooks): skip duplicate delivery when hook agent turn uses announce flow#20199

Closed
zerone0x wants to merge 1 commit into
openclaw:mainfrom
zerone0x:fix/hooks-duplicate-delivery-20196
Closed

fix(hooks): skip duplicate delivery when hook agent turn uses announce flow#20199
zerone0x wants to merge 1 commit into
openclaw:mainfrom
zerone0x:fix/hooks-duplicate-delivery-20196

Conversation

@zerone0x

@zerone0x zerone0x commented Feb 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #20196

When a hook is triggered via /hooks/agent with deliver: true, the response was being delivered twice — once through the announce flow and once through the main agent heartbeat.

Changes

  • Check result.delivered before calling enqueueSystemEvent() and requestHeartbeatNow()
  • Skip both when the isolated run already delivered its output to the target channel

This is the same pattern applied to the cron service in ea95e88 (#15692). The RunCronAgentTurnResult.delivered flag already documents this contract:

delivered: true — Callers should skip posting a summary to the main session to avoid duplicate messages.

The hooks handler simply needs to honor this flag.


🤖 Generated with Claude Code

Greptile Summary

Guards the hooks agent handler against duplicate message delivery by checking result.delivered before enqueuing a system event and triggering a heartbeat wake. This mirrors the existing pattern in the cron service timer (src/cron/service/timer.ts:541), where res.delivered is checked to avoid posting a summary to the main session when the isolated run already delivered output via the announce flow.

  • Wraps enqueueSystemEvent() and requestHeartbeatNow() in if (!result.delivered) to skip them when delivery already occurred
  • Error path (catch block) is unchanged and continues to always surface failures — correct behavior
  • No new test coverage for the delivered: true path was added; the existing e2e tests mock the isolated run result without a delivered field, so they continue to exercise the non-delivered path

Confidence Score: 4/5

  • This PR is safe to merge — the change is minimal, follows an established pattern from the cron service, and the error path remains unchanged.
  • Score of 4 reflects a clean, well-scoped fix that mirrors an existing pattern in the codebase (cron timer). The logic is straightforward — guarding on the delivered flag returned by runCronIsolatedAgentTurn. The only gap is the absence of a dedicated test for the delivered: true path in the hooks e2e tests, but the pattern is already tested in the cron service tests.
  • No files require special attention

Last reviewed commit: a51eaaa

Context used:

  • Context from dashboard - CLAUDE.md (source)

…e flow

When a hook agent turn delivers via the announce flow, skip enqueuing a
system event to the main session and waking the heartbeat. This prevents
duplicate messages being delivered to the target channel.

This is the same pattern applied to the cron service in ea95e88 (#15692).

Fixes #20196

Co-Authored-By: Claude <[email protected]>
@vincentkoc

Copy link
Copy Markdown
Member

Thanks for pushing this forward.

I’m closing this as a duplicate of #20678. The same hook-delivery root cause is covered there as part of the combined, merge-ready path.

Your earlier contribution is still part of the attribution trail. If this boundary looks wrong in your repro, tell me and I can reopen review quickly.

@vincentkoc vincentkoc closed this Feb 22, 2026
@vincentkoc vincentkoc added dedupe:child Duplicate issue/PR child in dedupe cluster close:duplicate Closed as duplicate labels Feb 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

close:duplicate Closed as duplicate dedupe:child Duplicate issue/PR child in dedupe cluster gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(hooks): duplicate delivery when hook agent turn uses announce flow

2 participants