2026.4.20
Changes
- Onboard/wizard: restyle the setup security disclaimer with a single yellow warning banner, section headings and bulleted checklists, and un-dim the note body so key guidance is easy to scan; add a loading spinner during the initial model catalog load so the wizard no longer goes blank while it runs; add an "API key" placeholder to provider API key prompts. (#69553) Thanks @Patrick-Erichsen.
- Agents/prompts: strengthen the default system prompt and OpenAI GPT-5 overlay with clearer completion bias, live-state checks, weak-result recovery, and verification-before-final guidance.
- Models/costs: support tiered model pricing from cached catalogs and configured models, and include bundled Moonshot Kimi K2.6/K2.5 cost estimates for token-usage reports. (#67605) Thanks @sliverp.
- Sessions/Maintenance: enforce the built-in entry cap and age prune by default, and prune oversized stores at load time so accumulated cron/executor session backlogs cannot OOM the gateway before the write path runs. (#69404) Thanks @bobrenze-bot.
- Plugins/tests: reuse plugin loader alias and Jiti config resolution across repeated same-context loads, reducing import-heavy test overhead. (#69316) Thanks @amknight.
- Cron: split runtime execution state into
jobs-state.jsonsojobs.jsonstays stable for git-tracked job definitions. (#63105) Thanks @Feelw00. - Agents/compaction: send opt-in start and completion notices during context compaction. (#67830) Thanks @feniix.
- Moonshot/Kimi: default bundled Moonshot setup, web search, and media-understanding surfaces to
kimi-k2.6while keepingkimi-k2.5available for compatibility. (#69477) Thanks @scoootscooob. - Moonshot/Kimi: allow
thinking.keep = "all"onmoonshot/kimi-k2.6, and strip it for other Moonshot models or requests where pinnedtool_choicedisables thinking. (#68816) Thanks @aniaan. - BlueBubbles/groups: forward per-group
systemPromptconfig into inbound contextGroupSystemPromptso configured group-specific behavioral instructions (for example threaded-reply and tapback conventions) are injected on every turn. Supports"*"wildcard fallback matching the existingrequireMentionpattern. Closes #60665. (#69198) Thanks @omarshahine. - Plugins/tasks: add a detached runtime registration contract so plugin executors can own detached task lifecycle and cancellation without reaching into core task internals. (#68915) Thanks @mbelinky.
- Terminal/logging: optimize
sanitizeForLog()by replacing the iterative control-character stripping loop with a single regex pass while preserving the existing ANSI-first sanitization behavior. (#67205) Thanks @bulutmuf. - QA/CI: make
openclaw qa suiteandopenclaw qa telegramfail by default when scenarios fail, add--allow-failuresfor artifact-only runs, and tighten live-lane defaults for CI automation. (#69122) Thanks @joshavant. - Mattermost: stream thinking, tool activity, and partial reply text into a single draft preview post that finalizes in place when safe. (#47838) thanks @ninjaa.
Fixes
- Exec/YOLO: stop rejecting gateway-host exec in
security=fullplusask=offmode via the Python/Node script preflight hardening path, so promptless YOLO exec once again runs direct interpreter stdin and heredoc forms such asnode <<'NODE' ... NODE. - OpenAI Codex: normalize legacy
openai-completionstransport overrides on default OpenAI/Codex and GitHub Copilot-compatible hosts back to the native Codex Responses transport while leaving custom proxies untouched. (#45304, #42194) Thanks @dyss1992 and @DeadlySilent. - Anthropic/plugins: scope Anthropic
api: "anthropic-messages"defaulting to Anthropic-owned providers, soopenai-codexand other providers without an explicitapino longer get rewritten to the wrong transport. Fixes #64534. - fix(qqbot): add SSRF guard to direct-upload URL paths in uploadC2CMedia and uploadGroupMedia [AI-assisted]. (#69595) Thanks @pgondhi987.
- fix(gateway): enforce allowRequestSessionKey gate on template-rendered mapping sessionKeys. (#69381) Thanks @pgondhi987.
- Browser/Chrome MCP: surface
DevToolsActivePortattach failures as browser-connectivity errors instead of a generic "waiting for tabs" timeout, and point signed-out fallbacks toward the managedopenclawprofile. - Webchat/images: treat inline image attachments as media for empty-turn gating while still ignoring metadata-only blank turns. (#69474) Thanks @Jaswir.
- Discord/think: only show
adaptivein/thinkautocomplete for provider/model pairs that actually support provider-managed adaptive thinking, so GPT/OpenAI models no longer advertise an Anthropic-only option. - Thinking: only expose
maxfor models that explicitly support provider max reasoning, and remap storedmaxsettings to the largest supported thinking mode when users switch to another model. - Gateway/usage: bound the cost usage cache with FIFO eviction so date/range lookups cannot grow unbounded. (#68842) Thanks @Feelw00.
- OpenAI/Responses: resolve
/thinklevels against each GPT model's supported reasoning efforts so/think offno longer becomes high reasoning or sends unsupportedreasoning.effort: "none"payloads. - Lobster/TaskFlow: allow managed approval resumes to use
approvalIdwithout a resume token, and persist that id in approval wait state. (#69559) Thanks @kirkluokun. - Plugins/startup: install bundled runtime dependencies into each plugin's own runtime directory, reuse source-checkout repair caches after rebuilds, and log only packages that were actually installed so repeated Gateway starts stay quiet once deps are present.
- Plugins/startup: ignore pnpm's
npm_execpathwhen repairing bundled plugin runtime dependencies and skip workspace-only package specs so npm-only install flags or local workspace links do not break packaged plugin startup. - MCP: block interpreter-startup env keys such as
NODE_OPTIONSfor stdio servers while preserving ordinary credential and proxy env vars. (#69540) Thanks @drobison00. - Agents/shell: ignore non-interactive placeholder shells like
/usr/bin/falseand/sbin/nologin, falling back toshso service-user exec runs no longer exit immediately. (#69308) Thanks @sk7n4k3d. - Setup/TUI: relaunch the setup hatch TUI in a fresh process while preserving the configured gateway target and auth source, so onboarding recovers terminal state cleanly without exposing gateway secrets on command-line args. (#69524) Thanks @shakkernerd.
- Codex: avoid re-exposing the image-generation tool on native vision turns with inbound images, and keep bare image-model overrides on the configured image provider. (#65061) Thanks @zhulijin1991.
- Sessions/reset: clear auto-sourced model, provider, and auth-profile overrides on
/newand/resetwhile preserving explicit user selections, so channel sessions stop staying pinned to runtime fallback choices. (#69419) Thanks @sk7n4k3d. - Sessions/costs: snapshot
estimatedCostUsdlike token counters so repeated persist paths no longer compound the same run cost by up to dozens of times. (#69403) Thanks @MrMiaigi. - OpenAI Codex: route ChatGPT/Codex OAuth Responses requests through the
/backend-api/codexendpoint soopenai-codex/gpt-5.4no longer hits the removed/backend-api/responsesalias. (#69336) Thanks @mzogithub. - OpenAI/Responses: omit disabled reasoning payloads when
/think offis active, so GPT reasoning models no longer receive unsupportedreasoning.effort: "none"requests. (#61982) Thanks @a-tokyo. - Gateway/pairing: treat loopback shared-secret node-host, TUI, and gateway clients as local for pairing decisions, so trusted local tools no longer reconnect as remote clients and fail with
pairing required. (#69431) Thanks @SARAMALI15792. - Active Memory: degrade gracefully when memory recall fails during prompt building, logging a warning and letting the reply continue without memory context instead of failing the whole turn. (#69485) Thanks @Magicray1217.
- Ollama: add provider-policy defaults for
baseUrlandmodelsso implicit local discovery can run before config validation rejects a minimal Ollama provider config. (#69370) Thanks @PratikRai0101. - Agents/model selection: clear transient auto-failover session overrides before each turn so recovered primary models are retried immediately without emitting user-override reset warnings. (#69365) Thanks @hitesh-github99.
- Auto-reply: apply silent
NO_REPLYpolicy per conversation type, so direct chats get a helpful rewritten reply while groups and internal deliveries can remain quiet. (#68644) Thanks @Takhoffman. - Telegram/status reactions: honor
messages.removeAckAfterReplywhen lifecycle status reactions are enabled, clearing or restoring the reaction after success/error using the configured hold timings. (#68067) Thanks @poiskgit. - Web search/plugins: resolve plugin-scoped SecretRef API keys for bundled Exa, Firecrawl, Gemini, Kimi, Perplexity, Tavily, and Grok web-search providers when they are selected through the shared web-search config. (#68424) Thanks @afurm.
- Telegram/polling: raise the default polling watchdog threshold from 90s to 120s and add configurable
channels.telegram.pollingStallThresholdMs(also per-account) so long-running Telegram work gets more room before polling is treated as stalled. (#57737) Thanks @Vitalcheffe. - Telegram/polling: bound the persisted-offset confirmation
getUpdatesprobe with a client-side timeout so a zombie socket cannot hang polling recovery before the runner watchdog starts. (#50368) Thanks @boticlaw. - Agents/Pi runner: retry silent
stopReason=errorturns with no output when no side effects ran, so non-frontier providers that briefly return empty error turns get another chance instead of ending the session early. (#68310) Thanks @Chased1k. - Plugins/memory: preserve the active memory capability when read-only snapshot plugin loads run, so status and provider discovery paths no longer wipe memory public artifacts. (#69219) Thanks @zeroaltitude.
- Plugins: keep only the highest-precedence manifest when distinct discovered plugins share an id, so lower-precedence global or workspace duplicates no longer load beside bundled or config-selected plugins. (#41626) Thanks @Tortes.
- fix(security): block MINIMAX_API_HOST workspace env injection and remove env-driven URL routing [AI-assisted]. (#67300) Thanks @pgondhi987.
- Cron/delivery: treat explicit
delivery.mode: "none"runs as not requested even if the runner reportsdelivered: false, so no-delivery cron jobs no longer persist false delivery failures or errors. (#69285) Thanks @matsuri1987. - Plugins/install: repair active and default-enabled bundled plugin runtime dependencies before import in packaged installs, so bundled Discord, WhatsApp, Slack, Telegram, and provider plugins work without putting their dependency trees in core.
- BlueBubbles: raise the outbound
/api/v1/message/textsend timeout default from 10s to 30s, and add a configurablechannels.bluebubbles.sendTimeoutMs(also per-account) so macOS 26 setups where Private API iMessage sends stall for 60+ seconds no longer silently lose messages at the 10s abort. Probes, chat lookups, and health checks keep the shorter 10s default. Fixes #67486. (#69193) Thanks @omarshahine. - Agents/bootstrap: budget truncation markers against per-file caps, preserve source content instead of silently wasting bootstrap bytes, and avoid marker-only output in tiny-budget truncation cases. (#69114) Thanks @BKF-Gitty.
- Context engine/plugins: stop rejecting third-party context engines whose
info.iddiffers from the registered plugin slot id. The strict-match contract added in 2026.4.14 brokelossless-clawand other plugins whose internal engine id does not equal the slot id they are registered under, producing repeatedinfo.id must match registered idlane failures on every turn. Fixes #66601. (#66678) Thanks @GodsBoy. - Agents/compaction: rename embedded Pi compaction lifecycle events to
compaction_start/compaction_endso OpenClaw stays aligned withpi-coding-agent0.66.1 event naming. (#67713) Thanks @mpz4life. - Security/dotenv: block all
OPENCLAW_*keys from untrusted workspace.envfiles so workspace-local env loading fails closed for new runtime-control variables instead of silently inheriting them. (#473) - Gateway/device pairing: restrict non-admin paired-device sessions (device-token auth) to their own pairing list, approve, and reject actions so a paired device cannot enumerate other devices or approve/reject pairing requests authored by another device. Admin and shared-secret operator sessions retain full visibility. (#69375) Thanks @eleqtrizit.
- Agents/gateway tool: extend the agent-facing
gatewaytool's config mutation guard so model-drivenconfig.patchandconfig.applycannot rewrite operator-trusted paths (sandbox, plugin trust, gateway auth/TLS, hook routing and tokens, SSRF policy, MCP servers, workspace filesystem hardening) and cannot bypass the guard by editing per-agent sandbox, tools, or embedded-Pi overrides in place underagents.list[]. (#69377) Thanks @eleqtrizit. - Gateway/websocket broadcasts: require
operator.read(or higher) for chat, agent, and tool-result event frames so pairing-scoped and node-role sessions no longer passively receive session chat content, and scope-gate unknown broadcast events by default. Plugin-definedplugin.*broadcasts are scoped to operator.write/admin, and status/transport events (heartbeat,presence,tick, etc.) remain unrestricted. Per-client sequence numbers preserve per-connection monotonicity. (#69373) Thanks @eleqtrizit. - Agents/compaction: always reload embedded Pi resources through an explicit loader and reapply reserve-token overrides so runs without extension factories no longer silently lose compaction settings before session start. (#67146) Thanks @ly85206559.
- Memory-core/dreaming: normalize sweep timestamps and reuse hashed narrative session keys for fallback cleanup so Dreaming narrative sub-sessions stop leaking. (#67023) Thanks @chiyouYCH.
- Gateway/startup: delay HTTP bind until websocket handlers are attached, so immediate post-startup websocket health/connect probes no longer hit the startup race window. (#43392) Thanks @dalefrieswthat.
- Codex/app-server: release the session lane when a downstream consumer throws while draining the
turn/completednotification, so follow-up messages after a Codex plugin reply stop queueing behind a stale lane lock. Fixes #67996. (#69072) Thanks @ayeshakhalid192007-dev. - Codex/app-server: default approval handling to
on-requestso Codex harness sessions do not start with overly permissive tool approvals. (#68721) Thanks @Lucenx9. - Cron/delivery: keep isolated cron chat delivery tools available, resolve
channel: "last"targets from the gateway, show delivery previews incron list/show, and avoid duplicate fallback sends after direct message-tool delivery. (#69587) Thanks @obviyus. - Cron/Telegram: key isolated direct-delivery dedupe to each cron execution instead of the reused session id, so recurring Telegram announce runs no longer report delivered while silently skipping later sends. (#69000) Thanks @obviyus.
- Models/Kimi: default bundled Kimi thinking to off and normalize Anthropic-compatible
thinkingpayloads so stale session/thinkstate no longer silently re-enables reasoning on Kimi runs. (#68907) Thanks @frankekn. - Control UI/cron: keep the runtime-only
lastdelivery sentinel from being materialized into persisted cron delivery and failure-alert channel configs when jobs are created or edited. (#68829) Thanks @tianhaocui. - OpenAI/Responses: strip orphaned reasoning blocks before outbound Responses API calls so compacted or restored histories no longer fail on standalone reasoning items. (#55787) Thanks @suboss87.
- Cron/CLI: parse PowerShell-style
--toolsallow-lists the same way as comma-separated input, socron addandcron editno longer persistexec read writeas one combined tool entry on Windows. (#68858) Thanks @chen-zhang-cs-code. - Browser/user-profile: let existing-session
profile="user"tool calls auto-route to a connected browser node or use explicittarget="node", while still honoring explicittarget="host"pinning. (#48677) - Discord/slash commands: tolerate partial Discord channel metadata in slash-command and model-picker flows so partial channel objects no longer crash when channel names, topics, or thread parent metadata are unavailable. (#68953) Thanks @dutifulbob.
- BlueBubbles: consolidate outbound HTTP through a typed
BlueBubblesClientthat resolves the SSRF policy once at construction so image attachments stop getting blocked on localhost and reactions stop getting blocked on private-IP BB deployments. Fixes #34749 and #59722. (#68234) Thanks @omarshahine. - Cron/gateway: reject ambiguous announce delivery config at add/update time so invalid multi-channel or target-id provider settings fail early instead of persisting broken cron jobs. (#69015) Thanks @obviyus.
- Cron/main-session delivery: preserve
heartbeat.target="last"through deferred wake queuing, gateway wake forwarding, and same-target wake coalescing so queued cron replies still return to the last active chat. (#69021) Thanks @obviyus. - Cron/gateway: ignore disabled channels when announce delivery ambiguity is checked, and validate main-session delivery patches against the live cron service default agent so hot-reloaded agent config does not falsely reject valid updates. (#69040) Thanks @obviyus.
- Matrix/allowlists: hot-reload
dm.allowFromandgroupAllowFromentries on inbound messages while keeping config removals authoritative, so Matrix allowlist changes no longer require a channel restart to add or revoke a sender. (#68546) Thanks @johnlanni. - BlueBubbles: always set
methodexplicitly on outbound text sends ("private-api"when available,"apple-script"otherwise), and prefer Private API on macOS 26 even for plain text. Fixes silent delivery failure on macOS setups without Private API where an omittedmethodlet BB Server fall back to version-dependent default behavior that silently drops the message (#64480), and the AppleScript-1700error on macOS 26 Tahoe plain text sends (#53159). (#69070) Thanks @xqing3. - Matrix/commands: recognize slash commands that are prefixed with the bot's Matrix mention, so room messages like
@bot:server /newtrigger the command path without requiring custom mention regexes. (#68570) Thanks @nightq and @johnlanni. - Gateway/pairing: return reason-specific
PAIRING_REQUIREDdetails, remediation hints, and request ids so unapproved-device and scope-upgrade failures surface actionable recovery guidance in the CLI and Control UI. (#69227) Thanks @obviyus. - Agents/subagents: include requested role and runtime timing on subagent failure payloads so parent agents can correlate failed or timed-out child work. (#68726) Thanks @BKF-Gitty.
- Gateway/sessions: reject stale agent-scoped sessions after an agent is removed from config while preserving legacy default-agent main-session aliases. (#65986) Thanks @bittoby.
- Doctor/gateway: surface pending device pairing requests, scope-upgrade approval drift, and stale device-token mismatch repair steps so
openclaw doctor --fixno longer leaves pairing/auth setup failures unexplained. (#69210) Thanks @obviyus. - Cron/isolated-agent: preserve explicit
delivery.mode: "none"message targets for isolated runs without inheriting implicitlastrouting, so agent-initiated Telegram sends keep their authored destination while baremode:nonejobs stay targetless. (#69153) Thanks @obviyus. - Cron/isolated-agent: keep
delivery.mode: "none"account-only or thread-only configs from inheriting a stale implicit recipient, so isolated runs only resolve message routing when the job authored an explicittotarget. (#69163) Thanks @obviyus. - Gateway/TUI: retry session history while the local gateway is still finishing startup, so
openclaw tuireconnects no longer fail on transientchat.history unavailable during gateway startuperrors. (#69164) Thanks @shakkernerd. - BlueBubbles/reactions: fall back to
lovewhen an agent reacts with an emoji outside the iMessage tapback set (love/like/dislike/laugh/emphasize/question), so wider-vocabulary model reactions like👀still produce a visible tapback instead of failing the whole reaction request. Configured ack reactions still validate strictly via the newnormalizeBlueBubblesReactionInputStrictpath. (#64693) Thanks @zqchris. - BlueBubbles: prefer iMessage over SMS when both chats exist for the same handle, honor explicit
sms:targets, and never silently downgrade iMessage-available recipients. (#61781) Thanks @rmartin. - Telegram/setup: require numeric
allowFromuser IDs during setup instead of offering unsupported@usernameDM resolution, and point operators tofrom.id/getUpdatesfor discovery. (#69191) Thanks @obviyus. - GitHub Copilot/onboarding: default GitHub Copilot setup to
claude-opus-4.6and keep the bundled default model list aligned, so new Copilot setups no longer start on the oldergpt-4odefault. (#69207) Thanks @obviyus. - Gateway/status: separate reachability, capability, and read-probe reporting so connect-only or scope-limited sessions no longer look fully healthy, and normalize SSH targets entered as
ssh user@host. (#69215) Thanks @obviyus. - Slack: fix outbound replies failing with "unresolved SecretRef" for accounts configured via
fileorexecsecret sources; the send path now tolerates the runtime snapshot retaining an unresolved channel SecretRef when a boot-resolved token override is already available. (#68954) Thanks @openperf. - Control UI/device pairing: explain scope and role approval upgrades during reconnects, and show requested versus approved access in the Control UI and
openclaw devicesso broader reconnects no longer look like lost pairings. (#69221) Thanks @obviyus. - Gateway/Control UI: surface pending scope, role, and device-metadata pairing approvals in auth errors and Control UI hints so broader reconnects no longer look like random auth breakage. (#69226) Thanks @obviyus.