openclaw - 💡(How to fix) Fix Dreaming narrative generation fails for all but 1 agent due to concurrent fire-and-forget API calls [1 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#75930Fetched 2026-05-03 04:44:12
View on GitHub
Comments
1
Participants
2
Timeline
4
Reactions
2
Timeline (top)
commented ×1mentioned ×1subscribed ×1unsubscribed ×1

The dreaming system's narrative generation (generateAndAppendDreamNarrative) uses queueMicrotask() + detachNarratives = true when triggered via cron, causing all workspace narrative API calls to fire simultaneously. With N workspaces × 2 phases (light + REM) ≈ 20+ concurrent LLM API calls, most providers rate-limit and only the first succeeds. The .catch(() => void 0) pattern silently swallows all failures.

Root Cause

In dreaming-IJthLYjI.js, detachNarratives is always true for cron triggers:

detachNarratives = params.trigger === "cron"

Combined with the fire-and-forget pattern:

if (params.detachNarratives)
  queueMicrotask(() => {
    generateAndAppendDreamNarrative({...}).catch(() => void 0);
  });
else
  await generateAndAppendDreamNarrative({...});

The outer loop iterates all workspaces and phases (runShortTermDreamingPromotionIfTriggered), so every workspace's narrative call fires as a microtask concurrently. DeepSeek, OpenAI, and similar providers reject or queue concurrent requests from the same API key, resulting in all but the first call being rate-limited. Because errors are silently swallowed, there is no log evidence unless you inspect the "narrative generation produced no text" debug output.

Additionally, there is a 15-second timeout (NARRATIVE_TIMEOUT_MS = 15e3) which can compound the issue when calls are queued server-side.

Code Example

detachNarratives = params.trigger === "cron"

---

if (params.detachNarratives)
  queueMicrotask(() => {
    generateAndAppendDreamNarrative({...}).catch(() => void 0);
  });
else
  await generateAndAppendDreamNarrative({...});
RAW_BUFFERClick to expand / collapse

Summary

The dreaming system's narrative generation (generateAndAppendDreamNarrative) uses queueMicrotask() + detachNarratives = true when triggered via cron, causing all workspace narrative API calls to fire simultaneously. With N workspaces × 2 phases (light + REM) ≈ 20+ concurrent LLM API calls, most providers rate-limit and only the first succeeds. The .catch(() => void 0) pattern silently swallows all failures.

Steps to reproduce

  1. Configure multiple agents with separate workspaces (e.g., 5-10)
  2. Enable dreaming with "frequency": "17 3 * * *" in memory-core plugin config
  3. Wait for a dreaming cycle, or trigger it manually
  4. Observe: only 1 workspace gets a DREAMS.md narrative entry; the rest produce no narrative text

Note: the core memory dreaming (light/REM/deep sleep raw data) works correctly for all agents. Only the LLM-generated diary narrative is affected.

Root cause

In dreaming-IJthLYjI.js, detachNarratives is always true for cron triggers:

detachNarratives = params.trigger === "cron"

Combined with the fire-and-forget pattern:

if (params.detachNarratives)
  queueMicrotask(() => {
    generateAndAppendDreamNarrative({...}).catch(() => void 0);
  });
else
  await generateAndAppendDreamNarrative({...});

The outer loop iterates all workspaces and phases (runShortTermDreamingPromotionIfTriggered), so every workspace's narrative call fires as a microtask concurrently. DeepSeek, OpenAI, and similar providers reject or queue concurrent requests from the same API key, resulting in all but the first call being rate-limited. Because errors are silently swallowed, there is no log evidence unless you inspect the "narrative generation produced no text" debug output.

Additionally, there is a 15-second timeout (NARRATIVE_TIMEOUT_MS = 15e3) which can compound the issue when calls are queued server-side.

Suggested fix

Option A — Remove detachNarratives and always await sequentially within the workspace loop. Simplest fix; guarantees every workspace gets a narrative. The dreaming cycle already runs asynchronously in the background, so the performance impact is negligible.

Option B — Keep concurrency but add a configurable limiter (e.g., p-limit with concurrency 1-3) plus retry with exponential backoff. More complex but retains parallelism for very large deployments.

Option C — Batch all workspace snippets into a single narrative generation call per cycle, producing one diary entry covering all agents, then fan out to individual DREAMS.md files.

Environment

  • OpenClaw 2026.4.27
  • macOS arm64
  • DeepSeek API (also reproducible with Moonshot API)
  • 10 workspaces configured

extent analysis

TL;DR

Remove detachNarratives and always await sequentially within the workspace loop to guarantee every workspace gets a narrative.

Guidance

  • Identify the dreaming-IJthLYjI.js file and locate the detachNarratives variable assignment to understand its impact on the narrative generation process.
  • Consider implementing Option A from the suggested fix, which involves removing detachNarratives and using await to ensure sequential execution of narrative generation for each workspace.
  • If concurrency is still desired, explore Option B and implement a configurable limiter with retry and exponential backoff to manage concurrent requests to the LLM API.
  • Verify the fix by checking the DREAMS.md files for each workspace to ensure that all workspaces are receiving narrative entries.

Example

// Before
if (params.detachNarratives)
  queueMicrotask(() => {
    generateAndAppendDreamNarrative({...}).catch(() => void 0);
  });
// After (Option A)
await generateAndAppendDreamNarrative({...});

Notes

The provided fix options assume that the narrative generation process is not time-sensitive and can be executed sequentially without significant performance impact. However, for very large deployments, Option B or Option C might be more suitable to balance concurrency and rate limiting.

Recommendation

Apply workaround Option A, as it is the simplest fix and guarantees every workspace receives a narrative, with negligible performance impact due to the asynchronous nature of the dreaming cycle.

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