Upgrade OpenClaw to 2026.4.15 - #25
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated Upgrade: 2026.3.11 → 2026.4.15
Test Results
Review these before merging.
Release Notes
openclaw 2026.4.15
Changes
opusaliases, Claude CLI defaults, and bundled image understanding to Claude Opus 4.7.googleplugin, including provider registration, voice selection, WAV reply output, PCM telephony output, and setup/docs guidance. (#67515) Thanks @barronlroth.models.authStatusgateway method that strips credentials and caches for 60s. (#66211) Thanks @omarshahine.memory-lancedbso durable memory indexes can run on remote object storage instead of local disk only. (#63502) Thanks @rugvedS07.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.qa-matrixrunner and keep repo-privateqa-*surfaces out of packaged and published builds. (#66723) Thanks @gumadeiras.Fixes
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)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.@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.channels.matrix.password, and document the remaining password-UIA limitation. (#66228) Thanks @SARAMALI15792.NO_REPLYso trailing silent sentinels no longer leak summary text to the target channel. (#65004) thanks @neo1027144-creator.OPENCLAW_BUNDLED_PLUGINS_DIRflips stop reusing stale plugin, setup, secrets, and runtime state. (#67200) Thanks @gumadeiras.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.agents.defaults.contextTokensis the real limit. (#66236) Thanks @ImLukeF.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.<function>...</function>tool-call payloads from visible assistant text without truncating prose examples or trailing replies. (#67318) Thanks @joelnishanth.creds.jsonwrites and falsely restores from backup. (#67464) Thanks @neeravmakwana.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/provider prefix from Ollama chat request model ids so configured refs likeollama/qwen3:14b-q8_0stop 404ing against the Ollama API. (#67457) Thanks @suboss87.~/...host edit/write operations stop failing or reading back the wrong file whenOPENCLAW_HOMEdiffers. (#62804) Thanks @stainlu.[[tts:speed=1.2]]stop silently landing on the wrong provider. (#62846) Thanks @stainlu.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)skills.*(for exampleskills.allowBundled,skills.entries.<id>.enabled, orskills.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, producingTool <name> not foundloops that ran until the embedded-run timeout. (#67401) Thanks @xantorres.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-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.(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....toolresult1during compaction and retry flows. (#67620) Thanks @stainlu.codexis selected as an embedded agent harness runtime, including forced default, per-agent, andOPENCLAW_AGENT_RUNTIMEpaths. (#67474) Thanks @duqaXxX.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 Desktop/0.118.0, keeping the version gate working when the Codex CLI inherits a multi-word originator. (#64666) Thanks @cyrusaf.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.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.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.available_skillsentries by skill name after merging sources soskills.load.extraDirsorder no longer changes prompt-cache prefixes. (#64198) Thanks @Bartok9.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.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.distchunks after npm upgrades and keep downgrade/verify inventory checks compat-safe so global upgrades stop failing on stale chunk imports. (#66959) Thanks @obviyus.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.--toolsallowlists, cron-owned message-tool suppression, explicit message targeting, and command-path internal events all take effect at runtime again. (#62675) Thanks @hexsprite.Cannot read properties of undefined (reading 'trim'). (#66649) Thanks @Tianworld.mxc://avatar URLs, and surface gmail watcher stop failures during reload. (#64701) Thanks @slepybear..mobior.epubno longer explode prompt token counts. (#66663) Thanks @joelnishanth.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.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.formatinstead ofunknowninmodels list --probe, and lock the invalid-model fallback path in with regression coverage. (#50028) Thanks @xiwuqi.finish_reason: network_errorstream failures as timeout so model fallback retries continue instead of stopping with an unknown failover reason. (#61784) thanks @lawrence3699./verbosewhen Slack renders native buttons by giving each button a unique action ID while still routing them through the sharedopenclaw_cmdarg*listener. Thanks @Wangmerlyn.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.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./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.max_tokensvalues no longer reach the provider API. (#66664) thanks @jalehman.epuband.mobiuploads can no longer leak raw binary into prompt context through reply metadata or archive-to-text/plaincoercion. (#66877) Thanks @martinfrancois.commands.nativeandcommands.nativeSkillsstay onauto. (#66843) Thanks @kashevk0.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./api/v1/message/query?after=<ts>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.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.event.contentinparseFaceTagsandfilterInternalMarkersso cron-triggered agent turns with no content payload no longer crash withTypeError: Cannot read properties of undefined (reading 'startsWith'). (#66302) Thanks @xinmotlanthua.--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.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..csvor.mdslip past the host-read guard. (#67047) Thanks @Unayung.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.file://URLs in the media embedding path. (#67293) Thanks @pgondhi987.dailyCountacross days instead of stalling at1. (#67091) Thanks @Bartok9./usr/bin/whoamino longer get rejected as unsafe interpreter/runtime commands. (#66731) Thanks @tmimmanuel.openclaw 2026.4.14
OpenClaw
2026.4.14is another broad quality release focused on model provider with explicit turn improvements for GPT-5 family and channel provider issues. Additionally we improved overal performance with refactors to our underlying core codebase.Changes
gpt-5.4-pro, including Codex pricing/limits and list/status visibility before the upstream catalog catches up. (#66453) Thanks @jepson-liu.Fixes
apiKeyin the codex provider catalog output so the Pi ModelRegistry validator no longer rejects the entry and silently drops all custom models from every provider inmodels.json. (#66180) Thanks @hoyyeva.allowFromowner allowlist to channel block-action and modal interactive events, require an expected sender id for cross-verification, and reject ambiguous channel types so interactive triggers can no longer bypass the documented allowlist intent in channels without auserslist. Open-by-default behavior is preserved when no allowlists are configured. (#66028) Thanks @eleqtrizit.realpath, so arealpatherror can no longer downgrade the canonical-roots allowlist check to a non-canonical comparison; attachments that also have a URL still fall back to the network fetch path. (#66022) Thanks @eleqtrizit.config.patchandconfig.applycalls from the model-facing gateway tool when they would newly enable any flag enumerated byopenclaw security audit(for exampledangerouslyDisableDeviceAuth,allowInsecureAuth,dangerouslyAllowHostHeaderOriginFallback,hooks.gmail.allowUnsafeExternalContent,tools.exec.applyPatch.workspaceOnly: false); already-enabled flags pass through unchanged so non-dangerous edits in the same patch still apply, and direct authenticated operator RPC behavior is unchanged. (#62006) Thanks @eleqtrizit./openaisuffix from configured Google base URLs only when calling the native Gemini image API so Gemini image requests stop 404ing without breaking explicit OpenAI-compatible Google endpoints. (#66445) Thanks @dapzthelegend.openclaw doctor --repairand service reinstall from re-embedding dotenv-backed secrets in user systemd units, while preserving newer inline overrides over stale state-dir.envvalues. (#66249) Thanks @tmimmanuel.stream_options.include_usagefor Ollama streaming completions so local Ollama runs report real usage instead of falling back to bogus prompt-token counts that trigger premature compaction. (#64568) Thanks @xchunzhao and @vincentkoc.preferOvercatalog lookups within each plugin auto-enable pass so largeagents.listconfigs no longer peg CPU and repeatedly reread plugin catalogs during doctor/plugins resolution. (#66246) Thanks @yfge.github-copilot/gpt-5.4to usexhighreasoning so Copilot GPT-5.4 matches the rest of the GPT-5.4 family. (#50168) Thanks @jakepresent and @vincentkoc.Unknown memory embedding provider. (#66452) Thanks @jlapenna.agents.defaults.contextTokensis the real limit. (#66236) Thanks @ImLukeF./json/newfallback requests on the local CDP control policy so browser follow-up fixes stop regressing normal navigation or self-blocking local CDP control. (#66386) Thanks @obviyus.openai-codex/gpt-5.4-codexruntime alias toopenai-codex/gpt-5.4while still honoring alias-specific and canonical per-model overrides. (#43060) Thanks @Sapientropic and @vincentkoc.browser.ssrfPolicy.allowPrivateNetwork: falseconfigs by normalizing the legacy alias to the canonical strict marker instead of silently widening those installs to the default non-strict hostname-navigation path.max_tokens=16for OpenAI-compatible verification probes so stricter custom endpoints stop rejecting onboarding checks that only need a tiny completion. (#66450) Thanks @WuKongAI-CMU.ERR_MODULE_NOT_FOUNDat runtime. (#66420) Thanks @obviyus.HTTP_PROXY/HTTPS_PROXYis active and the target is not bypassed byNO_PROXY, so remote media-understanding and transcription requests stop failing local DNS pre-resolution in proxy-only environments without widening SSRF bypasses. (#52162) Thanks @mjamiv and @vincentkoc.could not download mediaon Bot API file downloads after the DNS-pinning regression. (#66245) Thanks @dawei41468 and @vincentkoc.afterTurnis absent, so long-running tool loops can stay bounded without dropping engine state. (#63555) Thanks @Bikkies./statusinteractions instead of falling through to the synthetic✅ Done.ack when the generic dispatcher produces no visible reply. (#54629) Thanks @tkozzer and @vincentkoc.agents.defaults.timeoutSecondsoverride instead of always aborting after 15 seconds, so slow local Ollama runs stop silently dropping back to generic filenames. (#66237) Thanks @dmak and @vincentkoc..aacfilenames to.m4afor OpenAI-compatible audio uploads so AAC voice notes stop failing MIME-sensitive transcription endpoints. (#66446) Thanks @ben-z.sendPolicy: "deny"from blocking inbound message processing, so the agent still runs its turn while all outbound delivery is suppressed for observer-style setups. (#65461, #53328) Thanks @omarshahine.hook:wakesystem events [AI-assisted]. (#66031) Thanks @pgondhi987.sourceConfigandruntimeConfigalias fields inredactConfigSnapshot[AI]. (#66030) Thanks @pgondhi987.plugins inspectinstead of the owning plugin ID, so non-matching engine IDs and multi-engine plugins are classified correctly. (#58766) Thanks @zhuisDEV.info.iddoes not match their registered slot id, so malformed engines fail fast before id-based runtime branches can misbehave. (#63222) Thanks @fuller-stack-dev.ENOENTcrashes on image sends. (#65896) Thanks @frankekn.dist/entry.jsand currentdist/index.jspaths. (#65984) Thanks @mbelinky.target=last, instead of dropping them into the group root chat. (#66035) Thanks @mbelinky.heartbeattargets from poisoning later cron or user delivery. (#66073, #63733, #35300) Thanks @mbelinky.manual-cdpprofiles reuse the local loopback CDP control plane under strict default policy and remote-class probe timeouts, so tabs/snapshot stop falsely reporting a live local browser session as not running. (#65611, #66080) Thanks @mbelinky.sessioncontext on queued delivery entries and replay it during recovery, so write-ahead-queued sends keep their original outbound media policy context after restart instead of evaluating against a missing session. (#66025) Thanks @eleqtrizit.ollamaembedding adapter in memory-core so explicitmemorySearch.provider: "ollama"works again, and include endpoint-aware cache keys so different Ollama hosts do not reuse each other's embeddings. (#63429, #66078, #66163) Thanks @nnish16 and @vincentkoc.memory-wikigateway methods when the plugin is off, and refresh config before wiki reloads so the Dreaming tab stops showing misleading unknown-method failures. (#66140) Thanks @mbelinky.memory.mdas a second default root collection, so QMD recall no longer searches phantommemory-alt-*collections and builtin/QMD root-memory fallback stays aligned. (#66141) Thanks @mbelinky.dist/agents/subagent-registry.runtime.jsin npm builds soruntime: "subagent"runs stop stalling inqueuedafter the registry import fails. (#66189) Thanks @yqli2420 and @vincentkoc.minimalthinking to OpenAI's supportedlowreasoning effort for GPT-5.4 requests, so embedded runs stop failing request validation. Thanks @steipete.webhookSecurity.trustForwardingHeadersandtrustedProxyIPsare configured, and reservemaxConnectionscapacity for in-flight WebSocket upgrades so concurrent handshakes can no longer momentarily exceed the operator-set cap. (#66027) Thanks @eleqtrizit.user/chatkind, strip repeatedfeishu:/lark:provider prefixes, and stop folding opaque Feishu IDs to lowercase, so allowlist matching no longer crosses user/chat namespaces or widens to case-insensitive ID matches the operator did not intend. (#66021) Thanks @eleqtrizit./export-sessionon the normal lane so it cannot interleave with an in-flight session mutation. (#66226) Thanks @VACInc and @vincentkoc.C:\\...) as absolute when resolving sandbox and read-tool paths so workspace root is not prepended under POSIX path rules. (#54039) Thanks @ly85206559 and @vincentkoc.No channel reply.,Replied in-thread.,Replied in #..., wiki-update status variants ending inNo channel reply.) before channel delivery so internal housekeeping text does not leak to users.openclaw cronno longer fall back to Slack's broader contract surface, which could trigger Slack-related config-read crashes on affected setups. (#63192) Thanks @shhtheonlyperson./newand/resetsession-memory hooks so reset snapshots stay scoped to the right agent workspace instead of leaking into the default workspace. (#64735) Thanks @suboss87 and @vincentkoc.openclaw approvals getgateway timeout and report config-load timeouts explicitly, so slow hosts stop showing a misleadingConfig unavailable.note when the approvals snapshot succeeds but the follow-up config RPC needs more time. (#66239) Thanks @neeravmakwana.openclaw 2026.4.12
OpenClaw
2026.4.12is a broad quality release focused on plugin loading, memory and dreaming reliability, new local-model options, and a much smoother Feishu setup path.Changes
openclaw qa credentialsadmin commands and broker setup docs. (#65596) Thanks @joshavant./verboseinspection, advanced prompt/thinking overrides for tuning, and opt-in transcript persistence for debugging. (#63286) Thanks @Takhoffman.openclaw exec-policycommand withshow,preset, andsetsubcommands for synchronizing requestedtools.exec.*config with the local exec approvals file, plus follow-up hardening for node-host rejection, rollback safety, and sync conflict detection. (#64050)commands.listRPC so remote gateway clients can discover runtime-native, text, skill, and plugin commands with surface-aware naming and serialized argument metadata. (#62656) Thanks @samzong.models.providers.*.request.allowPrivateNetworkfor trusted self-hosted OpenAI-compatible endpoints, keep the opt-in scoped to model request surfaces, and refresh cached WebSocket managers when request transport overrides change. (#63671) Thanks @qas.--runner multipasslane foropenclaw qa suiteso repo-backed QA scenarios can run inside a disposable Linux VM and write back the usual report, summary, and VM logs. (#63426) Thanks @shakkernerd.openai/gpt-5.4path. (#62969, #63808) Thanks @hxy91819.This is an automated version bump. Only the Dockerfile was changed.
If release notes mention config/schema changes, manual review is required.
Do not merge if there are known regressions above.
Docker test output