Skip to content

[Bug] Default parallelism 24 eagerly spawns large Codex ACP pools, consuming ~14 GB and flooding Recents #2631

Description

@BrianSeong99

Summary

Buzz Desktop 0.4.23 defaults every managed local agent to parallelism: 24 and manual agent starts eagerly initialize the full pool. With Codex ACP, each worker is a multi-process adapter/app-server chain, so a few agents can create hundreds of idle processes, consume double-digit GiB of RAM, and populate Codex Recents with [Base] You are operating inside the Buzz platform... sessions.

This initially looked like an orphan cleanup leak, but controlled shutdown and source inspection show that cleanup works. The problem is the default pool size plus eager manual startup.

Environment

  • Buzz Desktop: 0.4.23
  • macOS: 26.5.2 (25F84)
  • Architecture: arm64
  • Hardware: Apple M4 Max
  • Agent runtime: bundled @agentclientprotocol/codex-acp
  • Model: gpt-5.6-sol

Reproduction

  1. Create three local Codex-backed agents using the default parallelism.
  2. Create one additional local agent with parallelism set to 1.
  3. Start all four agents from Buzz Desktop.
  4. Inspect the Buzz-owned process tree and local Codex Recents/state.

Actual behavior

The four agents were configured as 24 + 24 + 24 + 1 = 73 worker slots.

A live process snapshot showed:

  • 4 buzz-acp roots owned by buzz-desktop
  • approximately 220 codex-acp / Codex app-server descendants
  • 226 total Buzz-related processes
  • 14,359.8 MiB combined RSS
  • approximately 0% combined CPU while idle

The process count matches the configuration: 73 worker slots, with roughly three OS processes per Codex ACP worker.

The local Codex state database also contained 40 visible threads titled [Base] You are operating inside the Buzz platform...:

  • all 40 had has_user_event = 0
  • 17,721,356 cumulative tokens were recorded across those threads
  • threads were created across repeated Buzz agent starts over three days

The token field is reported as supporting evidence of substantial session activity; actual billed usage may differ due to caching/accounting semantics.

Quitting Buzz gracefully removed all 226 processes. Reopening Buzz without starting agents produced one buzz-desktop process at approximately 146 MiB. This confirms the process-tree shutdown path works and this is not an orphan-process report.

Source-level cause

At tag v0.4.23:

  • desktop/src-tauri/src/managed_agents/types.rs sets DEFAULT_AGENT_PARALLELISM to 24.
  • desktop/src-tauri/src/managed_agents/runtime.rs exports that value as BUZZ_ACP_AGENTS.
  • start_managed_agent_process calls spawn_agent_child(..., false, ...), disabling lazy-pool startup for the manual start path.
  • crates/buzz-acp/src/lib.rs immediately calls initialize_agent_pool(...) when lazy_pool is false.
  • In contrast, launch-time restore already uses spawn_agent_child(..., true, ...), with a comment explaining that eager restore would create “N idle brains.”

Relevant code:

Expected behavior

Starting a normally configured local agent should not eagerly allocate 24 model-adapter workers or create user-visible Codex sessions before work arrives.

Suggested fix

  1. Change the desktop default parallelism from 24 to 1.
  2. Use lazy-pool startup for manual starts, matching launch-time restore.
  3. Avoid creating visible Codex Recents entries for idle ACP workers, or archive/reuse them as internal sessions.
  4. Make higher parallelism an explicit advanced setting with a clear resource-cost warning.
  5. Add a regression test proving that manual start with default settings does not spawn the full worker pool until the first event arrives.

Even if parallelism 24 remains available for high-throughput deployments, it is unsafe as the default for a desktop installation using Codex ACP.

