mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-06 06:41:08 +00:00
fix(agents): prefer background completion wake over polling (#60877)
* fix(agents): prefer completion wake over polling * fix(changelog): note completion wake guidance * fix(agents): qualify quiet exec completion wake * fix(agents): qualify disabled exec completion wake * fix(agents): split process polling from control actions
This commit is contained in:
@@ -97,6 +97,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Gateway/auth: serialize async shared-secret auth attempts per client so concurrent Tailscale-capable failures cannot overrun the intended auth rate-limit budget. Thanks @Telecaster2147.
|
||||
- Doctor/config: compare normalized `talk` configs by deep structural equality instead of key-order-sensitive serialization so `openclaw doctor --fix` stops repeatedly reporting/applying no-op `talk.provider/providers` normalization. (#59911) Thanks @ejames-dev.
|
||||
- Gateway/device auth: reuse cached device-token scopes only for cached-token reconnects, while keeping explicit `deviceToken` scope requests and empty-cache fallbacks intact so reconnects preserve `operator.read` without breaking explicit auth flows. (#46032) Thanks @caicongyang.
|
||||
- Agents/scheduling: steer background-now work toward automatic completion wake and treat `process` polling as on-demand inspection or intervention instead of default completion handling. (#60877) Thanks @vincentkoc.
|
||||
- Google Gemini CLI auth: improve OAuth credential discovery across Windows nvm and Homebrew libexec installs, and align Code Assist metadata so Gemini login stops failing on packaged CLI layouts. (#40729) Thanks @hughcube.
|
||||
- Mattermost/config schema: accept `groups.*.requireMention` again so existing Mattermost configs no longer fail strict validation after upgrade. (#58271) Thanks @MoerAI.
|
||||
- Agents/failover: scope Anthropic `An unknown error occurred` failover matching by provider so generic internal unknown-error text no longer triggers retryable timeout fallback. (#59325) Thanks @aaron-he-zhu.
|
||||
|
||||
@@ -1119,6 +1119,7 @@ export function describeExecTool(params?: { agentId?: string; hasCronTool?: bool
|
||||
const base = [
|
||||
"Execute shell commands with background continuation for work that starts now.",
|
||||
"Use yieldMs/background to continue later via process tool.",
|
||||
"For long-running work started now, rely on automatic completion wake when it is enabled and the command emits output or fails; otherwise use process to confirm completion. Use process whenever you need logs, status, input, or intervention.",
|
||||
params?.hasCronTool
|
||||
? "Do not use exec sleep or delay loops for reminders or deferred follow-ups; use cron instead."
|
||||
: undefined,
|
||||
|
||||
@@ -120,6 +120,7 @@ function resetPollRetrySuggestion(sessionId: string): void {
|
||||
export function describeProcessTool(params?: { hasCronTool?: boolean }): string {
|
||||
return [
|
||||
"Manage running exec sessions for commands already started: list, poll, log, write, send-keys, submit, paste, kill.",
|
||||
"Use poll/log when you need status, logs, quiet-success confirmation, or completion confirmation when automatic completion wake is unavailable. Use write/send-keys/submit/paste/kill for input or intervention.",
|
||||
params?.hasCronTool
|
||||
? "Do not use process polling to emulate timers or reminders; use cron for scheduled follow-ups."
|
||||
: undefined,
|
||||
|
||||
@@ -415,6 +415,15 @@ describe("tool descriptions", () => {
|
||||
const execWithCron = createTestExecTool({ hasCronTool: true });
|
||||
const processWithCron = createProcessTool({ hasCronTool: true });
|
||||
|
||||
expect(execWithCron.description).toContain(
|
||||
"rely on automatic completion wake when it is enabled and the command emits output or fails; otherwise use process to confirm completion. Use process whenever you need logs, status, input, or intervention.",
|
||||
);
|
||||
expect(processWithCron.description).toContain(
|
||||
"completion confirmation when automatic completion wake is unavailable.",
|
||||
);
|
||||
expect(processWithCron.description).toContain(
|
||||
"Use write/send-keys/submit/paste/kill for input or intervention.",
|
||||
);
|
||||
expect(execWithCron.description).toContain(
|
||||
"Do not use exec sleep or delay loops for reminders or deferred follow-ups; use cron instead.",
|
||||
);
|
||||
@@ -423,6 +432,9 @@ describe("tool descriptions", () => {
|
||||
);
|
||||
expect(execTool.description).not.toContain("use cron instead");
|
||||
expect(processTool.description).not.toContain("scheduled follow-ups");
|
||||
expect(execTool.description).toContain("otherwise use process to confirm completion");
|
||||
expect(processTool.description).toContain("completion confirmation when automatic completion wake is unavailable");
|
||||
expect(processTool.description).toContain("Use write/send-keys/submit/paste/kill for input or intervention.");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -124,6 +124,9 @@ describe("buildAgentSystemPrompt", () => {
|
||||
expect(prompt).toContain(
|
||||
"Use exec/process only for commands that start now and continue running in the background.",
|
||||
);
|
||||
expect(prompt).toContain(
|
||||
"For long-running work that starts now, start it once and rely on automatic completion wake when it is enabled and the command emits output or fails; otherwise use process to confirm completion, and use it for logs, status, input, or intervention.",
|
||||
);
|
||||
expect(prompt).toContain(
|
||||
"Do not emulate scheduling with sleep loops, timeout loops, or repeated polling.",
|
||||
);
|
||||
@@ -295,6 +298,9 @@ describe("buildAgentSystemPrompt", () => {
|
||||
expect(prompt).toContain(
|
||||
"Use exec/process only for commands that start now and continue running in the background.",
|
||||
);
|
||||
expect(prompt).toContain(
|
||||
"For long-running work that starts now, start it once and rely on automatic completion wake when it is enabled and the command emits output or fails; otherwise use process to confirm completion, and use it for logs, status, input, or intervention.",
|
||||
);
|
||||
expect(prompt).toContain("Completion is push-based: it will auto-announce when done.");
|
||||
expect(prompt).toContain("Do not poll `subagents list` / `sessions_list` in a loop");
|
||||
expect(prompt).toContain(
|
||||
|
||||
@@ -244,8 +244,9 @@ export function buildAgentSystemPrompt(params: {
|
||||
const sandboxedRuntime = params.sandboxInfo?.enabled === true;
|
||||
const acpSpawnRuntimeEnabled = acpEnabled && !sandboxedRuntime;
|
||||
const execToolSummary =
|
||||
"Run shell commands (pty available for TTY-required CLIs; use for work that starts now, not delayed follow-ups)";
|
||||
const processToolSummary = "Manage background exec sessions for commands already started";
|
||||
"Run shell commands (pty available for TTY-required CLIs; use for work that starts now, not delayed follow-ups; background completion may wake automatically when enabled)";
|
||||
const processToolSummary =
|
||||
"Manage background exec sessions for commands already started (poll/log for inspection, debugging, input, intervention, or completion confirmation when auto-wake is unavailable)";
|
||||
const cronToolSummary =
|
||||
"Manage cron jobs and wake events (use for reminders, delayed follow-ups, and recurring tasks; for requests like 'check back in 10 minutes' or 'remind me later', use cron instead of exec sleep, yieldMs delays, or process polling; when scheduling a reminder, write the systemEvent text as something that will read like a reminder when it fires, and mention that it is a reminder depending on the time gap between setting and firing; include recent context in reminder text if appropriate)";
|
||||
const coreToolSummaries: Record<string, string> = {
|
||||
@@ -477,10 +478,12 @@ export function buildAgentSystemPrompt(params: {
|
||||
? [
|
||||
`For follow-up at a future time (for example "check back in 10 minutes", reminders, run-later work, or recurring tasks), use cron instead of ${execToolName} sleep, yieldMs delays, or ${processToolName} polling.`,
|
||||
`Use ${execToolName}/${processToolName} only for commands that start now and continue running in the background.`,
|
||||
`For long-running work that starts now, start it once and rely on automatic completion wake when it is enabled and the command emits output or fails; otherwise use ${processToolName} to confirm completion, and use it for logs, status, input, or intervention.`,
|
||||
"Do not emulate scheduling with sleep loops, timeout loops, or repeated polling.",
|
||||
]
|
||||
: [
|
||||
`For long waits, avoid rapid poll loops: use ${execToolName} with enough yieldMs or ${processToolName}(action=poll, timeout=<ms>).`,
|
||||
`For long-running work that starts now, start it once and rely on automatic completion wake when it is enabled and the command emits output or fails; otherwise use ${processToolName} to confirm completion, and use it for logs, status, input, or intervention.`,
|
||||
]),
|
||||
"If a task is more complex or takes longer, spawn a sub-agent. Completion is push-based: it will auto-announce when done.",
|
||||
...(acpHarnessSpawnAllowed
|
||||
|
||||
Reference in New Issue
Block a user