claude-code - 💡(How to fix) Fix Agent tool's foreground/sync dispatch silently removed and replaced with always-fork mode via undocumented Statsig rollout [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#54595Fetched 2026-04-30 06:41:20
View on GitHub
Comments
1
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
labeled ×2commented ×1

The Agent tool's behavioral contract has changed substantially in a way that is not reflected in the changelog, the sub-agents docs, or the environment-variables docs:

  1. The run_in_background parameter has been removed from the rendered Agent tool schema.
  2. The default dispatch is now asynchronous: every Agent call returns immediately with Async agent launched successfully, regardless of whether subagent_type is specified. There is no longer a way to launch an agent and synchronously wait for its result. The previous foreground-by-default behavior is gone.
  3. A new fork capability is exposed: calling Agent without a subagent_type creates a subagent that inherits the parent's full conversation context (system prompt, history, tool results) rather than starting cold. The Agent tool's description text documents this as a first-class pattern.
  4. Items 1–3 are gated by an undocumented Statsig/GrowthBook flag (tengu_copper_fox) and silently rolled out to a percentage of accounts. The flag is not documented anywhere except a third-party gist (unkn0wncode/f87295d055dd0f0e8082358a0b5cc467, updated 2026-04-27).

The only changelog entry adjacent to this rollout is v2.1.117: "Forked subagents can now be enabled on external builds by setting CLAUDE_CODE_FORK_SUBAGENT=1", which describes an opt-in env-var path. It does not mention that forks would also be flipped on for users via remote flag, that run_in_background would be removed when forks are active, or that synchronous Agent dispatch would be removed.

Root Cause

  1. Silent contract change for downstream tooling. Frameworks built on top of Claude Code's Agent tool (custom agent orchestrators, hooks, plan-mode integrations, prompt scaffolding) made design choices based on the documented synchronous-default contract. Those choices are now invisibly invalidated for users in the rollout cohort.

  2. No way to opt out. Setting CLAUDE_CODE_FORK_SUBAGENT=0 does not turn the rollout off — the env-var check is a positive gate. Users in the cohort have no documented mechanism to restore the previous behavior. (CLAUDE_CODE_DISABLE_BACKGROUND_TASKS only affects whether background-task descriptions are rendered, not whether dispatch is async.)

  3. Loss of an established capability. The synchronous Agent path was useful: it let the orchestrator block on a result and weave it back into the next turn deterministically. Replacing every Agent call with async dispatch shifts orchestration burden to the model and changes the shape of multi-step plans.

  4. Invisible cohort split. Two users on the same Claude Code version, same docs, same settings, behave differently depending on remote flag state. This makes documentation inaccurate for the rollout cohort and bug reports harder to diagnose.

  5. Pattern of undocumented behavioral changes via system-reminder / tool-description rewrite. This is the same shape as #29677 (Task→Agent rename), #31002 (built-in tools deferred), and #50331 (auto-mode behavioral steering). Combined, the pattern erodes the changelog's value as a reliable description of what changed between versions.

Fix Action

Fix / Workaround

  1. The run_in_background parameter has been removed from the rendered Agent tool schema.
  2. The default dispatch is now asynchronous: every Agent call returns immediately with Async agent launched successfully, regardless of whether subagent_type is specified. There is no longer a way to launch an agent and synchronously wait for its result. The previous foreground-by-default behavior is gone.
  3. A new fork capability is exposed: calling Agent without a subagent_type creates a subagent that inherits the parent's full conversation context (system prompt, history, tool results) rather than starting cold. The Agent tool's description text documents this as a first-class pattern.
  4. Items 1–3 are gated by an undocumented Statsig/GrowthBook flag (tengu_copper_fox) and silently rolled out to a percentage of accounts. The flag is not documented anywhere except a third-party gist (unkn0wncode/f87295d055dd0f0e8082358a0b5cc467, updated 2026-04-27).

The only changelog entry adjacent to this rollout is v2.1.117: "Forked subagents can now be enabled on external builds by setting CLAUDE_CODE_FORK_SUBAGENT=1", which describes an opt-in env-var path. It does not mention that forks would also be flipped on for users via remote flag, that run_in_background would be removed when forks are active, or that synchronous Agent dispatch would be removed.

The result arrives in a later turn as a <task-notification> system-reminder. There is no parameter that switches to foreground/synchronous dispatch.

Code Example

description, prompt, subagent_type, model, isolation

---

Async agent launched successfully.
agentId: a3e14351f51a26c31
The agent is working in the background. You will be notified automatically when it completes.

---

function Gy1() {
  if (oOH()) return "disabled";                                  // always false
  if (hH(process.env.CLAUDE_CODE_FORK_SUBAGENT)) return "env";   // env-var override
  if (S8()) return "disabled";                                    // !isInteractive
  if (hH(void 0)) return "ant";                                   // dead code
  if (Z_(Xy1, !1)) return "gb_rollout";                           // ← Statsig flag
  return "disabled";
}
// Xy1 = "tengu_copper_fox"
// Wy1 = "tengu_fork_subagent_enabled"  (telemetry event)

---

// Suppresses run_in_background guidance:
const X = !hH(process.env.CLAUDE_CODE_DISABLE_BACKGROUND_TASKS) && !Z2() && !T
  ? "\n- `run_in_background: true` runs the agent asynchronously..."
  : "";

// Adds fork guidance:
${T ? `... omit it to fork yourself — a fork inherits your full conversation context.`
    : `... If omitted, the general-purpose agent is used.`}
RAW_BUFFERClick to expand / collapse

Preflight

  • I have searched existing issues and this specific angle isn't reported
  • This is a single bug report
  • I am using the latest version of Claude Code (v2.1.123)

Summary

The Agent tool's behavioral contract has changed substantially in a way that is not reflected in the changelog, the sub-agents docs, or the environment-variables docs:

  1. The run_in_background parameter has been removed from the rendered Agent tool schema.
  2. The default dispatch is now asynchronous: every Agent call returns immediately with Async agent launched successfully, regardless of whether subagent_type is specified. There is no longer a way to launch an agent and synchronously wait for its result. The previous foreground-by-default behavior is gone.
  3. A new fork capability is exposed: calling Agent without a subagent_type creates a subagent that inherits the parent's full conversation context (system prompt, history, tool results) rather than starting cold. The Agent tool's description text documents this as a first-class pattern.
  4. Items 1–3 are gated by an undocumented Statsig/GrowthBook flag (tengu_copper_fox) and silently rolled out to a percentage of accounts. The flag is not documented anywhere except a third-party gist (unkn0wncode/f87295d055dd0f0e8082358a0b5cc467, updated 2026-04-27).

The only changelog entry adjacent to this rollout is v2.1.117: "Forked subagents can now be enabled on external builds by setting CLAUDE_CODE_FORK_SUBAGENT=1", which describes an opt-in env-var path. It does not mention that forks would also be flipped on for users via remote flag, that run_in_background would be removed when forks are active, or that synchronous Agent dispatch would be removed.

Reproduction

Account on Max subscription, no CLAUDE_CODE_FORK_SUBAGENT set in env or any settings file. Claude Code v2.1.123, fresh terminal session.

The Agent tool's rendered parameter list:

description, prompt, subagent_type, model, isolation

No run_in_background.

Calling Agent with an explicit subagent_type (e.g. "Explore") and a trivial prompt (Run \pwd` and report the result.`) returns:

Async agent launched successfully.
agentId: a3e14351f51a26c31
The agent is working in the background. You will be notified automatically when it completes.

The result arrives in a later turn as a <task-notification> system-reminder. There is no parameter that switches to foreground/synchronous dispatch.

What's actually happening (from binary inspection of v2.1.121)

The Agent tool's description and behavior are conditional on eZ() — the fork-mode-enabled gate:

function Gy1() {
  if (oOH()) return "disabled";                                  // always false
  if (hH(process.env.CLAUDE_CODE_FORK_SUBAGENT)) return "env";   // env-var override
  if (S8()) return "disabled";                                    // !isInteractive
  if (hH(void 0)) return "ant";                                   // dead code
  if (Z_(Xy1, !1)) return "gb_rollout";                           // ← Statsig flag
  return "disabled";
}
// Xy1 = "tengu_copper_fox"
// Wy1 = "tengu_fork_subagent_enabled"  (telemetry event)

When eZ() returns true, the description-rendering logic switches branches:

// Suppresses run_in_background guidance:
const X = !hH(process.env.CLAUDE_CODE_DISABLE_BACKGROUND_TASKS) && !Z2() && !T
  ? "\n- `run_in_background: true` runs the agent asynchronously..."
  : "";

// Adds fork guidance:
${T ? `... omit it to fork yourself — a fork inherits your full conversation context.`
    : `... If omitted, the general-purpose agent is used.`}

The base zod schema (q05) still defines run_in_background, so the parameter exists in the codebase — it's just no longer described to the model. The model has no way to discover or use it in a fork-mode-enabled session.

The tengu_copper_fox flag has been present in the binary since at least v2.1.118, so this rollout mechanism shipped alongside the v2.1.117 env-var path — it was not retrofitted.

The documented contract

The sub-agents documentation and the v2.1.117 changelog describe forks as opt-in via CLAUDE_CODE_FORK_SUBAGENT=1. Nothing in the docs says:

  • That forks would also be enabled via remote feature flag for accounts that haven't set the env var.
  • That run_in_background would be removed from the Agent tool when forks are active.
  • That synchronous/foreground Agent dispatch would no longer be available in fork-enabled sessions.
  • That an explicit subagent_type would also be forced into background dispatch.

