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

opened22d agobyDDropje97

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:

1parent_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

shell
1# UTC. R<n> = run ordinal on the affected thread; every run is claudeAgent with a root node.
2# Sources: orchestration_events (statev2.sqlite) and the Claude session transcripts.
3
4# Background native subagent, 2026-10-04
503:01:56.870 R59 running (user turn); parent launches Agent(run_in_background=true)
603:06:16.099 R59 waiting
703:06:17.022 R59 completed # no active run from here on
803:56:28.150 subagent: delegate_task -> parent_not_active
903:59:18.121 R60 created
10
11# Parent turn started by a subagent's agent-message, 2026-10-05
1217:31:49.726 R298 completed
1317:36:56.447 transcript: isMeta user "Another Claude session sent a message: <agent-message from=…>"
1417:37:18–17:37:51 parent runs four tool calls with no T3 run
1517:38:22.690 parent: delegate_task -> parent_not_active
1617:38:47.825 R299 created (creationSource=provider, text "Background task completed."); the
17 earlier tool calls are stored under R299 with processing-time timestamps
1817:39:09.643 R299 completed
19
20# Comparison on the same thread, T3-started turns
212026-10-05 17:48:36 parent, R300 running (user turn) -> delegate_task OK
222026-10-07 10:42:44 parent, R414 running -> delegate_task OK
23
24# All 10 failures: the latest run was `completed` (never `waiting`). All 419 runs on the
25# thread stayed on claudeAgent. At each failure the provider session was attached and
26# `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.

Synced from GitHub

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

1# Codex, 2026-10-11 UTC
217:33:36.514 parent run completed (activeRunId: null)
317:35:45 subagent preview_open -> "The calling provider no longer owns an active thread run."
4
5# Claude, server trace for the refused call
616:48:40.747 McpServer tools/call tool=preview_open 2.9ms
716:48:40.748 mcp.loadCaller 1.1ms
8 (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.

Synced from GitHub

Here is another parent-side trigger, on a build after #15055: a turn that Claude Code starts by itself when a background Bash command (run_in_background: true) completes.

Version: 0.0.46-nightly.20261015.3176 (Linux AppImage, desktop app with its built-in server). Claude Code provider, claude-opus-5-5, full-access.

Timeline, 16 Oct 2026 (UTC):

  • An earlier turn started a background command, a CI gate of about 10 minutes. Run 233 handled a user turn from 07:33:14 to 07:34:02, and then completed.
  • At 07:40:44 the background command finished. Claude Code delivered its <task-notification> and started a new turn on its own.
  • Four delegate_task calls in that turn failed, at 07:44:40, 07:44:51, 07:46:30 and 07:46:39:
    1{"_tag":"OrchestratorMcpFailure","code":"parent_not_active","message":"The calling provider no longer owns an active thread run."}
  • T3 created no run for that turn. The thread's runs go from 233 (completed 07:34:02) straight to 234 (requested 07:50:20 by a scheduled task). The same calls succeeded in run 234.

So the note that the parent-side variant is "probably fixed on main" does not hold for task-notification wakes on this build.

Effect: a coordinator that reacts to a long background command can't delegate, link PRs or launch threads in that turn. The work waits for the next run that T3 starts. Here that was about 10 minutes later, from the heartbeat.

Workaround: end the turn, and let a scheduled task, a child completion or a user message start a run.

Synced from GitHub

Claude Claude Opus 5.5 (high effort) wrote this; Claude Opus 5.5 (medium effort) reviewed it.

I hit the same trigger as @hardik88t above, on 0.0.46-nightly.20261014.3132 (desktop app with its built-in server, WSL2, Claude Code 2.1.300, claude-opus-5-5). Events from Claude Code's Monitor tool start turns the same way as a finished background Bash command. I had turned off the thread's scheduled task, so nothing started a run for 8.5 hours while the session kept waking up:

109:32:34 run 3464 completes
209:35:14 a background Bash command finishes; Claude Code starts a turn on its own
309:35:35-53 delegate_task (x2) and run_scheduled_task_now -> parent_not_active
409:48-17:58 24 more task notifications, all from the Monitor tool
513:33:08 PushNotification -> "Mobile push not sent (Remote Control inactive)"
618:06:50 my message "Done?" starts run 3465; the same delegate_task calls succeed

This differs from the held queue in #17885. The run after 3464 is 3465, my own message, so T3 never queued a run for these turns. None of their text or tool calls are in the thread either: its items go from run 3464's checkpoint straight to my message. The agent noticed it couldn't delegate and tried to start the scheduled task itself, which also failed with parent_not_active. Its push notification asking me to send a message didn't go through either, so the thread looked idle to me the whole time.

I'd make every turn Claude starts by itself get a run, as @iokoioko suggested on #17857, because that one change makes the turn visible and lets its T3 tools work.

Fresh triage on main b5a226e49c: the general live-caller check now accepts pending native subagents, following 11ce406d2c. However, OrchestratorMcpService.delegateTask still independently requires an active parent run before accepting delegation. This is source inspection, not a runtime reproduction.

Searched all 19 pages of open issues for delegation, background/native subagents and parent_not_active; no earlier duplicate with this trigger found. #16565 requires a provider switch; #23009 overlaps the later parent-notification variant and points here.

Leaving open for maintainer review: resolving delegation after the parent settles changes MCP caller/run ownership behavior, which is outside the automated triage fix scope. No implementation changes or runtime verification performed.

Synced from GitHub

Same rejection on 0.1.3-nightly.20261025.3669 (macOS, Claude Code 2.1.310), this time for t3_background_wait, so the "keep Working" path fails exactly when a background subagent needs it.

  1. A native Agent subagent was resumed with SendMessage, so it ran in the background.
  2. The parent ended its turn.
  3. The subagent's own background tasks woke it (task_started … is_backgrounded: true at 16:29:23).
  4. At 16:29:41 it called t3_background_wait {"taskIds":["bryakiqmh","bewduxibb"],"waiting":true} and got parent_not_active: The calling provider no longer owns an active thread run.

isLiveCallerShell accepts a background subagent only through pendingBackgroundTasks with kind: "subagent". A subagent resumed by SendMessage didn't count as one at that moment: the subagent projection still had it as completed from its earlier Agent call. The Lineage panel likewise lists it under "Previous agents" while it's running.

The foreground-subagent stall from the same thread is filed separately: #24956.

Filed by Claude Code (claude-opus-5-5) via t3 triage.