Summary
cleanupBrowserSessionsForLifecycleEnd() is only called from two places in runtime code:
src/agents/subagent-registry-lifecycle.ts:611 — subagent completion
src/gateway/server-cron.ts:305 — cron-isolated agent turn completion
Primary agents' interactive (channel/paired) sessions have no corresponding call. Tabs opened during normal agent-user chat are tracked in the session-tab registry but never closed until the agent process or browser container is restarted externally.
In practice this means a tab with a hot JS loop (setInterval, WS reconnect, animation frame, etc.) pegs CPU indefinitely.
Evidence
On a production gateway we observed a renderer process at 31.5% CPU for ~47 hours inside an openclaw-sbx-browser-agent-* container. The container sessionKey label was agent:<agent-id>, and the agent process had been running continuously since the browser was first used. Restarting the container (docker restart) reclaimed the CPU immediately; the agent reopened pages on next use without issue.
Two browser containers on the same host had been up for 24h+ / 47h+ respectively.
Expected
Primary-agent sessions should participate in some form of tab lifecycle. Options (any or a combination):
- Idle timeout per tab — close tabs with no navigation/interaction for N minutes (config-driven).
- Periodic tab GC — on a timer, close tabs older than N minutes from primary sessions (same mechanism subagents/cron already have at
cleanupBrowserSessionsForLifecycleEnd, just timer-triggered).
- Per-session tab cap — enforce a max open-tab count per agent, closing LRU tabs when exceeded.
No strong opinion on which; (2) is probably the smallest change given the infrastructure already exists.
Actual
Zero cleanup. Tabs persist for the lifetime of the agent process (days/weeks in practice). Stuck-JS tabs silently burn CPU until something external kills them.
Workaround
Operators can add a nightly cron to docker restart openclaw-sbx-browser-agent-* containers. This works but is blunt — it also closes healthy tabs that would otherwise be reused.
Related
src/browser-lifecycle-cleanup.ts — the cleanup entrypoint; only the two call sites above exercise it
src/plugin-sdk/browser-maintenance.ts → session-tab-registry.ts — the tab tracking infrastructure that already distinguishes per-session ownership
Summary
cleanupBrowserSessionsForLifecycleEnd()is only called from two places in runtime code:src/agents/subagent-registry-lifecycle.ts:611— subagent completionsrc/gateway/server-cron.ts:305— cron-isolated agent turn completionPrimary agents' interactive (channel/paired) sessions have no corresponding call. Tabs opened during normal agent-user chat are tracked in the session-tab registry but never closed until the agent process or browser container is restarted externally.
In practice this means a tab with a hot JS loop (setInterval, WS reconnect, animation frame, etc.) pegs CPU indefinitely.
Evidence
On a production gateway we observed a renderer process at 31.5% CPU for ~47 hours inside an
openclaw-sbx-browser-agent-*container. The containersessionKeylabel wasagent:<agent-id>, and the agent process had been running continuously since the browser was first used. Restarting the container (docker restart) reclaimed the CPU immediately; the agent reopened pages on next use without issue.Two browser containers on the same host had been up for 24h+ / 47h+ respectively.
Expected
Primary-agent sessions should participate in some form of tab lifecycle. Options (any or a combination):
cleanupBrowserSessionsForLifecycleEnd, just timer-triggered).No strong opinion on which; (2) is probably the smallest change given the infrastructure already exists.
Actual
Zero cleanup. Tabs persist for the lifetime of the agent process (days/weeks in practice). Stuck-JS tabs silently burn CPU until something external kills them.
Workaround
Operators can add a nightly cron to
docker restartopenclaw-sbx-browser-agent-*containers. This works but is blunt — it also closes healthy tabs that would otherwise be reused.Related
src/browser-lifecycle-cleanup.ts— the cleanup entrypoint; only the two call sites above exercise itsrc/plugin-sdk/browser-maintenance.ts→session-tab-registry.ts— the tab tracking infrastructure that already distinguishes per-session ownership