openclaw 2026.4.15
View on GitHub
Changes
- Anthropic/models: default Anthropic selections,
opusaliases, Claude CLI defaults, and bundled image understanding to Claude Opus 4.7. - Google/TTS: add Gemini text-to-speech support to the bundled
googleplugin, including provider registration, voice selection, WAV reply output, PCM telephony output, and setup/docs guidance. (#67515) Thanks @barronlroth. - Control UI/Overview: add a Model Auth status card showing OAuth token health and provider rate-limit pressure at a glance, with attention callouts when OAuth tokens are expiring or expired. Backed by a new
models.authStatusgateway method that strips credentials and caches for 60s. (#66211) Thanks @omarshahine. - Memory/LanceDB: add cloud storage support to
memory-lancedbso durable memory indexes can run on remote object storage instead of local disk only. (#63502) Thanks @rugvedS07. - GitHub Copilot/memory search: add a GitHub Copilot embedding provider for memory search, and expose a dedicated Copilot embedding host helper so plugins can reuse the transport while honoring remote overrides, token refresh, and safer payload validation. (#61718) Thanks @feiskyer and @vincentkoc.
- Agents/local models: add experimental
agents.defaults.experimental.localModelLean: trueto drop heavyweight default tools likebrowser,cron, andmessage, reducing prompt size for weaker local-model setups without changing the normal path. (#66495) Thanks @ImLukeF. - Packaging/plugins: localize bundled plugin runtime deps to their owning extensions, trim the published docs payload, and tighten install/package-manager guardrails so published builds stay leaner and core stops carrying extension-owned runtime baggage. (#67099) Thanks @vincentkoc.
- QA/Matrix: split Matrix live QA into a source-linked
qa-matrixrunner and keep repo-privateqa-*surfaces out of packaged and published builds. (#66723) Thanks @gumadeiras. - Docs/showcase: add a scannable hero, complete section jump links, and a responsive video grid for community examples. (#48493) Thanks @jchopard69.
Fixes
- Gateway/tools: anchor trusted local
MEDIA:tool-result passthrough on the exact raw name of this run's registered built-in tools, and reject client tool definitions whose names normalize-collide with a built-in or with another client tool in the same request (400 invalid_request_erroron both JSON and SSE paths), so a client-supplied tool named like a built-in can no longer inherit its local-media trust. (#67303) - Agents/replay recovery: classify the provider wording
401 input item ID does not belong to this connectionas replay-invalid, so users get the existing/newsession reset guidance instead of a raw 401-style failure. (#66475) Thanks @dallylee. - Gateway/webchat: enforce localRoots containment on webchat audio embedding path [AI-assisted]. (#67298) Thanks @pgondhi987.
- Matrix/pairing: block DM pairing-store entries from authorizing room control commands [AI-assisted]. (#67294) Thanks @pgondhi987.
- Docker/build: verify
@matrix-org/matrix-sdk-crypto-nodejsnative bindings withfindundernode_modulesinstead of a hardcoded.pnpm/...path so pnpm v10+ virtual-store layouts no longer fail the image build. (#67143) thanks @ly85206559. - Matrix/E2EE: keep startup bootstrap conservative for passwordless token-auth bots, still attempt the guarded repair pass without requiring
channels.matrix.password, and document the remaining password-UIA limitation. (#66228) Thanks @SARAMALI15792. - Cron/announce delivery: suppress mixed-content isolated cron announce replies that end with
NO_REPLYso trailing silent sentinels no longer leak summary text to the target channel. (#65004) thanks @neo1027144-creator. - Plugins/bundled channels: partition bundled channel lazy caches by active bundled root so
OPENCLAW_BUNDLED_PLUGINS_DIRflips stop reusing stale plugin, setup, secrets, and runtime state. (#67200) Thanks @gumadeiras. - Packaging/plugins: prune common test/spec cargo from bundled plugin runtime dependencies and fail npm release validation if packaged test cargo reappears, keeping published tarballs leaner without plugin-specific special cases. (#67275) thanks @gumadeiras.
- Agents/context + Memory: trim default startup/skills prompt budgets, cap
memory_getexcerpts by default with explicit continuation metadata, and keep QMD reads aligned with the same bounded excerpt contract so long sessions pull less context by default without losing deterministic follow-up reads. - Matrix/commands: skip DM pairing-store reads on room traffic now that room control-command authorization ignores pairing-store entries, keeping the room path narrower without changing room auth behavior. (#67325) Thanks @gumadeiras.
- Memory-core/dreaming: skip dreaming narrative transcripts from session-store metadata before bootstrap records land so dream diary prompt/prose lines do not pollute session ingestion. (#67315) thanks @jalehman.
- Agents/local models: clarify low-context preflight hints for self-hosted models, point config-backed caps at the relevant OpenClaw setting, and stop suggesting larger models when
agents.defaults.contextTokensis the real limit. (#66236) Thanks @ImLukeF. - Dreaming/memory-core: change the default
dreaming.storage.modefrominlinetoseparateso Dreaming phase blocks (## Light Sleep,## REM Sleep) land inmemory/dreaming/{phase}/YYYY-MM-DD.mdinstead of being injected intomemory/YYYY-MM-DD.md. Daily memory files no longer get dominated by structured candidate output, and the daily-ingestion scanner that already strips dream marker blocks no longer has to compete with hundreds of phase-block lines on every run. Operators who want the previous behavior can opt in by settingplugins.entries.memory-core.config.dreaming.storage.mode: "inline". (#66412) Thanks @mjamiv. - Control UI/Overview: fix false-positive "missing" alerts on the Model Auth status card for aliased providers, env-backed OAuth with auth.profiles, and unresolvable env SecretRefs. (#67253) Thanks @omarshahine.
- Dashboard: constrain exec approval modal overflow on desktop so long command content no longer pushes action buttons out of view. (#67082) Thanks @Ziy1-Tan.
- Agents/CLI transcripts: persist successful CLI-backed turns into the OpenClaw session transcript so google-gemini-cli replies appear in session history and the Control UI again. (#67490) Thanks @obviyus.
- Discord/tool-call text: strip standalone Gemma-style
tool-call payloads from visible assistant text without truncating prose examples or trailing replies. (#67318) Thanks @joelnishanth.... - WhatsApp/web-session: drain the pending per-auth creds save queue before reopening sockets so reconnect-time auth bootstrap no longer races in-flight
creds.jsonwrites and falsely restores from backup. (#67464) Thanks @neeravmakwana. - BlueBubbles/catchup: add a per-message retry ceiling (
catchup.maxFailureRetries, default 10) so a persistently-failing message with a malformed payload no longer wedges the catchup cursor forever. After N consecutiveprocessMessagefailures against the same GUID, catchup logs a WARN, skips that message on subsequent sweeps, and lets the cursor advance past it. Transient failures still retry from the same point as before. Also fixes a lost-update race in the persistent dedupe file lock that silently dropped inbound GUIDs on concurrent writes, a dedupe file naming migration gap on version upgrade, and a balloon-event bypass that let catchup replay debouncer-coalesced events as standalone messages. (#67426, #66870) Thanks @omarshahine. - Ollama/chat: strip the
ollama/provider prefix from Ollama chat request model ids so configured refs likeollama/qwen3:14b-q8_0stop 404ing against the Ollama API. (#67457) Thanks @suboss87. - Agents/tools: resolve non-workspace host tilde paths against the OS home directory and keep edit recovery aligned with that same path target, so
~/...host edit/write operations stop failing or reading back the wrong file whenOPENCLAW_HOMEdiffers. (#62804) Thanks @stainlu. - Speech/TTS: auto-enable the bundled Microsoft and ElevenLabs speech providers, and route generic TTS directive tokens through the explicit or active provider first so overrides like
[[tts:speed=1.2]]stop silently landing on the wrong provider. (#62846) Thanks @stainlu. - OpenAI Codex/models: normalize stale native transport metadata in both runtime resolution and discovery/listing so legacy
openai-codexrows with missingapiorhttps://chatgpt.com/backend-api/v1self-heal to the canonical Codex transport instead of routing requests through broken HTML/Cloudflare paths, combining the original fixes proposed in #66969 (saamuelng601-pixel) and #67159 (hclsys). (#67635) - Agents/failover: treat HTML provider error pages as upstream transport failures for CDN-style 5xx responses without misclassifying embedded body text as API rate limits, while still preserving auth remediation for HTML 401/403 pages and proxy remediation for HTML 407 pages. (#67642) Thanks @stainlu.
- Gateway/skills: bump the cached skills-snapshot version whenever a config write touches
skills.*(for exampleskills.allowBundled,skills.entries., or.enabled skills.profile). Existing agent sessions persist askillsSnapshotinsessions.jsonthat reuses the skill list frozen at session creation; without this invalidation, removing a bundled skill from the allowlist left the old snapshot live and the model kept calling the disabled tool, producingToolloops that ran until the embedded-run timeout. (#67401) Thanks @xantorres.not found - Agents/tool-loop: enable the unknown-tool stream guard by default. Previously
resolveUnknownToolGuardThresholdreturnedundefinedunlesstools.loopDetection.enabledwas explicitly set totrue, which left the protection off in the default configuration. A hallucinated or removed tool (for examplehimalayaafter it was dropped fromskills.allowBundled) would then loop "Tool X not found" attempts until the full embedded-run timeout. The guard has no false-positive surface because it only triggers on tools that are objectively not registered in the run, so it now stays on regardless oftools.loopDetection.enabledand still acceptstools.loopDetection.unknownToolThresholdas a per-run override (default 10). (#67401) Thanks @xantorres. - TUI/streaming: add a client-side streaming watchdog to
tui-event-handlersso thestreaming · Xm Ysactivity indicator resets toidleafter 30s of delta silence on the active run. Guards against lost or latestate: "final"chat events (WS reconnects, gateway restarts, etc.) leaving the TUI stuck onstreamingindefinitely; a new system log line surfaces the reset so users know to send a new message to resync. The window is configurable via the newstreamingWatchdogMscontext option (set to0to disable), and the handler now exposes adispose()that clears the pending timer on shutdown. (#67401) Thanks @xantorres. - Extensions/lmstudio: add exponential backoff to the inference-preload wrapper so an LM Studio model-load failure (for example the built-in memory guardrail rejecting a load because the swap is saturated) no longer produces a WARN line every ~2s for every chat request. The wrapper now records consecutive preload failures per
(baseUrl, modelKey, contextLength)tuple with a 5s → 10s → 20s → … → 5min cooldown and skips the preload step entirely while a cooldown is active, letting chat requests proceed directly to the stream (the model is often already loaded via the LM Studio UI). The combinedpreload failedlog line now reports consecutive-failure count and remaining cooldown so operators can act on the real issue instead of drowning in repeated warnings. (#67401) Thanks @xantorres. - Agents/replay: re-run tool/result pairing after strict replay tool-call ID sanitization on outbound requests so Anthropic-compatible providers like MiniMax no longer receive malformed orphan tool-result IDs such as
...toolresult1during compaction and retry flows. (#67620) Thanks @stainlu. - Gateway/startup: fix spurious SIGUSR1 restart loop on Linux/systemd when plugin auto-enable is the only startup config write; the config hash guard was not captured for that write path, causing chokidar to treat each boot write as an external change and trigger a reload → restart cycle that corrupts manifest.db after repeated cycles. Fixes #67436. (#67557) thanks @openperf
- Codex/harness: auto-enable the Codex plugin when
codexis selected as an embedded agent harness runtime, including forced default, per-agent, andOPENCLAW_AGENT_RUNTIMEpaths. (#67474) Thanks @duqaXxX. - OpenAI Codex/CLI: keep resumed
codex exec resumeruns on the safe non-interactive path without reintroducing the removed dangerous bypass flag by passing the supported--skip-git-repo-checkresume arg plus Codex's nativesandbox_mode="workspace-write"config override. (#67666) Thanks @plgonzalezrx8. - Codex/app-server: parse Desktop-originated app-server user agents such as
Codex Desktop/0.118.0, keeping the version gate working when the Codex CLI inherits a multi-word originator. (#64666) Thanks @cyrusaf. - Cron/announce delivery: keep isolated announce
NO_REPLYstripping case-insensitive across direct and text delivery, preserve structured media-only sends when a caption strips silent, and derive main-session awareness from the cleaned payloads so silent captions no longer leak staleNO_REPLYtext. (#65016) Thanks @BKF-Gitty. - Sessions/Codex: skip redundant
delivery-mirrortranscript appends only when the latest assistant message has the same visible text, preventing duplicate visible replies on Codex-backed turns without suppressing repeated answers across turns. (#67185) Thanks @andyylin. - Auto-reply/prompt-cache: keep volatile inbound chat IDs out of the stable system prompt so task-scoped adapters can reuse prompt caches across runs, while preserving conversation metadata for the user turn and media-only messages. (#65071) Thanks @MonkeyLeeT.
- BlueBubbles/inbound: restore inbound image attachment downloads on Node 22+ by stripping incompatible bundled-undici dispatchers from the non-SSRF fetch path, accept
updated-messagewebhooks carrying attachments, use event-type-aware dedup keys so attachment follow-ups are not rejected as duplicates, and retry attachment fetch from the BB API when the initial webhook arrives with an empty array. (#64105, #61861, #65430, #67510) Thanks @omarshahine. - Agents/skills: sort prompt-facing
available_skillsentries by skill name after merging sources soskills.load.extraDirsorder no longer changes prompt-cache prefixes. (#64198) Thanks @Bartok9. - Agents/OpenAI Responses: add
models.providers.*.models.*.compat.supportsPromptCacheKeyso OpenAI-compatible proxies that forwardprompt_cache_keycan keep prompt caching enabled while incompatible endpoints can still force stripping. (#67427) Thanks @damselem. - Agents/context engines: keep loop-hook and final
afterTurnprompt-cache touch metadata aligned with the current assistant turn so cache-aware context engines retain accurate cache TTL state during tool loops. (#67767) thanks @jalehman. - Memory/dreaming: strip AI-facing inbound metadata envelopes from session-corpus user turns before normalization so REM topic extraction sees the user's actual message text, including array-shaped split envelopes. (#66548) Thanks @zqchris.
- Agents/errors: detect standalone Cloudflare/CDN HTML challenge pages before transport DNS classification so provider block pages no longer appear as local DNS lookup failures. (#67704) Thanks @chris-yyau.
- Security/approvals: redact secrets in exec approval prompts so inline approval review can no longer leak credential material in rendered prompt content. (#61077, #64790)
- CLI/configure: re-read the persisted config hash after writes so config updates stop failing with stale-hash races. (#64188, #66528)
- CLI/update: prune stale packaged
distchunks after npm upgrades and keep downgrade/verify inventory checks compat-safe so global upgrades stop failing on stale chunk imports. (#66959) Thanks @obviyus. - Onboarding/CLI: fix channel-selection crashes on globally installed CLI setups during onboarding. (#66736)
- Video generation/live tests: bound provider polling for live video smoke, default to the fast non-FAL text-to-video path, and use a one-second lobster prompt so release validation no longer waits indefinitely on slow provider queues.
- Memory-core/QMD
memory_get: reject reads of arbitrary workspace markdown paths and only allow canonical memory files (MEMORY.md,memory.md,DREAMS.md,dreams.md,memory/**) plus exact paths of active indexed QMD workspace documents, so the QMD memory backend can no longer be used as a generic workspace-file read shim that bypassesreadtool-policy denials. (#66026) Thanks @eleqtrizit. - Cron/agents: forward embedded-run tool policy and internal event params into the attempt layer so
--toolsallowlists, cron-owned message-tool suppression, explicit message targeting, and command-path internal events all take effect at runtime again. (#62675) Thanks @hexsprite. - Setup/providers: guard preferred-provider lookup during setup so malformed plugin metadata with a missing provider id no longer crashes the wizard with
Cannot read properties of undefined (reading 'trim'). (#66649) Thanks @Tianworld. - Matrix/security: normalize sandboxed profile avatar params, preserve
mxc://avatar URLs, and surface gmail watcher stop failures during reload. (#64701) Thanks @slepybear. - Telegram/documents: drop leaked binary caption bytes from inbound Telegram text handling so document uploads like
.mobior.epubno longer explode prompt token counts. (#66663) Thanks @joelnishanth. - Gateway/auth: resolve the active gateway bearer per-request on the HTTP server and the HTTP upgrade handler via
getResolvedAuth(), mirroring the WebSocket path, so a secret rotated throughsecrets.reloador config hot-reload stops authenticating on/v1/*,/tools/invoke, plugin HTTP routes, and the canvas upgrade path immediately instead of remaining valid on HTTP until gateway restart. (#66651) Thanks @mmaps. - Agents/compaction: cap the compaction reserve-token floor to the model context window so small-context local models (e.g. Ollama with 16K tokens) no longer trigger context-overflow errors or infinite compaction loops on every prompt. (#65671) Thanks @openperf.
- Agents/OpenAI Responses: classify the exact
Unknown error (no error details in response)transport failure as failover reasonunknownso assistant/model fallback still runs for that no-details failure path. (#65254) Thanks @OpenCodeEngineer. - Models/probe: surface invalid-model probe failures as
formatinstead ofunknowninmodels list --probe, and lock the invalid-model fallback path in with regression coverage. (#50028) Thanks @xiwuqi. - Agents/failover: classify OpenAI-compatible
finish_reason: network_errorstream failures as timeout so model fallback retries continue instead of stopping with an unknown failover reason. (#61784) thanks @lawrence3699. - Onboarding/channels: normalize channel setup metadata before discovery and validation so malformed or mixed-shape channel plugin metadata no longer breaks setup and onboarding channel lists. (#66706) Thanks @darkamenosa.
- Slack/native commands: fix option menus for slash commands such as
/verbosewhen Slack renders native buttons by giving each button a unique action ID while still routing them through the sharedopenclaw_cmdarg*listener. Thanks @Wangmerlyn. - Feishu/webhook: harden the webhook transport and card-action replay guards to fail closed on missing
encryptKeyand blank callback tokens — refuse to start the webhook transport without anencryptKey, reject unsigned requests when no key is present instead of accepting them, and drop blank card-action tokens before the dedupe claim and dispatcher. Defense-in-depth over the already-closed monitor-account layer. (#66707) Thanks @eleqtrizit. - Agents/workspace files: route
agents.files.get,agents.files.set, and workspace listing through the sharedfs-safehelpers (openFileWithinRoot/readFileWithinRoot/writeFileWithinRoot), reject symlink aliases for allowlisted agent files, and havefs-saferesolve opened-file real paths from the file descriptor before falling back to path-basedrealpathso a symlink swap betweenopenandrealpathcan no longer redirect the validated path off the intended inode. (#66636) Thanks @eleqtrizit. - Gateway/MCP loopback: switch the
/mcpbearer comparison from plain!==to constant-timesafeEqualSecret(matching the convention every other auth surface in the codebase uses), and reject non-loopback browser-origin requests viacheckBrowserOriginbefore the auth gate runs. Loopback origins (127.0.0.1:*,localhost:*, same-origin) still go through, including thelocalhost↔127.0.0.1host mismatch that browsers flag asSec-Fetch-Site: cross-site. (#66665) Thanks @eleqtrizit. - Auto-reply/billing: classify pure billing cooldown fallback summaries from structured fallback reasons so users see billing guidance instead of the generic failure reply. (#66363) Thanks @Rohan5commit.
- Agents/fallback: preserve the original prompt body on model fallback retries with session history so the retrying model keeps the active task instead of only seeing a generic continue message. (#66029) Thanks @WuKongAI-CMU.
- Reply/secrets: resolve active reply channel/account SecretRefs before reply-run message-action discovery so channel token SecretRefs (for example Discord) do not degrade into discovery-time unresolved-secret failures. (#66796) Thanks @joshavant.
- Agents/Anthropic: ignore non-positive Anthropic Messages token overrides and fail locally when no positive token budget remains, so invalid
max_tokensvalues no longer reach the provider API. (#66664) thanks @jalehman - Agents/context engines: preserve prompt-only token counts, not full request totals, when deferred maintenance reuses after-turn runtime context so background compaction bookkeeping matches the active prompt window. (#66820) thanks @jalehman.
- BlueBubbles/inbound: add a persistent file-backed GUID dedupe so MessagePoller webhook replays after BB Server restart or reconnect no longer cause the agent to re-reply to already-handled messages. (#19176, #12053, #66816) Thanks @omarshahine.
- Secrets/plugins/status: align SecretRef inspect-vs-strict handling across plugin preload, read-only status/agents surfaces, and runtime auth paths so unresolved refs no longer crash read-only CLI flows while runtime-required non-env refs stay strict. (#66818) Thanks @joshavant.
- Memory/dreaming: stop ordinary transcripts that merely quote the dream-diary prompt from being classified as internal dreaming runs and silently dropped from session recall ingestion. (#66852) Thanks @gumadeiras.
- Telegram/documents: sanitize binary reply context and ZIP-like archive extraction so
.epuband.mobiuploads can no longer leak raw binary into prompt context through reply metadata or archive-to-text/plaincoercion. (#66877) Thanks @martinfrancois. - Telegram/native commands: restore plugin-registry-backed auto defaults for native commands and native skills so Telegram slash commands keep registering when
commands.nativeandcommands.nativeSkillsstay onauto. (#66843) Thanks @kashevk0. - OpenRouter/Qwen3: parse
reasoning_detailsstream deltas as thinking content without skipping same-chunk tool calls, so Qwen3 replies no longer fail empty on OpenRouter and mixed reasoning/tool-call chunks still execute normally. (#66905) Thanks @bladin. - BlueBubbles/catchup: replay missed webhook messages after gateway restart via a persistent per-account cursor and
/api/v1/message/query?after=pass, so messages delivered while the gateway was down no longer disappear. Uses the existingprocessMessagepath and is deduped by #66816's inbound GUID cache. (#66857, #66721) Thanks @omarshahine. - Telegram/native commands: keep Telegram command-sync cache process-local so gateway restarts re-register the menu instead of trusting stale on-disk sync state after Telegram cleared commands out-of-band. (#66730) Thanks @nightq.
- Audio/self-hosted STT: restore
models.providers.*.request.allowPrivateNetworkfor audio transcription so private or LAN speech-to-text endpoints stop tripping SSRF blocks after the v2026.4.14 regression. (#66692) Thanks @jhsmith409. - Auto-reply/media: allow workspace-rooted absolute media paths in auto-reply send flows so valid local media references no longer fail path validation. (#66689)
- WhatsApp/Baileys media upload: harden encrypted upload handling so large outbound media sends avoid buffer spikes and reliability regressions. (#65966) Thanks @frankekn.
- QQBot/cron: guard against undefined
event.contentinparseFaceTagsandfilterInternalMarkersso cron-triggered agent turns with no content payload no longer crash withTypeError: Cannot read properties of undefined (reading 'startsWith'). (#66302) Thanks @xinmotlanthua. - CLI/plugins: stop
--dangerously-force-unsafe-installplugin installs from falling back to hook-pack installs after security scan failures, while still preserving non-security fallback behavior for real hook packs. (#58909) Thanks @hxy91819. - Claude CLI/sessions: classify
No conversation found with session IDassession_expiredso expired CLI-backed conversations clear the stale binding and recover on the next turn. (#65028) thanks @Ivan-Fn. - Context Engine: gracefully fall back to the legacy engine when a third-party context engine plugin fails at resolution time (unregistered id, factory throw, or contract violation), preventing a full gateway outage on every channel. (#66930) Thanks @openperf.
- Control UI/chat: keep optimistic user message cards visible during active sends by deferring same-session history reloads until the active run ends, including aborted and errored runs. (#66997) Thanks @scotthuang and @vincentkoc.
- Media/Slack: allow host-local CSV and Markdown uploads only when the fallback buffer actually decodes as text, so real plain-text files work without letting opaque non-text blobs renamed to
.csvor.mdslip past the host-read guard. (#67047) Thanks @Unayung. - Ollama/onboarding: split setup into
Cloud + Local,Cloud only, andLocal only, support directOLLAMA_API_KEYcloud setup without a local daemon, and keep Ollama web search on the local-host path. (#67005) Thanks @obviyus. - Webchat/security: reject remote-host
file://URLs in the media embedding path. (#67293) Thanks @pgondhi987. - Dreaming/memory-core: use the ingestion day, not the source file day, for daily recall dedupe so repeat sweeps of the same daily note can increment
dailyCountacross days instead of stalling at1. (#67091) Thanks @Bartok9. - Node-host/tools.exec: let approval binding distinguish known native binaries from mutable shell payload files, while still fail-closing unknown or racy file probes so absolute-path node-host commands like
/usr/bin/whoamino longer get rejected as unsafe interpreter/runtime commands. (#66731) Thanks @tmimmanuel.