openclaw - 💡(How to fix) Fix Followup queue drain crashes on CLI runtimes (claude-cli/codex-cli/gemini-cli): "Requested agent harness ... is not registered"

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…

createFollowupRunner unconditionally routes through runEmbeddedPiAgent, skipping the CLI-runtime dispatch branch the primary reply path uses. Any queued followup whose model resolves to a CLI runtime (claude-cli, codex-cli, google-gemini-cli) throws Requested agent harness "<runtime>" is not registered. and the queued message is silently dropped.

User-visible symptom: on bursty Signal threads (and any channel with queued followup delivery), only the most recent inbound that arrives while the agent is idle gets processed. Anything that lands mid-turn is queued, the drain crashes, and those messages vanish without surfacing an error.

Error Message

User-visible symptom: on bursty Signal threads (and any channel with queued followup delivery), only the most recent inbound that arrives while the agent is idle gets processed. Anything that lands mid-turn is queued, the drain crashes, and those messages vanish without surfacing an error. throw new Error(Requested agent harness "${runtime}" is not registered.);

Root Cause

Throw site: selection-61FIEezO.js:9781-9799

const forced = pluginHarnesses.find((entry) => entry.id === runtime);
if (forced) return ...;
throw new Error(`Requested agent harness "${runtime}" is not registered.`);

Primary reply path (agent-runner.runtime-Dv_D_ax0.js:1030-1083) correctly checks for CLI runtimes first and routes them through runCliAgent:

const cliExecutionProvider = resolveCliRuntimeExecutionProvider(...) ?? provider;
if (isCliProvider(cliExecutionProvider, runtimeConfig)) {
  const result = await runCliAgent(...);
}

Followup queued runner (agent-runner.runtime-Dv_D_ax0.js:3034-3047) skips that branch entirely and always calls embedded Pi:

const fallbackResult = await runWithModelFallback({
  ...
  run: async (provider, model, runOptions) => {
    ...
    const result = await runEmbeddedPiAgent({ ... });

Embedded harness selection then looks up claude-cli (or codex-cli/google-gemini-cli) as a harness id — but those are registered as CLI backends by their plugins, not as runtime harnesses. Anthropic plugin registration:

  • register.runtime-CR-c-hRh.js:403-405api.registerCliBackend(buildAnthropicCliBackend())
  • Manifest extensions/anthropic/openclaw.plugin.json:54-56cliBackends entry, not a runtime harness

Fix Action

Fix / Workaround

createFollowupRunner unconditionally routes through runEmbeddedPiAgent, skipping the CLI-runtime dispatch branch the primary reply path uses. Any queued followup whose model resolves to a CLI runtime (claude-cli, codex-cli, google-gemini-cli) throws Requested agent harness "<runtime>" is not registered. and the queued message is silently dropped.

Note: parent/child sharing the same runtime does not avoid the bug if that runtime is a CLI runtime. The dispatcher problem is independent of inheritance — it triggers whenever the queued lane resolves to any CLI runtime id.

Code Example

const forced = pluginHarnesses.find((entry) => entry.id === runtime);
if (forced) return ...;
throw new Error(`Requested agent harness "${runtime}" is not registered.`);

---

const cliExecutionProvider = resolveCliRuntimeExecutionProvider(...) ?? provider;
if (isCliProvider(cliExecutionProvider, runtimeConfig)) {
  const result = await runCliAgent(...);
}

---

const fallbackResult = await runWithModelFallback({
  ...
  run: async (provider, model, runOptions) => {
    ...
    const result = await runEmbeddedPiAgent({ ... });

---

const cliExecutionProvider = resolveCliRuntimeExecutionProvider(...) ?? provider;
if (isCliProvider(cliExecutionProvider, runtimeConfig)) {
  return runCliAgent(...);  // with the queued run params
}
return runEmbeddedPiAgent(...);
RAW_BUFFERClick to expand / collapse

Summary

createFollowupRunner unconditionally routes through runEmbeddedPiAgent, skipping the CLI-runtime dispatch branch the primary reply path uses. Any queued followup whose model resolves to a CLI runtime (claude-cli, codex-cli, google-gemini-cli) throws Requested agent harness "<runtime>" is not registered. and the queued message is silently dropped.

User-visible symptom: on bursty Signal threads (and any channel with queued followup delivery), only the most recent inbound that arrives while the agent is idle gets processed. Anything that lands mid-turn is queued, the drain crashes, and those messages vanish without surfacing an error.

Root cause

Throw site: selection-61FIEezO.js:9781-9799

const forced = pluginHarnesses.find((entry) => entry.id === runtime);
if (forced) return ...;
throw new Error(`Requested agent harness "${runtime}" is not registered.`);

Primary reply path (agent-runner.runtime-Dv_D_ax0.js:1030-1083) correctly checks for CLI runtimes first and routes them through runCliAgent:

const cliExecutionProvider = resolveCliRuntimeExecutionProvider(...) ?? provider;
if (isCliProvider(cliExecutionProvider, runtimeConfig)) {
  const result = await runCliAgent(...);
}

Followup queued runner (agent-runner.runtime-Dv_D_ax0.js:3034-3047) skips that branch entirely and always calls embedded Pi:

const fallbackResult = await runWithModelFallback({
  ...
  run: async (provider, model, runOptions) => {
    ...
    const result = await runEmbeddedPiAgent({ ... });

Embedded harness selection then looks up claude-cli (or codex-cli/google-gemini-cli) as a harness id — but those are registered as CLI backends by their plugins, not as runtime harnesses. Anthropic plugin registration:

  • register.runtime-CR-c-hRh.js:403-405api.registerCliBackend(buildAnthropicCliBackend())
  • Manifest extensions/anthropic/openclaw.plugin.json:54-56cliBackends entry, not a runtime harness

How to reproduce

  1. Configure a session whose agents.defaults.models[<id>].agentRuntime.id is claude-cli (or codex-cli/google-gemini-cli).
  2. Send a message that triggers a long-running turn (tools, subagents).
  3. While that turn is in flight, send a second message on the same channel. It enters the followup queue.
  4. When the primary turn completes, the followup drain runs → throws Requested agent harness "claude-cli" is not registered. → queued message is dropped.

Affects every queued lane that goes through createFollowupRunner: followup, collect, steer-backlog, cron/system-event followups.

Note: parent/child sharing the same runtime does not avoid the bug if that runtime is a CLI runtime. The dispatcher problem is independent of inheritance — it triggers whenever the queued lane resolves to any CLI runtime id.

Recommended fix (upstream)

In createFollowupRunner, before runEmbeddedPiAgent, perform the same CLI check the primary path does:

const cliExecutionProvider = resolveCliRuntimeExecutionProvider(...) ?? provider;
if (isCliProvider(cliExecutionProvider, runtimeConfig)) {
  return runCliAgent(...);  // with the queued run params
}
return runEmbeddedPiAgent(...);

Keeps claude-cli / codex-cli / google-gemini-cli as CLI backends instead of pretending they're harnesses.

Risk: affects all queued lanes — followup, collect, steer-backlog, cron/system-event followups, and any lane draining queued replies. Tests should cover:

  • Signal followup delivery for CLI runtimes
  • CLI session binding reuse across the drain
  • Fallback to embedded Pi for non-CLI runtimes (regression check)
  • Duplicate-delivery semantics through the CLI output bridge

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix Followup queue drain crashes on CLI runtimes (claude-cli/codex-cli/gemini-cli): "Requested agent harness ... is not registered"