#12240: fix: suppress heartbeat agent events from webchat broadcast
gateway
stale
Cluster:
Heartbeat Message Filtering
## Summary
- Apply `shouldSuppressHeartbeatBroadcast` check to the agent event broadcast path in `server-chat.ts`
- Chat delta/final messages already filter heartbeat runs, but agent lifecycle/stream events were broadcast unconditionally
- This caused webchat to display the full heartbeat execution trace (system prompt, tool calls, HEARTBEAT_OK) when `showOk` was `false`
## Root Cause
In `server-chat.ts`, the agent event handler at line 364 broadcasts all non-tool agent events without checking the heartbeat suppression flag:
```typescript
// Before (line 364):
} else {
broadcast("agent", agentPayload);
}
```
Meanwhile, `emitChatDelta` (line 250) and `emitChatFinal` (line 281) both gate on `shouldSuppressHeartbeatBroadcast` — the agent event path was simply missed.
## Fix
```typescript
// After:
} else if (!shouldSuppressHeartbeatBroadcast(evt.runId)) {
broadcast("agent", agentPayload);
}
```
This matches the existing pattern used for chat messages and ensures heartbeat agent events (lifecycle phases, tool invocations) are not pushed to webchat clients when `showOk` is disabled.
## Test plan
- [x] `server-chat.agent-events.test.ts` — 5 tests pass
- [x] `server-chat-registry.test.ts` — 10 tests pass
- [x] `heartbeat-runner.returns-default-unset.test.ts` — 23 tests pass
Closes #12186
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
This PR updates `src/gateway/server-chat.ts` to apply the existing heartbeat visibility suppression (`shouldSuppressHeartbeatBroadcast`) to the agent-event broadcast path. Previously, only chat delta/final messages were gated, while non-tool agent lifecycle/stream events were broadcast unconditionally to webchat clients. With this change, heartbeat runs no longer leak their agent event traces to webchat when `showOk` is disabled, aligning agent-event behavior with the already-suppressed chat message path.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk.
- Change is a single-branch conditional that reuses an existing suppression function already applied to chat delta/final broadcasts. No new data shapes or side effects were introduced; it only prevents certain agent events from being broadcast to webchat clients when configured to suppress heartbeat OK traces.
- src/gateway/server-chat.ts
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#11647: fix(webchat): filter HEARTBEAT_OK messages from chat.history response
by liuxiaopai-ai · 2026-02-08
87.4%
#11661: fix: Filter HEARTBEAT_OK from chat.history when showOk is false
by veast · 2026-02-08
87.2%
#12774: fix: webchat heartbeat should respect showAlerts config
by a2093930 · 2026-02-09
86.5%
#11889: fix(chat): filter HEARTBEAT_OK messages in chat.history when showOk...
by bendyclaw · 2026-02-08
85.5%
#11859: fix: filter HEARTBEAT_OK messages from chat.history when showOk is ...
by Zjianru · 2026-02-08
84.0%
#19745: fix(heartbeat): enforce interval check regardless of trigger source
by misterdas · 2026-02-18
79.5%
#12786: fix: drop heartbeat runs that arrive while another run is active
by mcaxtr · 2026-02-09
78.6%
#21014: fix(cron): suppress main-session summary for HEARTBEAT_OK responses
by nickjlamb · 2026-02-19
78.0%
#8598: fix: emit agent events for CLI agents targeting webchat
by dbottme · 2026-02-04
77.7%
#8334: fix(webchat): Filter NO_REPLY messages from chat history
by vishaltandale00 · 2026-02-03
77.6%