openclaw - ✅(Solved) Fix Bug: /new reset can be queued behind active run when queue mode is steer [1 pull requests, 4 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#74093Fetched 2026-04-30 06:28:35
View on GitHub
Comments
4
Participants
2
Timeline
8
Reactions
0
Author
Timeline (top)
commented ×4cross-referenced ×3referenced ×1

When messages.queue.mode is steer, a reset command such as /new (via Feishu DM) appears to go through the normal active-run queue/steer path instead of interrupting the current run. The result is that the reset is acknowledged by ingress immediately, but the new session/reply can be delayed until the active/queued work clears.

Error Message

A Feishu DM /new was received and dispatched promptly:

Root Cause

When messages.queue.mode is steer, a reset command such as /new (via Feishu DM) appears to go through the normal active-run queue/steer path instead of interrupting the current run. The result is that the reset is acknowledged by ingress immediately, but the new session/reply can be delayed until the active/queued work clears.

Fix Action

Fix / Workaround

A Feishu DM /new was received and dispatched promptly:

12:54:15 feishu[default]: DM ...: /new
12:54:15 feishu[default]: dispatching to agent (...)
12:55:02 session-memory saved old session summary
13:04:12 new session started
13:04:35 model completed
13:04:43 feishu[default]: dispatch complete (queuedFinal=true, replies=1)

A local hotfix that made reset-triggered turns use interrupt semantics and disabled steer/followup for that turn fixed the behavior locally:

PR fix notes

PR #74144: fix(queue): reset turns bypass steer/followup queue when active run exists

Description (problem / solution / changelog)

Summary

  • Fix /new and /reset commands being delayed behind active runs when messages.queue.mode is steer, followup, collect, or steer-backlog.
  • Reset-triggered turns now use interrupt semantics: queue is cleared, active run is aborted, and the new session starts immediately.
  • Add 5 new test cases covering reset + queue mode interactions.

Closes #74093

Problem

When messages.queue.mode is steer, issuing /new or /reset during an active run would enqueue the reset command as a normal followup message. The reset would only execute after the active run completed — delays of 10+ minutes were reported. This defeated the purpose of reset commands, which should interrupt and start fresh immediately.

Root cause: resolveActiveRunQueueAction() had no awareness of resetTriggered. When queueMode === "steer" and there was an active run, it always returned "enqueue-followup", regardless of whether the turn was a reset.

Fix

Three coordinated changes:

1. src/auto-reply/reply/queue-policy.ts — Add resetTriggered to queue policy

Added optional resetTriggered parameter to resolveActiveRunQueueAction. When true and there's an active run, returns "run-now" before the steer/followup check (heartbeat drop still takes priority).

2. src/auto-reply/reply/get-reply-run.ts — Three changes:

  • Suppress steer/followup for reset turns: shouldSteer and shouldFollowup are now false when effectiveResetTriggered is true, preventing the steer path from absorbing the reset into the active run's context.
  • Extend interrupt block: The lane-clear + active-run-abort block (previously only for queue.mode === "interrupt") now also fires for reset-triggered turns, ensuring the active run is properly cleaned up.
  • Pass resetTriggered to resolveActiveRunQueueAction.

3. src/auto-reply/reply/agent-runner.ts — Pass resetTriggered to queue policy

The second call site for resolveActiveRunQueueAction now also receives resetTriggered.

Test plan

  • pnpm test src/auto-reply/reply/queue-policy.test.ts — 9 tests (4 existing + 5 new), all pass
  • New test cases:
    • Reset-triggered in steer mode → "run-now" (not "enqueue-followup")
    • Reset-triggered in followup/collect mode → "run-now"
    • Reset-triggered in steer-backlog mode → "run-now"
    • Heartbeat still dropped even with resetTriggered
    • Non-active runs unaffected by resetTriggered

Notes

  • The fix matches the reporter's validated local hotfix approach
  • isReplySkip-style ping-pong flows are unaffected since they don't set resetTriggered
  • Backward compatible: resetTriggered is optional and defaults to undefined (falsy)

Changed files

  • src/auto-reply/reply/agent-runner.ts (modified, +1/-0)
  • src/auto-reply/reply/get-reply-run.ts (modified, +11/-5)
  • src/auto-reply/reply/queue-policy.test.ts (modified, +60/-0)
  • src/auto-reply/reply/queue-policy.ts (modified, +6/-0)

Code Example

12:54:15 feishu[default]: DM ...: /new
12:54:15 feishu[default]: dispatching to agent (...)
12:55:02 session-memory saved old session summary
13:04:12 new session started
13:04:35 model completed
13:04:43 feishu[default]: dispatch complete (queuedFinal=true, replies=1)

---

const shouldSteer = resolvedQueue.mode === steer || resolvedQueue.mode === steer-backlog;
const shouldFollowup = resolvedQueue.mode === followup || resolvedQueue.mode === collect || resolvedQueue.mode === steer-backlog;
const activeRunQueueAction = resolveActiveRunQueueAction({
  isActive,
  isHeartbeat: opts?.isHeartbeat === true,
  shouldFollowup,
  queueMode: resolvedQueue.mode
});

---

const queueModeForActiveRun = effectiveResetTriggered ? interrupt : resolvedQueue.mode;
const shouldSteer = !effectiveResetTriggered && (resolvedQueue.mode === steer || resolvedQueue.mode === steer-backlog);
const shouldFollowup = !effectiveResetTriggered && (resolvedQueue.mode === followup || resolvedQueue.mode === collect || resolvedQueue.mode === steer-backlog);
RAW_BUFFERClick to expand / collapse

Summary

When messages.queue.mode is steer, a reset command such as /new (via Feishu DM) appears to go through the normal active-run queue/steer path instead of interrupting the current run. The result is that the reset is acknowledged by ingress immediately, but the new session/reply can be delayed until the active/queued work clears.

Environment

  • OpenClaw: 2026.4.26
  • OS: Windows 10
  • Channel: Feishu built-in channel, connectionMode: websocket
  • Queue config: messages.queue.mode: steer
  • Model: kimi/kimi-for-coding

Observed behavior

A Feishu DM /new was received and dispatched promptly:

12:54:15 feishu[default]: DM ...: /new
12:54:15 feishu[default]: dispatching to agent (...)
12:55:02 session-memory saved old session summary
13:04:12 new session started
13:04:35 model completed
13:04:43 feishu[default]: dispatch complete (queuedFinal=true, replies=1)

So the Feishu websocket ingress was alive, but the reset turn did not produce a prompt new-session reply until roughly 10 minutes later. There was also a Feishu openclaw_bot/ping timeout during the wait, but the core issue seems to be that /new can be delayed behind active work under steer queue mode.

Expected behavior

Reset-triggered turns (/new, /reset, or command reset hooks) should interrupt/clear the active run and start the fresh session immediately. They should not be treated as normal steer/followup messages that can wait behind the current run.

Suspected cause

In runPreparedReply (dist/get-reply-eY9NJdyX.js in the published 2026.4.26 package), the active-run queue behavior is derived from resolvedQueue.mode even when effectiveResetTriggered is true:

const shouldSteer = resolvedQueue.mode === steer || resolvedQueue.mode === steer-backlog;
const shouldFollowup = resolvedQueue.mode === followup || resolvedQueue.mode === collect || resolvedQueue.mode === steer-backlog;
const activeRunQueueAction = resolveActiveRunQueueAction({
  isActive,
  isHeartbeat: opts?.isHeartbeat === true,
  shouldFollowup,
  queueMode: resolvedQueue.mode
});

A local hotfix that made reset-triggered turns use interrupt semantics and disabled steer/followup for that turn fixed the behavior locally:

const queueModeForActiveRun = effectiveResetTriggered ? interrupt : resolvedQueue.mode;
const shouldSteer = !effectiveResetTriggered && (resolvedQueue.mode === steer || resolvedQueue.mode === steer-backlog);
const shouldFollowup = !effectiveResetTriggered && (resolvedQueue.mode === followup || resolvedQueue.mode === collect || resolvedQueue.mode === steer-backlog);

and then passing queueModeForActiveRun into resolveActiveRunQueueAction / prepared queue handling.

Notes

This may overlap conceptually with other queue/reset issues, but this report is specifically about reset commands being delayed by the normal active-run queue policy.

extent analysis

TL;DR

The issue can be fixed by modifying the queue mode handling in runPreparedReply to use interrupt semantics for reset-triggered turns.

Guidance

  • Identify the runPreparedReply function in dist/get-reply-eY9NJdyX.js and modify the queue mode handling to prioritize reset-triggered turns.
  • Update the queueModeForActiveRun variable to use interrupt mode when effectiveResetTriggered is true.
  • Pass the updated queueModeForActiveRun variable to resolveActiveRunQueueAction to ensure correct queue handling.
  • Verify the fix by testing reset commands (/new, /reset) and checking if the new session starts immediately.

Example

const queueModeForActiveRun = effectiveResetTriggered ? 'interrupt' : resolvedQueue.mode;
const shouldSteer = !effectiveResetTriggered && (resolvedQueue.mode === 'steer' || resolvedQueue.mode === 'steer-backlog');
const shouldFollowup = !effectiveResetTriggered && (resolvedQueue.mode === 'followup' || resolvedQueue.mode === 'collect' || resolvedQueue.mode === 'steer-backlog');

Notes

This fix assumes that the effectiveResetTriggered variable is correctly set for reset-triggered turns. Additional testing may be necessary to ensure the fix works as expected in all scenarios.

Recommendation

Apply the workaround by modifying the runPreparedReply function to use interrupt semantics for reset-triggered turns, as this fix has been locally verified to resolve the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Reset-triggered turns (/new, /reset, or command reset hooks) should interrupt/clear the active run and start the fresh session immediately. They should not be treated as normal steer/followup messages that can wait behind the current run.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING