Changes
- Highlight: External Secrets Management introduces a full
openclaw secretsworkflow (audit,configure,apply,reload) with runtime snapshot activation, strictsecrets applytarget-path validation, safer migration scrubbing, ref-only auth-profile support, and dedicated docs. (#26155) Thanks @joshavant. - ACP/Thread-bound agents: make ACP agents first-class runtimes for thread sessions with
acpspawn/send dispatch integration, acpx backend bridging, lifecycle controls, startup reconciliation, runtime cleanup, and coalesced thread replies. (#23580) thanks @osolmaz. - Agents/Routing CLI: add
openclaw agents bindings,openclaw agents bind, andopenclaw agents unbindfor account-scoped route management, including channel-only to account-scoped binding upgrades, role-aware binding identity handling, plugin-resolved binding account IDs, and optional account-binding prompts inopenclaw channels add. (#27195) thanks @gumadeiras. - Codex/WebSocket transport: make
openai-codexWebSocket-first by default (transport: "auto"with SSE fallback), keep explicit per-model/runtime transport overrides, and add regression coverage + docs for transport selection. - Onboarding/Plugins: let channel plugins own interactive onboarding flows with optional
configureInteractiveandconfigureWhenConfiguredhooks while preserving the generic fallback path. (#27191) thanks @gumadeiras. - Auth/Onboarding: add an explicit account-risk warning and confirmation gate before starting Gemini CLI OAuth, and document the caution in provider docs and the Gemini CLI auth plugin README. (#16683) Thanks @vincentkoc.
- Android/Nodes: add Android
devicecapability plusdevice.statusanddevice.infonode commands, including runtime handler wiring and protocol/registry coverage for device status/info payloads. (#27664) Thanks @obviyus. - Android/Nodes: add
notifications.listsupport on Android nodes and exposenodes notifications_listin agent tooling for listing active device notifications. (#27344) thanks @obviyus. - Docs/Contributing: add Nimrod Gutman to the maintainer roster in
CONTRIBUTING.md. (#27840) Thanks @ngutman.
Fixes
- Telegram/DM allowlist runtime inheritance: enforce
dmPolicy: "allowlist"allowFromrequirements using effective account-plus-parent config across account-capable channels (Telegram, Discord, Slack, Signal, iMessage, IRC, BlueBubbles, WhatsApp), and alignopenclaw doctorchecks to the same inheritance logic so DM traffic is not silently dropped after upgrades. (#27936) Thanks @widingmarcus-cyber. - Delivery queue/recovery backoff: prevent retry starvation by persisting
lastAttemptAton failed sends and deferring recovery retries until each entry'slastAttemptAt + backoffwindow is eligible, while continuing to recover ready entries behind deferred ones. Landed from contributor PR #27710 by @Jimmy-xuzimo. Thanks @Jimmy-xuzimo. - Gemini OAuth/Auth flow: align OAuth project discovery metadata and endpoint fallback handling for Gemini CLI auth, including fallback coverage for environment-provided project IDs. (#16684) Thanks @vincentkoc.
- Google Chat/Lifecycle: keep Google Chat
startAccountpending until abort in webhook mode so startup is no longer interpreted as immediate exit, preventing auto-restart loops and webhook-target churn. (#27384) thanks @junsuwhy. - Temp dirs/Linux umask: force
0700permissions after temp-dir creation and self-heal existing writable temp dirs before trust checks soumask 0002installs no longer crash-loop on startup. Landed from contributor PR #27860 by @stakeswky. (#27853) Thanks @stakeswky. - Nextcloud Talk/Lifecycle: keep
startAccountpending until abort and stop the webhook monitor on shutdown, preventingEADDRINUSErestart loops when the gateway manages account lifecycle. (#27897) - Microsoft Teams/File uploads: acknowledge
fileConsent/invokeimmediately (invokeResponsebefore upload + file card send) so Teams no longer shows false "Something went wrong" timeout banners while upload completion continues asynchronously; includes updated async regression coverage. Landed from contributor PR #27641 by @scz2011. - Queue/Drain/Cron reliability: harden lane draining with guaranteed
drainingflag reset on synchronous pump failures, reject new queue enqueues during gateway restart drain windows (instead of silently killing accepted tasks), add/stopqueued-backlog cutoff metadata with stale-message skipping (while avoiding cross-session native-stop cutoff bleed), and raise isolated cronagentTurnouter safety timeout to avoid false 10-minute timeout races against longer agent session timeouts. (#27407, #27332, #27427) - Typing/Main reply pipeline: always mark dispatch idle in
agent-runnerfinalization so typing cleanup runs even when dispatcheronIdledoes not fire, preventing stuck typing indicators after run completion. (#27250) Thanks @Sid-Qin. - Typing/TTL safety net: add max-duration guardrails to shared typing callbacks so stuck lifecycle edges auto-stop typing indicators even when explicit idle/cleanup signals are missed. (#27428) Thanks @Crpdim.
- Typing/Cross-channel leakage: unify run-scoped typing suppression for cross-channel/internal-webchat routes, preserve current inbound origin as embedded run message channel context, harden shared typing keepalive with consecutive-failure circuit breaker edge-case handling, and enforce dispatcher completion/idle waits in extension dispatcher callsites (Feishu, Matrix, Mattermost, MSTeams) so typing indicators always clean up on success/error paths. Related: #27647, #27493, #27598. Supersedes/replaces draft PRs: #27640, #27593, #27540.
- Telegram/sendChatAction 401 handling: add bounded exponential backoff + temporary local typing suppression after repeated unauthorized failures to stop unbounded
sendChatActionretry loops that can trigger Telegram abuse enforcement and bot deletion. (#27415) Thanks @widingmarcus-cyber. - Telegram/Webhook startup: clarify webhook config guidance, allow
channels.telegram.webhookPort: 0for ephemeral listener binding, and log both the local listener URL and Telegram-advertised webhook URL with the bound port. (#25732) thanks @huntharo. - Config/Doctor allowlist safety: reject
dmPolicy: "allowlist"configs with emptyallowFrom, add Telegram account-level inheritance-aware validation, and teachopenclaw doctor --fixto restore missingallowFromentries from pairing-store files when present, preventing silent DM drops after upgrades. (#27936) Thanks @widingmarcus-cyber. - Browser/Chrome extension handshake: bind relay WS message handling before
onopenand add non-blockingconnect.challengeresponse handling for gateway-style handshake frames, avoiding stuck…badge states when challenge frames arrive immediately on connect. Landed from contributor PR #22571 by @pandego. (#22553) - Browser/Extension relay init: dedupe concurrent same-port relay startup with shared in-flight initialization promises so callers await one startup lifecycle and receive consistent success/failure results. Landed from contributor PR #21277 by @HOYALIM. (Related #20688)
- Browser/Fill relay + CLI parity: accept
act.fillfields without explicittypeby defaulting missing/emptytypetotextin both browser relay route parsing andopenclaw browser fillCLI field parsing, so relay calls no longer fail when the model omits field type metadata. Landed from contributor PR #27662 by @Uface11. (#27296) Thanks @Uface11. - Feishu/Permission error dispatch: merge sender-name permission notices into the main inbound dispatch so one user message produces one agent turn/reply (instead of a duplicate permission-notice turn), with regression coverage. (#27381) thanks @byungsker.
- Agents/Canvas default node resolution: when multiple connected canvas-capable nodes exist and no single
mac-*candidate is selected, default to the first connected candidate instead of failing withnode requiredfor implicit-node canvas tool calls. Landed from contributor PR #27444 by @carbaj03. Thanks @carbaj03. - TUI/stream assembly: preserve streamed text across real tool-boundary drops without keeping stale streamed text when non-text blocks appear only in the final payload. Landed from contributor PR #27711 by @scz2011. (#27674)
- Hooks/Internal
message:sent: forwardsessionKeyon outbound sends from agent delivery, cron isolated delivery, gateway receipt acks, heartbeat sends, session-maintenance warnings, and restart-sentinel recovery so internalmessage:senthooks consistently dispatch with session context, includingopenclaw agent --deliverruns resumed via--session-id(without explicit--session-key). Landed from contributor PR #27584 by @qualiobra. Thanks @qualiobra. - Pi image-token usage: stop re-injecting history image blocks each turn, process image references from the current prompt only, and prune already-answered user-image blocks in stored history to prevent runaway token growth. (#27602)
- BlueBubbles/SSRF: auto-allowlist the configured
serverUrlhostname for attachment fetches so localhost/private-IP BlueBubbles setups are no longer false-blocked by default SSRF checks. Landed from contributor PR #27648 by @lailoo. (#27599) Thanks @taylorhou for reporting. - Agents/Compaction + onboarding safety: prevent destructive double-compaction by stripping stale assistant usage around compaction boundaries, skipping post-compaction custom metadata writes in the same attempt, and cancelling safeguard compaction when there are no real conversation messages to summarize; harden workspace/bootstrap detection for memory-backed workspaces; and change
openclaw onboard --resetdefault scope toconfig+creds+sessions(workspace deletion now requires--reset-scope full). (#26458, #27314) Thanks @jaden-clovervnd, @Sid-Qin, and @widingmarcus-cyber for fix direction in #26502, #26529, and #27492. - NO_REPLY suppression: suppress
NO_REPLYbefore Slack API send and in sub-agent announce completion flow so sentinel text no longer leaks into user channels. Landed from contributor PRs #27529 (by @Sid-Qin) and #27535 (rewritten minimal landing by maintainers). (#27387, #27531) - Matrix/Group sender identity: preserve sender labels in Matrix group inbound prompt text (
BodyForAgent) for both channel and threaded messages, and align group envelopes with shared inbound sender-prefix formatting so first-person requests resolve against the current sender. (#27401) thanks @koushikxd. - Auto-reply/Streaming: suppress only exact
NO_REPLYfinal replies while still filtering streaming partial sentinel fragments (NO_,NO_RE,HEARTBEAT_...) so substantive replies ending withNO_REPLYare delivered and partial silent tokens do not leak during streaming. (#19576) Thanks @aldoeliacim. - Auto-reply/Inbound metadata: add a readable
timestampfield to conversation info and ignore invalid/out-of-range timestamp values so prompt assembly never crashes on malformed timestamp inputs. (#17017) thanks @liuy. - Typing/Run completion race: prevent post-run keepalive ticks from re-triggering typing callbacks by guarding
triggerTyping()withrunComplete, with regression coverage for no-restart behavior during run-complete/dispatch-idle boundaries. (#27413) Thanks @widingmarcus-cyber. - Typing/Dispatch idle: force typing cleanup when
markDispatchIdlenever arrives after run completion, avoiding leaked typing keepalive loops in cron/announce edges. Landed from contributor PR #27541 by @Sid-Qin. (#27493) - Telegram/Inline buttons: allow callback-query button handling in groups (including
/modelsfollow-up buttons) when group policy authorizes the sender, by removing the redundant callback allowlist gate that blocked open-policy groups. (#27343) Thanks @GodsBoy. - Telegram/Streaming preview: when finalizing without an existing preview message, prime pending preview text with final answer before stop-flush so users do not briefly see stale 1-2 word fragments (for example
nobeforeno problem). (#27449) Thanks @emanuelst for the original fix direction in #19673. - Browser/Extension relay CORS: handle
/json*OPTIONSpreflight before auth checks, allow Chrome extension origins, and return extension-origin CORS headers on relay HTTP responses so extension token validation no longer fails cross-origin. Landed from contributor PR #23962 by @miloudbelarebia. (#23842) - Browser/Extension relay auth: allow
?token=query-param auth on relay/json*endpoints (consistent with relay WebSocket auth) so curl/devtools-style/json/versionand/json/listprobes work without requiring custom headers. Landed from contributor PR #26015 by @Sid-Qin. (#25928) - Browser/Extension relay shutdown: flush pending extension-request timers/rejections during relay
stop()before socket/server teardown so in-flight extension waits do not survive shutdown windows. Landed from contributor PR #24142 by @kevinWangSheng. - Browser/Extension relay reconnect resilience: keep CDP clients alive across brief MV3 extension disconnect windows, wait briefly for extension reconnect before failing in-flight CDP commands, and only tear down relay target/client state after reconnect grace expires. Landed from contributor PR #27617 by @davidemanuelDEV.
- Browser/Route decode hardening: guard malformed percent-encoding in relay target action routes and browser route-param decoding so crafted
%paths return400instead of crashing/unhandled URI decode failures. Landed from contributor PR #11880 by @Yida-Dev. - Feishu/Inbound message metadata: include inbound
message_idinBodyForAgenton a dedicated metadata line so agents can reliably correlate and act on media/message operations that require message IDs, with regression coverage. (#27253) thanks @xss925175263. - Feishu/Doc tools: route
feishu_docandfeishu_app_scopesthrough the active agent account context (with explicitaccountIdoverride support) so multi-account agents no longer default to the first configured app, with regression coverage for context routing and explicit override behavior. (#27338) thanks @AaronL725. - LINE/Inline directives auth: gate directive parsing (
/model,/think,/verbose,/reasoning,/queue) on resolved authorization (command.isAuthorizedSender) socommands.allowFrom-authorized LINE senders are not silently stripped when rawCommandAuthorizedis unset. Landed from contributor PR #27248 by @kevinWangSheng. (#27240) - Onboarding/Gateway: seed default Control UI
allowedOriginsfor non-loopback binds during onboarding (localhost/127.0.0.1plus custom bind host) so fresh non-loopback setups do not fail startup due to missing origin policy. (#26157) thanks @stakeswky. - Docker/GCP onboarding: reduce first-build OOM risk by capping Node heap during
pnpm install, reuse existing gateway token duringdocker-setup.shreruns so.envstays aligned with config, auto-bootstrap Control UI allowed origins for non-loopback Docker binds, and add GCP docs guidance for tokenized dashboard links + pairing recovery commands. (#26253) Thanks @pandego. - CLI/Gateway
--forcein non-root Docker: recover fromlsofpermission failures (EACCES/EPERM) by falling back tofuserkill + probe-based port checks, soopenclaw gateway --forceworks for default containernodeuser flows. (#27941) - Gateway/Bind visibility: emit a startup warning when binding to non-loopback addresses so operators get explicit exposure guidance in runtime logs. (#25397) thanks @let5sne.
- Sessions cleanup/Doctor: add
openclaw sessions cleanup --fix-missingto prune store entries whose transcript files are missing, including doctor guidance and CLI coverage. Landed from contributor PR #27508 by @Sid-Qin. (#27422) - Doctor/State integrity: ignore metadata-only slash routing sessions when checking recent missing transcripts so
openclaw doctorno longer reports false-positive transcript-missing warnings for*:slash:*keys. (#27375) thanks @gumadeiras. - CLI/Gateway status: force local
gateway statusprobe host to127.0.0.1forbind=lanso co-located probes do not trip non-loopback plaintext WebSocket checks. (#26997) thanks @chikko80. - CLI/Gateway auth: align
gateway run --authparsing/help text with supported gateway auth modes by acceptingnoneandtrusted-proxy(in addition totoken/password) for CLI overrides. (#27469) thanks @s1korrrr. - CLI/Daemon status TLS probe: use
wss://and forward local TLS certificate fingerprint for TLS-enabled gateway daemon probes soopenclaw daemon statusworks withgateway.bind=lan+gateway.tls.enabled=true. (#24234) thanks @liuy. - Podman/Default bind: change
run-openclaw-podman.shdefault gateway bind fromlantoloopbackand document explicit LAN opt-in with Control UI origin configuration. (#27491) thanks @robbyczgw-cla. - Daemon/macOS launchd: forward proxy env vars into supervised service environments, keep LaunchAgent
KeepAlive=truesemantics, and harden restart sequencing toprint -> bootout -> wait old pid exit -> bootstrap -> kickstart. (#27276) thanks @frankekn. - Gateway/macOS restart-loop hardening: detect OpenClaw-managed supervisor markers during SIGUSR1 restart handoff, clean stale gateway PIDs before
/restartlaunchctl/systemctl triggers, and set LaunchAgentThrottleInterval=60to bound launchd retry storms during lock-release races. Landed from contributor PRs #27655 (@taw0002), #27448 (@Sid-Qin), and #27650 (@kevinWangSheng). (#27605, #27590, #26904, #26736) - Models/MiniMax auth header defaults: set
authHeader: truefor both onboarding-generated MiniMax API providers and implicit built-in MiniMax (minimax,minimax-portal) provider templates so first requests no longer fail with MiniMax401 authentication_errordue to missingAuthorizationheader. Landed from contributor PRs #27622 by @riccoyuanft and #27631 by @kevinWangSheng. (#27600, #15303) - Models/Google Antigravity IDs: normalize bare
gemini-3-pro,gemini-3.1-pro, andgemini-3-1-promodel IDs to the default-lowthinking tier so provider requests no longer fail with 404 when the tier suffix is omitted. (#24145) Thanks @byungsker. - Auth/Auth profiles: normalize
auth-profiles.jsonalias fields (mode -> type,apiKey -> key) before credential validation so entries copied fromopenclaw.jsonauth examples are no longer silently dropped. (#26950) thanks @byungsker. - Models/Google Gemini: treat
google(Gemini API key auth profile) as a reasoning-tag provider to prevent<think>leakage, and add forward-compat model fallback forgoogle-gemini-cligemini-3.1-pro*/gemini-3.1-flash*IDs to avoid false unknown-model errors. (#26551, #26524) Thanks @byungsker. - Models/Profile suffix parsing: centralize trailing
@profileparsing and only treat@as a profile separator when it appears after the final/, preserving model IDs likeopenai/@cf/...andopenrouter/@preset/...across/modeldirective parsing and allowlist model resolution, with regression coverage. - Models/OpenAI Codex config schema parity: accept
openai-codex-responsesin the config model API schema and TypeScriptModelApiunion, with regression coverage for config validation. Landed from contributor PR #27501 by @AytuncYildizli. Thanks @AytuncYildizli. - Agents/Models config: preserve agent-level provider
apiKeyandbaseUrlduring merge-modemodels.jsonupdates when agent values are present. (#27293) thanks @Sid-Qin. - Azure OpenAI Responses: force
store=trueforazure-openai-responsesdirect responses API calls to avoid multi-turn 400 failures. Landed from contributor PR #27499 by @polarbear-Yang. (#27497) - Security/Node exec approvals: require structured
commandArgvapprovals forhost=node, enforce versionedsystemRunBindingV1matching for argv/cwd/session/agent/env context with fail-closed behavior on missing/mismatched bindings, and addGIT_EXTERNAL_DIFFto blocked host env keys. This ships in the next npm release (2026.2.26). Thanks @tdjackey for reporting. - Security/Plugin channel HTTP auth: normalize protected
/api/channelspath checks against canonicalized request paths (case + percent-decoding + slash normalization), resolve encoded dot-segment traversal variants, and fail closed on malformed%-encoded channel prefixes so alternate-path variants cannot bypass gateway auth. This ships in the next npm release (2026.2.26). Thanks @zpbrent for reporting. - Security/Gateway node pairing: pin paired-device
platform/deviceFamilymetadata across reconnects and bind those fields into device-auth signatures, so reconnect metadata spoofing cannot expand node command allowlists without explicit repair pairing. This ships in the next npm release (2026.2.26). Thanks @76embiid21 for reporting. - Security/Sandbox path alias guard: reject broken symlink targets by resolving through existing ancestors and failing closed on out-of-root targets, preventing workspace-only
apply_patchwrites from escaping sandbox/workspace boundaries via dangling symlinks. This ships in the next npm release (2026.2.26). Thanks @tdjackey for reporting. - Security/Workspace FS boundary aliases: harden canonical boundary resolution for non-existent-leaf symlink aliases while preserving valid in-root aliases, preventing first-write workspace escapes via out-of-root symlink targets. This ships in the next npm release (
2026.2.26). Thanks @tdjackey for reporting. - Security/Config includes: harden
$includefile loading with verified-open reads, reject hardlinked include aliases, and enforce include file-size guardrails so config include resolution remains bounded to trusted in-root files. This ships in the next npm release (2026.2.26). Thanks @zpbrent for reporting. - Security/Node exec approvals hardening: freeze immutable approval-time execution plans (
argv/cwd/agentId/sessionKey) viasystem.run.prepare, enforce those canonical plan values during approval forwarding/execution, and reject mutable parent-symlink cwd paths during approval-plan building to prevent approval bypass via symlink rebind. This ships in the next npm release (2026.2.26). Thanks @tdjackey for reporting. - Security/Microsoft Teams media fetch: route Graph message/hosted-content/attachment fetches and auth-scope fallback attachment downloads through shared SSRF-guarded fetch paths, and centralize hostname-suffix allowlist policy helpers in the plugin SDK to remove channel/plugin drift. This ships in the next npm release (
2026.2.26). Thanks @tdjackey for reporting. - Security/Voice Call (Twilio): bind webhook replay + manager dedupe identity to authenticated request material, remove unsigned
i-twilio-idempotency-tokentrust from replay/dedupe keys, and thread verified request identity through provider parse flow to harden cross-provider event dedupe. This ships in the next npm release (2026.2.26). Thanks @tdjackey for reporting. - Security/Exec approvals forwarding: prefer turn-source channel/account/thread metadata when resolving approval delivery targets so stale session routes do not misroute approval prompts.
- Security/Pairing multi-account isolation: enforce account-scoped pairing allowlists and pending-request storage across core + extension message channels while preserving channel-scoped defaults for the default account. This ships in the next npm release (
2026.2.26). Thanks @tdjackey for reporting and @gumadeiras for implementation. - Config/Plugins entries: treat unknown
plugins.entries.*ids as startup warnings (ignored stale keys) instead of hard validation failures that can crash-loop gateway boot. Landed from contributor PR #27506 by @Sid-Qin. (#27455) - Telegram native commands: degrade command registration on
BOT_COMMANDS_TOO_MUCHby retrying with fewer commands instead of crash-looping startup sync. Landed from contributor PR #27512 by @Sid-Qin. (#27456) - Web tools/Proxy: route
web_searchprovider HTTP calls (Brave, Perplexity, xAI, Gemini, Kimi), redirect resolution, andweb_fetchthrough a shared proxy-aware SSRF guard path so gateway installs behindHTTP_PROXY/HTTPS_PROXY/ALL_PROXYno longer fail with transportfetch failederrors. (#27430) thanks @kevinWangSheng. - Android/Node invoke: remove native gateway WebSocket
Originheader to avoid false origin rejections, unify invoke command registry/policy/error parsing paths, and keep command availability checks centralized to reduce dispatcher/advertisement drift. (#27257) Thanks @obviyus. - Gateway shared-auth scopes: preserve requested operator scopes for shared-token clients when device identity is unavailable, instead of clearing scopes during auth handling. Landed from contributor PR #27498 by @kevinWangSheng. (#27494)
- Cron/Hooks isolated routing: preserve canonical
agent:*session keys in isolated runs so already-qualified keys are not double-prefixed (for exampleagent:main:mainno longer becomesagent:main:agent:main:main). Landed from contributor PR #27333 by @MaheshBhushan. (#27289, #27282) - Channels/Multi-account config: when adding a non-default channel account to a single-account top-level channel setup, move existing account-scoped top-level single-account values into
channels.<channel>.accounts.defaultbefore writing the new account so the original account keeps working without duplicated account values at channel root;openclaw doctor --fixnow repairs previously mixed channel account shapes the same way. (#27334) thanks @gumadeiras. - iOS/Talk mode: stop injecting the voice directive hint into iOS Talk prompts and remove the Voice Directive Hint setting, reducing model bias toward tool-style TTS directives and keeping relay responses text-first by default. (#27543) thanks @ngutman.
- CI/Windows: shard the Windows
checks-windowstest lane into two matrix jobs and honor explicit shard index overrides inscripts/test-parallel.mjsto reduce CI critical-path wall time. (#27234) Thanks @joshavant.