Skip to content

Commit 496a5eb

Browse files
committed
fix: dedupe silent reply prompt guidance
1 parent ccfa0c1 commit 496a5eb

24 files changed

Lines changed: 144 additions & 62 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Docs: https://docs.openclaw.ai
2222
- Doctor/gateway services: ignore launchd/systemd companion services that only reference the gateway as a dependency, suppress inactive Linux extra-service warnings, and avoid rewriting a running systemd gateway command/entrypoint during doctor repair. Carries forward #39118. Thanks @therk.
2323
- Daemon/service: only emit hard-coded version-manager paths such as `~/.volta/bin`, `~/.asdf/shims`, `~/.bun/bin`, and fnm/pnpm fallbacks into gateway and node service PATHs when the directories exist, so `openclaw doctor` no longer flags `gateway.path.non-minimal` against a PATH the daemon just wrote. Env-driven roots and stable user-bin dirs remain unconditional. Fixes #71944; carries forward #71964. Thanks @Sanjays2402.
2424
- CLI/startup: disable Node's module compile cache automatically for live source-checkout launchers so in-place `pnpm build` updates are visible to the next `openclaw` CLI invocation. Fixes #73037. Thanks @LouisGameDev.
25+
- Agents/group chat: move `NO_REPLY` mechanics into channel-aware direct/group prompts and suppress the duplicate generic silent-reply section for auto-reply runs, so always-on group agents get one consistent stay-silent instruction. Thanks @vincentkoc.
2526
- Channels/commands: make generated `/dock-*` commands switch the active session reply route through `session.identityLinks` instead of falling through to normal chat. Fixes #69206; carries forward #73033. Thanks @clawbones and @michaelatamuk.
2627
- Providers/Cloudflare AI Gateway: strip assistant prefill turns from Anthropic Messages payloads when thinking is enabled, so Claude requests through Cloudflare AI Gateway no longer fail Anthropic conversation-ending validation. Fixes #72905; carries forward #73005. Thanks @AaronFaby and @sahilsatralkar.
2728
- Gateway/startup: keep primary-model startup prewarm on scoped metadata preparation, let native approval bootstraps retry outside channel startup, and skip the global hook runner when no `gateway_start` hook is registered, so clean post-ready sidecar work stays off the critical path. Refs #72846. Thanks @RayWoo, @livekm0309, and @mrz1836.

docs/channels/groups.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ Replying to a bot message counts as an implicit mention when the channel support
289289
- Surfaces that provide explicit mentions still pass; patterns are a fallback.
290290
- Per-agent override: `agents.list[].groupChat.mentionPatterns` (useful when multiple agents share a group).
291291
- Mention gating is only enforced when mention detection is possible (native mentions or `mentionPatterns` are configured).
292+
- Group chat prompt context carries the resolved silent-reply instruction every turn; workspace files should not duplicate `NO_REPLY` mechanics.
292293
- Groups where silent replies are allowed treat clean empty or reasoning-only model turns as silent, equivalent to `NO_REPLY`. Direct chats still treat empty replies as a failed agent turn.
293294
- Discord defaults live in `channels.discord.guilds."*"` (overridable per guild/channel).
294295
- Group history context is wrapped uniformly across channels and is **pending-only** (messages skipped due to mention gating); use `messages.groupChat.historyLimit` for the global default and `channels.<channel>.historyLimit` (or `channels.<channel>.accounts.*.historyLimit`) for overrides. Set `0` to disable.

docs/concepts/system-prompt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ OpenClaw can render smaller system prompts for sub-agents. The runtime sets a
9696
When `promptMode=minimal`, extra injected prompts are labeled **Subagent
9797
Context** instead of **Group Chat Context**.
9898

99+
For channel auto-reply runs, OpenClaw can omit the generic **Silent Replies**
100+
section when the direct/group chat context already includes the resolved
101+
conversation-specific `NO_REPLY` behavior. This avoids repeating token mechanics
102+
in both the global system prompt and channel context.
103+
99104
## Workspace bootstrap injection
100105

101106
Bootstrap files are trimmed and appended under **Project Context** so the model sees identity and profile context without needing explicit reads:

docs/reference/templates/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ In group chats where you receive every message, be **smart about when to contrib
9494
- Correcting important misinformation
9595
- Summarizing when asked
9696

97-
**Stay silent (HEARTBEAT_OK) when:**
97+
**Stay silent when:**
9898

9999
- It's just casual banter between humans
100100
- Someone already answered the question

src/agents/cli-runner.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ export function buildRunClaudeCliAgentParams(params: RunClaudeCliAgentParams): R
394394
runId: params.runId,
395395
jobId: params.jobId,
396396
extraSystemPrompt: params.extraSystemPrompt,
397+
silentReplyPromptMode: params.silentReplyPromptMode,
397398
extraSystemPromptStatic: params.extraSystemPromptStatic,
398399
ownerNumbers: params.ownerNumbers,
399400
// Legacy `claudeSessionId` callers predate the shared CLI session contract.

