Skip to content

delegate_task from a background native Claude subagent fails with parent_not_active after the parent's turn settles #16808

Open

Description

@Dropje97

What happened

On a Claude thread (claudeAgent, claude-opus-5-5, full-access), the agent launched native subagents with Claude Code's built-in Agent tool (run_in_background: true) and ended its turn. Later, a subagent called the inherited mcp__t3-code__delegate_task tool to start a Codex review. The call failed with:

parent_not_active: Delegated tasks require an active run owned by this MCP provider session.

This happened 10 times on one thread between 2026-10-04 and 2026-10-07:

  • 8 calls came from background native subagents. One of those subagents had been launched by another native subagent.
  • 2 calls came from the parent itself. Both were on turns that Claude started on its own after a subagent sent it a message (Another Claude session sent a message: <agent-message from="…">).

Every successful delegate_task on the same thread ran during a turn that T3 started, from a user message or t3_thread_send.

T3 lists the native subagents as thread:provider:claudeAgent:native-thread:… with status idle and latestRunId: null. The T3 orchestration instructions tell agents to prefer native subagent tools for same-provider work when they support the chosen model, so this situation comes up in ordinary use.

Diagnosis

Line references are for b37fcea.

  1. The T3 MCP credential is scoped to a thread and provider instance, not to a run (McpSessionRegistry.ts#L130-L142). Claude receives it as the t3-code MCP server (ClaudeAdapterV2.ts#L937-L945). Native subagents inherit the parent's MCP servers, so their calls are checked against the parent thread's runs.
  2. delegateTask requires the newest run to be preparing, starting, running or waiting, with a root node and a matching provider instance (OrchestratorMcpService.ts#L1356-L1371, ThreadManagementService.ts#L326-L333).
  3. When the root Claude turn ends, the run is stored as waiting (RunExecutionService.ts#L633-L644). Within seconds, checkpoint capture marks it completed (CheckpointCaptureService.ts#L201-L216). Native background subagents that are still running do not keep it open.
  4. This matches the intended projection. In the claude_background_subagent_after_root fixture, the background subagent's frames are buffered after the root settles and drained into a continuation run that starts when the subagent completes (input.ts#L17-L19). Until then, the subagent keeps executing tools, including the inherited T3 MCP tools, while the thread has no active run.

Each step behaves as designed, but together they mean a background native subagent cannot call delegate_task once its parent's turn has ended. The error message suggests a lost or stale session, which hides the real cause.

Parent-side variant. The two parent failures happened on turns that Claude started after receiving a subagent's <agent-message>. In this build, such a wake opens its continuation run only at the result frame when no task notification is buffered (ClaudeAdapterV2.ts#L5043-L5057). The parent's tool calls in that turn therefore ran without an active run. T3 later attached them to a continuation run created 25–32 s after the failed call. #15055 (merged 2026-10-03, after this preview build) starts the continuation on system/init. The provider log shows system/init about 100 ms after such a message, so this variant is probably fixed on main. I have not verified that on a newer build.

On main (cd41c4a), the delegateTask guard (OrchestratorMcpService.ts#L1791-L1805), checkpoint completion and the fixture are unchanged. The subagent case should still apply there.

Possible directions, for the maintainers to choose:

  • keep the parent run waiting while native background subagents launched by that run are live;
  • or, if this is intended, return a distinct error such as "native background subagents cannot delegate after the parent turn has ended", and say so in the orchestration instructions.

Steps to reproduce

These steps follow from the source and the production failures below. I did not rerun them as a clean repro, because this machine has since disabled Claude's native Agent tool.

  1. On a Claude thread with T3 MCP orchestration, send:
    Use the Agent tool with run_in_background: true to launch one general-purpose subagent with this prompt: "Run sleep 90 with Bash, then call mcp__t3-code__delegate_task with task 'Reply with exactly OK.' and target provider codex, and reply with the raw tool result." Then reply ROOT_STARTED and stop.
  2. The root turn ends, and the run goes waiting → completed.
  3. About 90 s later, the subagent's delegate_task returns parent_not_active.
  4. For comparison, the same delegate_task call made by the parent during a user-started turn succeeds.

Version

0.0.46-preview.20261002.2598 (b37fcea). 9 of the 10 failures happened on the unmodified official binary. The last one happened on a server rebuilt from the same SHA with an unrelated SQLite scheduling patch (see #14701).

Environment

Linux x64 (LXC, kernel 7.0), T3 running as a systemd user service, Claude Code 2.1.292 through the Agent SDK. Parent provider claudeAgent (claude-opus-5-5), delegation target codex.

Evidence

# UTC. R<n> = run ordinal on the affected thread; every run is claudeAgent with a root node.
# Sources: orchestration_events (statev2.sqlite) and the Claude session transcripts.

# Background native subagent, 2026-10-04
03:01:56.870  R59 running (user turn); parent launches Agent(run_in_background=true)
03:06:16.099  R59 waiting
03:06:17.022  R59 completed                                  # no active run from here on
03:56:28.150  subagent: delegate_task -> parent_not_active
03:59:18.121  R60 created

# Parent turn started by a subagent's agent-message, 2026-10-05
17:31:49.726  R298 completed
17:36:56.447  transcript: isMeta user "Another Claude session sent a message: <agent-message from=…>"
17:37:18–17:37:51  parent runs four tool calls with no T3 run
17:38:22.690  parent: delegate_task -> parent_not_active
17:38:47.825  R299 created (creationSource=provider, text "Background task completed."); the
              earlier tool calls are stored under R299 with processing-time timestamps
17:39:09.643  R299 completed

# Comparison on the same thread, T3-started turns
2026-10-05 17:48:36  parent, R300 running (user turn)  -> delegate_task OK
2026-10-07 10:42:44  parent, R414 running              -> delegate_task OK

# All 10 failures: the latest run was `completed` (never `waiting`). All 419 runs on the
# thread stayed on claudeAgent. At each failure the provider session was attached and
# `ready`, with no stop since that attachment.

Related issues

#16565 has the same error with a different trigger: a provider switch-and-back that leaves the credential on the wrong provider. This thread never switched provider. #15173: idle session release revokes the MCP credential, which surfaces as HTTP 401 invalid_mcp_credential rather than this tool-level error, and the session was attached at every failure. #15055 probably fixes the parent-side variant.

Fix applied or workaround

No change to T3. Agents worked around it by relaying the delegation through the parent on the next T3-started turn. This machine now denies Claude's native Agent tool (permissions.deny: ["Agent"]) and uses delegate_task only.

Filed by

Claude Code (Claude Opus 5.5), with investigation by Codex (GPT-6.1-Sol) sub-agents, following the t3 triage playbook.

Activity

  1. Jacksondr5 commented on Oct 11, 2026

    @Jacksondr5

    This now affects every writing tool, not only delegate_task, and it reproduces on Codex as well as Claude.

    What happened

    A native subagent that outlives its parent's turn has every writing MCP tool refused with "The calling provider no longer owns an active thread run." Read-only tools keep answering, so preview_status returns available: false, tabId: null with nothing to say the caller is not live. It is easy to read as a browser fault.

    Diagnosis

    actsAsCaller, writes and writesThreads all go through assertLiveCaller (apps/server/src/mcp/threadAccess.ts), which needs a non-null activeRunId. The gate's comment says it stops "a provider token that outlived its session". Here the session is alive and working; it is the run that has ended. I exercised only the preview tools; device, worktree handoff, pull request and thread tools share the gate by declaration.

    Steps to reproduce

    1. The parent launches a native subagent that does not finish within the turn (Claude: run_in_background: true; Codex: spawn and don't wait), then ends its turn. The run goes to completed.
    2. The subagent calls preview_open with {"open": false, "reuseExistingTab": false}. It is refused.
    3. In the same window preview_status, t3_preview_list and t3_thread_list succeed.
    4. Control: with the parent turn held open, the same call succeeds (Claude: 47 preview calls with no failures; Codex: open and close succeeded).

    Version

    A fork pinned at upstream 29980a3140; the gate files are identical on main at 243c9994d0. Not reproduced on an upstream build.

    Environment

    Ubuntu 24.04.5, Node 24.14.0, Claude Code 2.1.296 (Opus 5.5), codex-cli 0.162.1 (GPT-6-Astra).

    Evidence

    # Codex, 2026-10-11 UTC
    17:33:36.514  parent run completed (activeRunId: null)
    17:35:45      subagent preview_open -> "The calling provider no longer owns an active thread run."
    
    # Claude, server trace for the refused call
    16:48:40.747  McpServer tools/call  tool=preview_open  2.9ms
    16:48:40.748  mcp.loadCaller        1.1ms
                  (no PreviewToolkit.invoke span: refused before reaching the browser)
    

    Related issues

    #17809 and #17885 hit the same message in the parent's wake turn. #16565 is the same message from a different arm of the gate (provider switch).

    Workaround

    Keep the parent turn open until the subagent returns.

    Both directions listed above would fix this. Whichever is chosen, the error could say that the parent turn ended while background work continues, and preview_status could report it too.

    Prepared with Claude Opus 5.5 and approved by Jackson.

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