-
-
Notifications
You must be signed in to change notification settings - Fork 69.6k
Sub-agent announce flow does not suppress NO_REPLY — leaks 'NO' + '✅ Done.' to channel #27531
Description
Bug Description
When a sub-agent replies NO_REPLY, the announce flow in subagent-announce.ts does not suppress it. This causes garbage messages like "NO" and "✅ Done." to leak into Slack channels.
Root Cause
In src/agents/subagent-announce.ts line ~1207, only isAnnounceSkip() is checked (which matches "ANNOUNCE_SKIP"). The SILENT_REPLY_TOKEN ("NO_REPLY") is not checked:
// line ~1207
if (isAnnounceSkip(reply)) { // only matches "ANNOUNCE_SKIP"
return true;
}
// NO_REPLY falls through hereThen buildCompletionDeliveryMessage() treats "NO_REPLY" as valid findings text (hasFindings = true because it is not empty and not "(no output)"), producing:
✅ Subagent xxx finished
NO_REPLY
This is sent via the gateway send method (direct path for expectsCompletionMessage=true), which calls deliverOutboundPayloads without any isSilentReplyText filtering.
When the direct path fails (e.g., device token mismatch), it falls back to the agent method, injecting a [System Message] into the main session. The main agent then generates short garbage replies like "NO" (a streaming truncation of NO_REPLY) and "✅ Done." which get delivered to the channel.
Why Cron Jobs Are Not Affected
The cron delivery dispatch (src/cron/isolated-agent/delivery-dispatch.ts ~line 271) has a separate SILENT_REPLY_TOKEN check before calling runSubagentAnnounceFlow:
if (synthesizedText.toUpperCase() === SILENT_REPLY_TOKEN.toUpperCase()) {
return params.withRunSession({ status: "ok", delivered: true, ... });
}This correctly catches NO_REPLY for cron jobs. Sub-agents lack this guard.
Suggested Fix
Add isSilentReplyText(reply) check alongside isAnnounceSkip(reply) in runSubagentAnnounceFlow:
if (isAnnounceSkip(reply)) {
return true;
}
// Add this:
if (isSilentReplyText(reply, SILENT_REPLY_TOKEN)) {
return true;
}The isSilentReplyText function is already imported in the file (SILENT_REPLY_TOKEN from ../auto-reply/tokens.js).
Steps to Reproduce
- Spawn a sub-agent via
sessions_spawnwith a task that results inNO_REPLY - Observe announce message delivered to the requester channel containing "NO_REPLY" as findings
- If direct delivery fails and falls back to
agentmethod, main agent generates garbage replies ("NO", "✅ Done.")
Environment
- OpenClaw v2026.2.22
- Channel: Slack
- Observed frequently when sub-agents have nothing to report
Screenshots
Messages appearing in Slack thread:
NO
✅ Done.