src/agents/cli-runner/helpers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { detectRuntimeShell } from "../shell-utils.js";
2727
import { stripSystemPromptCacheBoundary } from "../system-prompt-cache-boundary.js";
2828
import { buildSystemPromptParams } from "../system-prompt-params.js";
2929
import { buildAgentSystemPrompt } from "../system-prompt.js";
30+
import type { SilentReplyPromptMode } from "../system-prompt.types.js";
3031
import { sanitizeImageBlocks } from "../tool-images.js";
3132
import { formatTomlConfigOverride } from "./toml-inline.js";
3233
export { buildCliSupervisorScopeKey, resolveCliNoOutputTimeoutMs } from "./reliability.js";
@@ -69,6 +70,7 @@ export function buildSystemPrompt(params: {
6970
config?: OpenClawConfig;
7071
defaultThinkLevel?: ThinkLevel;
7172
extraSystemPrompt?: string;
73+
silentReplyPromptMode?: SilentReplyPromptMode;
7274
ownerNumbers?: string[];
7375
heartbeatPrompt?: string;
7476
docsPath?: string;
@@ -107,6 +109,7 @@ export function buildSystemPrompt(params: {
107109
workspaceDir: params.workspaceDir,
108110
defaultThinkLevel: params.defaultThinkLevel,
109111
extraSystemPrompt: params.extraSystemPrompt,
112+
silentReplyPromptMode: params.silentReplyPromptMode,
110113
ownerNumbers: params.ownerNumbers,
111114
ownerDisplay: ownerDisplay.ownerDisplay,
112115
ownerDisplaySecret: ownerDisplay.ownerDisplaySecret,

src/agents/cli-runner/prepare.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ export async function prepareCliRunContext(
301301
config: params.config,
302302
defaultThinkLevel: params.thinkLevel,
303303
extraSystemPrompt,
304+
silentReplyPromptMode: params.silentReplyPromptMode,
304305
ownerNumbers: params.ownerNumbers,
305306
heartbeatPrompt,
306307
docsPath: openClawReferences.docsPath ?? undefined,

src/agents/cli-runner/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type { PromptImageOrderEntry } from "../../media/prompt-image-order.js";
99
import type { ResolvedCliBackend } from "../cli-backends.js";
1010
import type { EmbeddedRunTrigger } from "../pi-embedded-runner/run/params.js";
1111
import type { SkillSnapshot } from "../skills.js";
12+
import type { SilentReplyPromptMode } from "../system-prompt.types.js";
1213

1314
export type RunCliAgentParams = {
1415
sessionId: string;
@@ -27,6 +28,7 @@ export type RunCliAgentParams = {
2728
runId: string;
2829
jobId?: string;
2930
extraSystemPrompt?: string;
31+
silentReplyPromptMode?: SilentReplyPromptMode;
3032
/** Static portion of extraSystemPrompt (excluding per-message inbound metadata) for session reuse hashing. */
3133
extraSystemPromptStatic?: string;
3234
streamParams?: import("../command/types.js").AgentStreamParams;

src/agents/pi-embedded-runner/run/attempt.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,7 @@ export async function runEmbeddedAttempt(
11311131
workspaceNotes: workspaceNotes?.length ? workspaceNotes : undefined,
11321132
reactionGuidance,
11331133
promptMode: effectivePromptMode,
1134+
silentReplyPromptMode: params.silentReplyPromptMode,
11341135
acpEnabled: isAcpRuntimeSpawnAvailable({
11351136
config: params.config,
11361137
sandboxed: sandboxInfo?.enabled === true,

src/agents/pi-embedded-runner/run/params.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {
1515
ToolResultFormat,
1616
} from "../../pi-embedded-subscribe.shared-types.js";
1717
import type { SkillSnapshot } from "../../skills.js";
18+
import type { SilentReplyPromptMode } from "../../system-prompt.types.js";
1819
import type { PromptMode } from "../../system-prompt.types.js";
1920
import type { AuthProfileFailurePolicy } from "./auth-profile-failure-policy.types.js";
2021
export type { ClientToolDefinition } from "../../command/shared-types.js";
@@ -142,6 +143,7 @@ export type RunEmbeddedPiAgentParams = {
142143
lane?: string;
143144
enqueue?: CommandQueueEnqueueFn;
144145
extraSystemPrompt?: string;
146+
silentReplyPromptMode?: SilentReplyPromptMode;
145147
internalEvents?: AgentInternalEvent[];
146148
inputProvenance?: InputProvenance;
147149
streamParams?: AgentStreamParams;

0 commit comments

Comments
 (0)