Activity

  1. added a commit that references this issue on Jul 24, 2026
    ce8372b
  2. moneyteamameen commented on Jul 27, 2026

    @moneyteamameen

    Corroborating datapoint from a different runtime: same mechanism with claude-agent-acp on macOS.

    Environment

    • Buzz Desktop 0.4.26, macOS (Darwin 25.5.0), arm64
    • Agent runtime: bundled @agentclientprotocol/claude-agent-acp v0.62.0 (Application Support node-tools)
    • 3 managed Claude agents, all defaulted to parallelism: 24, idle_timeout_seconds: null, started manually

    Observed

    • 3 buzz-acp roots owned by buzz-desktop, each with exactly 24 claude-agent-acp node children = 72 processes
    • ~3.1 GB combined RSS, ~0% combined CPU while idle
    • Process count matches config exactly: agents × parallelism, one node process per worker slot

    Confirmations

    • managed-agents.json had "parallelism": 24 on every agent entry (never set by the user)
    • Graceful quit reclaimed everything, consistent with the report that this is pool sizing + eager init, not an orphan-cleanup leak
    • Workaround verified: setting "parallelism": 1 per agent in managed-agents.json (with Buzz quit) persists across relaunch

    So the mechanism is runtime-agnostic: with claude-agent-acp it is ~1 process / ~43 MB per worker slot rather than Codex's ~3 processes per slot, but the multiplier is the same 24 × agents default.

  3. ami230392 commented on Jul 30, 2026

    @ami230392

    Additional data point on macOS (Intel, 8 GB), with what looks like a distinct root cause worth separating from the "default is 24" framing: the UI-set parallelism is persisted to a different field than the one the running pool uses.

    Environment

    • Buzz Desktop: 0.5.2 (also observed on 0.5.0)
    • macOS 14.8.7, Intel Core i5-8210Y, 8 GB RAM
    • Runtime: bundled claude-agent-acp (preferred_runtime: "claude")
    • 4 unique agents, 8 registered entries

    Symptom

    24 idle claude-agent-acp processes, ~33 MB each, ~790 MB total:

    buzz-desktop → buzz-acp → 24 × node .../Buzz/node-tools/bin/claude-agent-acp
    

    All 24 share one parent, are identical in RSS, spawned within a ~10 second window, and sit at 0.0% CPU. On an 8 GB machine this is ~10% of total RAM held by agents that are not in use. Combined with swap pressure it drove sustained CPU throttling (pmset -g therm showed CPU_Speed_Limit = 36–47 for extended periods).

    The part that seems new: two fields, only one is honoured

    Reducing parallelism in the UI appears to succeed — it persists — but has no effect on the running pool. From ~/Library/Application Support/xyz.block.buzz.app/agents/managed-agents.json:

    [0] brain-hermes   parallelism=10   definition_parallelism=1      pubkey=none   last_started_at=None
    [1] Bumble         parallelism=10   definition_parallelism=None   pubkey=none   last_started_at=None
    [2] Fizz           parallelism=10   definition_parallelism=2      pubkey=none   last_started_at=None
    [3] Honey          parallelism=10   definition_parallelism=None   pubkey=none   last_started_at=None
    [4] brain-hermes   parallelism=10   definition_parallelism=None   pubkey=set    last_started_at=2026-07-30
    [5] Bumble         parallelism=24   definition_parallelism=None   pubkey=set    team_id=builtin-team:welcome
    [6] Fizz           parallelism=24   definition_parallelism=None   pubkey=set    team_id=builtin-team:welcome
    [7] Honey          parallelism=24   definition_parallelism=None   pubkey=set    team_id=builtin-team:welcome
    

    The UI edits (parallelism 1 and 2) landed in definition_parallelism on entries [0] and [2]. Those entries have no pubkey and last_started_at: None — they are unregistered local drafts that never run. The entries that actually run are [4]–[7], and their effective parallelism remains 10 / 24 with definition_parallelism: None.

    Net effect from a user's perspective: you set parallelism to 1, the UI accepts it, and 24 processes keep running. Repeating the change and restarting the app does not help, because the edit is being written to a record that is never started.

    Two secondary observations

    1. builtin-team:welcome agents default to 24. Entries [5]–[7] are the shipped welcome-team agents and carry parallelism: 24, while the user-created records carry 10. Users who never intentionally created these still pay for a 24-worker pool each. Two of them (Bumble, Honey) had last_started_at 7 days old and were still holding live processes.

    2. idle_timeout_seconds: None on all 8 entries. With no idle eviction, a pool spun up once is held for the lifetime of the worker regardless of use. This compounds [Bug] Per-channel ACP sessions are never released: on Windows each live session pins a full agent process tree (~33 procs / ~2 GB), exhausting the commit limit until Windows kills the WebView2 host and the desktop silently renders black #2961 — nothing reclaims workers even when an agent has been untouched for days.

    Suggested fixes, in order of impact

    1. Apply definition_parallelism to the running pool, or surface a clear "restart required / not applied" state so the setting is not silently ignored
    2. Lower the default from 24 to something like 2, particularly for builtin-team:welcome agents
    3. Spawn workers lazily on first use rather than eagerly at agent start
    4. Give idle_timeout_seconds a non-null default so idle pools shrink

    Happy to provide further output from a specific machine state if useful.

  4. eiq-lucky commented on Oct 28, 2026

    @eiq-lucky

    Still reproduces on Buzz Desktop 0.5.28 (macOS 27, Apple silicon, claude-agent-acp and codex-acp). A specific part of it: an agent started with Stop/Start on its card never releases idle sessions, while the same agent started at Desktop launch does.

    Observed (live process env of each buzz-acp):

    How the agent was started BUZZ_ACP_LAZY_POOL BUZZ_ACP_IDLE_POOL_SLEEP Result
    Desktop launch (restore) true 900 pool sleeps after 15 idle min
    Stop, then Start on the agent card false 0 every thread session stays resident until Desktop is relaunched

    Three agents restarted from their cards held 52 idle sessions (~14 GB) after a few hours and pushed a 36 GB machine into swap. Relaunching Desktop brought all of them back lazy (true / 900) and memory dropped to ~3 GB.

    Code path (source at 6861e18):

    • Card Start: commands/agents.rs:307 -> start_managed_agent_process (managed_agents/runtime.rs:904), which calls spawn_agent_child(..., false, ...), i.e. lazy = false.
    • runtime.rs:615 then sets BUZZ_ACP_LAZY_POOL=false, and agent_env.rs idle_pool_sleep_env(false) returns "0", so idle re-sleep is disabled.
    • Launch restore and restart_managed_agent_runtime go through start_pair(..., true, ...) (runtime_commands.rs) and are lazy.

    Expected: the card's Start uses the same lazy start as launch restore (or at least keeps the idle pool sleep), so the start path doesn't change the memory lifetime of an agent.

    Workaround: never use Stop/Start on the card; quit and reopen Desktop instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions