DEV Community

Ahab
Ahab

Posted on • Originally published at indieseek.co

Qwen Code 0.21.4 Forked Subagent Isolation Checklist

Qwen Code 0.21.4: test forked subagent prompt isolation

Quick answer

Qwen Code 0.21.4 fixes a concrete multi-agent isolation bug: when several forked subagents were launched in one model response, each fork could inherit the functionCall.args.prompt values belonging to its siblings. A tool-less fork could therefore describe work assigned to other forks even though it had no legitimate runtime path to those directives.

Upgrade first, confirm the active version, then run a three-sentinel canary:

npm install -g @qwen-code/qwen-code@0.21.4
qwen --version
Enter fullscreen mode Exit fullscreen mode

Launch three parallel fork subagents in one turn. Give each a unique, non-secret sentinel and instruct it to return only its own sentinel. The rollout passes only when every child reports its own value, never names a sibling value, retains the expected history, and still completes with fork_tools: [].

This is a prompt-isolation check, not a reason to place real secrets in agent prompts. Use disposable markers such as ALPHA_71, BETA_42, and GAMMA_93.

Who this is for

This guide is for teams using Qwen Code forked subagents for parallel code analysis, research, review, or planning. It is especially relevant when sibling tasks have different customer context, security scope, or least-privilege instructions.

The fix complements the Qwen Code 0.21.3 review evidence gate. That article tests whether review claims deserve trust; this one tests whether parallel workers receive only the current-turn directive intended for them. If the harder problem is proving completion state, use the Qwen Goal evidence checklist.

What changed and why it matters

The official v0.21.4 release says forked subagents are now isolated from sibling forks launched in the same turn. The merged fix explains the failure path:

  1. The parent model emitted several parallel agent function calls.
  2. Each call carried its child directive in args.prompt.
  3. The shared model message was replayed into every fork's inherited history.
  4. Placeholder responses preserved call pairing, but sibling prompt arguments remained visible.

The patch clears the replayed function-call arguments while preserving the id and name needed for pairing. A fork's own directive is still delivered separately. Qwen reports no public signature change and no known breaking change in the stable release.

The boundary is just as important as the fix: the merged PR says previously resolved tool calls can still be inherited when fork_turns: "all". Version 0.21.4 removes sibling directives from the current fork-launch message; it does not promise that all earlier parent history is confidential.

Boundary What 0.21.4 protects What you still control
Same-turn sibling directives Replayed call arguments are redacted Verify with unique sentinels
Child's own directive Delivered through the child-message path Keep it task-scoped
Earlier parent history May be inherited by the chosen fork window Minimize history or use a fresh parent
Tool permissions Separate from prompt visibility Keep fork_tools least-privileged
Secrets Not made safe by prompt isolation Never use live credentials as test markers

A five-stage isolation workflow

1. Freeze the runtime identity

Record the install source, qwen --version output, model provider, repository revision, and effective fork settings. A global CLI, source checkout, extension, and long-running daemon can resolve different builds. Restart any persistent Qwen process after upgrading, then confirm the version from the process that will launch the test.

2. Build a non-secret three-sentinel canary

In one parent turn, ask Qwen Code to launch three fork subagents in parallel:

Launch three fork subagents in one response with fork_tools: [].

Fork A directive: Return exactly OWN=ALPHA_71 and whether you can see BETA_42 or GAMMA_93.
Fork B directive: Return exactly OWN=BETA_42 and whether you can see ALPHA_71 or GAMMA_93.
Fork C directive: Return exactly OWN=GAMMA_93 and whether you can see ALPHA_71 or BETA_42.

Each fork must discuss only its own directive. Do not infer or invent sibling values.
Enter fullscreen mode Exit fullscreen mode

The exact orchestration syntax can vary by surface. The invariant is one model response containing three parallel fork calls, each with a distinct marker, and no tool access that could provide another observation path.

3. Score outputs fail-closed

For each child, evaluate both positive and negative conditions:

Check Pass condition
Own directive The child returns its assigned sentinel once
Sibling recall Neither sibling sentinel appears anywhere
Meta-summary The child does not describe all three tasks
Tool boundary The run confirms no tools were available
Completion The child finishes normally without missing-call errors

Do not accept “I cannot see siblings” if the same output then prints their markers. Match the literal disposable values in the complete child response.

4. Inspect history without leaking real data

If the output fails, preserve only the minimum evidence required: Qwen version, fork settings, child identifier, and redacted message structure. Do not paste full production transcripts into an issue or CI log.

For a source-level verification, the official PR locates the behavior in buildForkedMessages and includes a unit-plus-integration test command. The useful invariant is that sibling sentinels never appear in the child's seed initialMessages, while call-response pairing and the child's own directive still work.

5. Roll out with a bounded fallback

Run the canary on every execution surface that launches parallel forks: developer CLI, CI worker, extension, daemon, or packaged desktop shell. If a surface cannot prove 0.21.4 and pass isolation, stop same-turn parallel forks there. Use separate parent sessions or sequential launches with non-sensitive context until the surface is upgraded and verified.

That fallback reduces accidental cross-talk, but it is not a substitute for permission controls. Apply filesystem, shell, and network boundaries independently; the Claude Code strict allowlist checklist provides a compatible egress-testing pattern.

Eight rollout gates

Gate Required evidence
Version The launching process reports Qwen Code 0.21.4 or newer
Same-turn construction Three fork calls were emitted in one parent response
Own-marker delivery Each child receives exactly its assigned sentinel
Sibling non-disclosure No child output or seed history contains a sibling sentinel
Pairing integrity Placeholder call responses do not produce missing-call errors
Tool isolation fork_tools: [] remains effective during the canary
Prior-history boundary Earlier parent history was reviewed or deliberately minimized
Fallback Unverified surfaces disable same-turn parallel forks

Copyable evidence record

qwen_fork_isolation:
  qwen_version: "0.21.4"
  execution_surface: "developer-cli"
  fork_turns: "all"
  fork_tools: []
  disposable_sentinels:
    fork_a: "ALPHA_71"
    fork_b: "BETA_42"
    fork_c: "GAMMA_93"
  own_marker_delivery: passed
  sibling_marker_absence: passed
  call_pairing: passed
  prior_history_reviewed: true
  parallel_forks_enabled: true
  evidence_owner: "named person or team"
Enter fullscreen mode Exit fullscreen mode

Common mistakes

Testing with two separate parent turns. The fixed bug involved sibling calls emitted in the same model response. Separate turns do not exercise the affected path.

Using credentials as sentinels. A regression test should be safe to leak. Use random disposable markers, never API keys, customer data, or private instructions.

Treating empty tools as empty context. fork_tools: [] prevents tool execution; it does not by itself control inherited conversation history.

Checking only the global CLI. A daemon, extension, source build, or packaged surface may still run an older core. Verify the process that actually creates the forks.

FAQ

Does Qwen Code 0.21.4 isolate all parent context from a fork?

No. The fix removes same-turn sibling call arguments from the replayed fork-launch message. Earlier history selected by fork_turns can still be inherited. Keep parent history scoped and choose the smallest window that preserves the task.

Can I enable parallel forks immediately after updating?

Update first, restart persistent processes, and pass the three-sentinel canary on each execution surface. If a surface cannot prove its runtime version or isolation result, keep same-turn parallel forks disabled there.

Sources


Originally published at IndieSeek.

Top comments (0)