Workflow tool: agent() sub-agent calls in a run returned content from an unrelated, concurrent session
Summary
While running a custom Workflow-tool script (multiple sequential agent() sub-agent
calls orchestrating a multi-step automation, similar in shape to a CI "build a
feature branch → rebase → push" pipeline), several of the sub-agent calls in a
single Workflow run returned content that appears to have come from a completely
different, concurrent conversation in a separate Claude Code session — running
under the same OS user account on the same machine, at roughly the same wall-clock
time — instead of executing the deterministic shell task their prompt actually
specified.
Environment
- Claude Code CLI, Workflow tool (
agent()calls inside a custom workflow script
invoked via a plugin skill)
- Two separate Claude Code sessions active concurrently on the same machine / same
user account: Session A running the Workflow, Session B in an unrelated
interactive conversation with the user
- macOS
What happened
Session A's Workflow run executed 9 sequential agent() calls, each with a
distinct, static, single-purpose prompt (e.g. "acquire an advisory lock and
return this JSON shape", "create a git worktree and report success/failure",
"write a small manifest file", "run this shell script and return its JSON
output", "clean up state files").
5 of those 9 calls — starting right after the 3rd call and ending right before
the 9th — returned prose that answered an unrelated question ("did you take
those <X> changes also into this repo/ship?") instead of performing their
assigned task. That exact question, verbatim, was asked by the user to Session B
(a completely separate, concurrent conversation) at approximately the same time.
The contaminated responses:
- Never executed the shell commands their prompts specified (confirmed no trace
of the expected commands/output in the affected steps' results)
- Were mutually inconsistent with each other (some correctly said "no, those
changes are not included", one incorrectly claimed they were included and
attributed them to the wrong commit, one lost context entirely and asked the
(nonexistent, from this workflow's perspective) user to clarify which files
they meant)
- Did not otherwise reference anything in the actual prompt text (which is
static, contains no reference to the leaked topic, and was verified not to
interpolate any variable that could produce that text)
The calls immediately before (pre-flight, check existing MR, try acquire) and immediately after (
lockrelease lock) all returned correct results for
their actual assigned tasks. So the contamination window was contiguous and
bounded, not present for the whole run.
Why this is more than a "one weird response" issue
One of the 5 contaminated calls was expected to return strict JSON (parsed by
the orchestrating script). Because it returned prose instead, JSON parsing
failed and the orchestrating script correctly detected the failure and aborted
safely.
The other 4 contaminated calls were free-text confirmation steps with no schema
validation on the orchestrating side (by design — they're advisory/cleanup
steps). Those calls report has no way to distinguish "call succeeded" from
"call silently did nothing and returned unrelated prose" — meaning in a run
where the JSON-validated step happens not to be the one contaminated, the
orchestrating script could believe worktree setup / cleanup / state-management
steps succeeded when they never actually ran.
Ask
- Is this a known failure mode in how the Workflow tool dispatches/threads
agent() sub-agent calls, particularly when multiple Claude Code sessions
are active concurrently under the same account/machine?
- Is there sub-agent-to-parent-conversation isolation guaranteed at all today,
or is this a known gap?
- Any recommended mitigation in the meantime (e.g., avoid running Workflow-tool
scripts while another session is mid-conversation on the same machine)?
Happy to share the raw journal.jsonl for the affected run (with any
proprietary content redacted) if that helps reproduce or diagnose this — it
records each agent() call's label, prompt key, and raw result in order.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