Why this matters

  1. Silent contract change for downstream tooling. Frameworks built on top of Claude Code's Agent tool (custom agent orchestrators, hooks, plan-mode integrations, prompt scaffolding) made design choices based on the documented synchronous-default contract. Those choices are now invisibly invalidated for users in the rollout cohort.

  2. No way to opt out. Setting CLAUDE_CODE_FORK_SUBAGENT=0 does not turn the rollout off — the env-var check is a positive gate. Users in the cohort have no documented mechanism to restore the previous behavior. (CLAUDE_CODE_DISABLE_BACKGROUND_TASKS only affects whether background-task descriptions are rendered, not whether dispatch is async.)

  3. Loss of an established capability. The synchronous Agent path was useful: it let the orchestrator block on a result and weave it back into the next turn deterministically. Replacing every Agent call with async dispatch shifts orchestration burden to the model and changes the shape of multi-step plans.

  4. Invisible cohort split. Two users on the same Claude Code version, same docs, same settings, behave differently depending on remote flag state. This makes documentation inaccurate for the rollout cohort and bug reports harder to diagnose.

  5. Pattern of undocumented behavioral changes via system-reminder / tool-description rewrite. This is the same shape as #29677 (Task→Agent rename), #31002 (built-in tools deferred), and #50331 (auto-mode behavioral steering). Combined, the pattern erodes the changelog's value as a reliable description of what changed between versions.

Suggested approaches

Option A: Document the rollout. Add a changelog entry covering the tengu_copper_fox rollout, what it changes (fork enabled, run_in_background removed, sync dispatch removed), and how to detect whether it's active in the session.

Option B: Honor a kill switch. Wire CLAUDE_CODE_FORK_SUBAGENT=0 to force the flag off regardless of tengu_copper_fox state, and document it. Users in the cohort can then restore the previous behavior.

Option C: Keep synchronous dispatch available. Even with fork mode active, retain a way to synchronously launch an explicit-subagent_type agent (e.g. via a wait: true parameter, or by treating explicit-type calls as synchronous and reserving async-by-default for forks).

Option D: Make the rollout cohort visible. Surface the active fork-mode source in /status or /doctor so users can see whether their session is disabled / env / gb_rollout / ant. This wouldn't change behavior but would make rollout state debuggable.

My preference is B + D: a documented kill switch and rollout visibility. A is necessary regardless. C is a more invasive change but worth considering if the synchronous path has users depending on it.

Related issues

  • #51769 (open, docs) — request to document CLAUDE_CODE_FORK_SUBAGENT in cloud-session docs. Adjacent but assumes the env var is the only enablement path.
  • #29677 (closed, undocumented Task→Agent rename) — same class: behavioral change to the Agent tool not reflected in the changelog.
  • #31002 (closed, built-in tools deferred behind ToolSearch) — same class: undocumented behavioral change.
  • #50331 (open, auto-mode behavioral steering) — same class: injected behavioral layer not reflected in docs.

Environment

  • Claude Code version: 2.1.123
  • Subscription: Claude Max
  • Model: claude-opus-4-7[1m]
  • Operating System: macOS (Darwin 25.2.0)
  • CLAUDE_CODE_FORK_SUBAGENT: not set
  • Fork mode source (inferred): gb_rollout via tengu_copper_fox

extent analysis

TL;DR

The issue can be addressed by documenting the tengu_copper_fox rollout and its effects on the Agent tool's behavior, and considering a kill switch to allow users to opt out of the rollout.

Guidance

  • Document the tengu_copper_fox rollout in the changelog, including its effects on the Agent tool's behavior, such as the removal of run_in_background and synchronous dispatch.
  • Consider adding a kill switch, such as CLAUDE_CODE_FORK_SUBAGENT=0, to allow users to opt out of the rollout and restore the previous behavior.
  • Surface the active fork-mode source in /status or /doctor to make the rollout state debuggable.
  • Review related issues, such as #51769, #29677, #31002, and #50331, to ensure that similar behavioral changes are properly documented.

Example

No code snippet is provided as the issue is related to documentation and behavioral changes rather than a specific code problem.

Notes

The issue highlights the importance of proper documentation and transparency when making changes to a system's behavior. The lack of documentation and the silent rollout of the tengu_copper_fox flag have caused confusion and made it difficult for users to understand the changes to the Agent tool's behavior.

Recommendation

Apply a workaround by documenting the tengu_copper_fox rollout and its effects, and consider adding a kill switch to allow users to opt out. This will provide transparency and give users control over the behavior of the Agent tool.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Agent tool's foreground/sync dispatch silently removed and replaced with always-fork mode via undocumented Statsig rollout [1 comments, 1 participants]