Skip to content

[Bug]: Delegated-task and command notices wait for the next turn on Claude instead of reaching the running turn #36106

Closed as not planned

Description

@Alb11747

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. On a Claude thread, have the agent call delegate_task and keep working while the child runs, for example with a long tool call.
  2. Let the child finish, or ask a question, while the parent's turn is still running.
  3. Do the same on Codex.

Expected behavior

The completion or question notice reaches the running Claude turn at its next safe point, as it does on Codex.

Actual behavior

On Claude, the notice is queued for the parent's next turn. A parent turn that is still working only learns that its child finished, or asked a question, after the whole turn ends. Command notices during an active goal behave the same way.

The routing is in Orchestrator.dispatchMessage (Orchestrator.ts:6960). Delegated-task notices and command notices are steered into the active run only when the provider's activeSteeringInterruptsTools is not true. Claude declares it true (ClaudeAdapterV2.ts:512). On main that is accurate: a Claude steer is written with priority: "now" and cancels in-flight MCP tool calls (#21895).

Impact

Major degradation or frequent failure

Version or commit

ed05c0e (found by reading the code)

Environment

Any; Claude provider.

Logs or stack traces

n/a: behaviour follows from the routing condition above

Notes

#35462 makes Claude steers wait for the next root tool boundary (priority: "next" from PostToolBatch), so they no longer cancel tools. After that, activeSteeringInterruptsTools: true no longer describes Claude, and its only remaining effect is to keep these notices out of the running turn.

Flipping the flag alone isn't safe. A notice sent as a steer is marked delivered once the steer call returns, but with #35462 the steer may still be held for the next boundary at that moment. If Stop drops it, a delegated-task completion would be marked delivered and lost. So the receipt for steered notices should wait until the input is written to Claude, or a dropped notice should return to the mailbox. Then Claude can declare false.

Related: #21895, #35462 (closed by the open PR limit and queued to reopen), #21158, #32606.

🤖 Generated with Claude Code

Activity

  1. juliusmarminge commented on Nov 13, 2026

    @juliusmarminge
    Member

    I tried to reproduce this on the current build and could not.

    Commit ed05c0e (origin/main). No live run: Claude needs first-party Claude OAuth, which no worker has. Code: Orchestrator.dispatchMessage (apps/server/src/orchestration-v2/Orchestrator.ts:6960) steers delegated-task and command notices into the active run only when the provider's activeSteeringInterruptsTools !== true. ClaudeAdapterV2.ts:512 declares it true, so on Claude these notices go to the queue. In apps/server, vp test run src/orchestration-v2/SteeringCompletion.integration.test.ts -t "interrupting native steering" passes. That existing case asserts that, with interrupting native steering, the mailbox notification is delivered only after the turn, the behaviour the reporter describes.

    Closing as not planned. If it still happens for you, reply with the exact steps and the version you are on and it will be looked at again.

  2. mselcukozturk commented on Nov 13, 2026

    @mselcukozturk

    This still happens with a live Claude parent. Reproduced on T3 Code 0.1.7 (Linux, desktop + local server). The routing is unchanged on main f313d0a (Orchestrator.ts:7024-7035, ClaudeAdapterV2.ts:512).

    Steps

    1. Parent thread on Claude Opus 5.5. Call delegate_task (async) to Antigravity claude-sonnet-5-5 while that model's quota is spent.
    2. Keep the parent turn working (shell commands, file reads) for a few minutes.

    Timeline (UTC, from statev2.sqlite)

    Event Time
    Child run requested 15:41:42.078
    Child failed: "Usage limit reached. You have reached your Antigravity quota for this period." 15:41:46.549
    Completion message created in the parent as a new queued run (ordinal 2, queuePosition: 1) 15:41:46.571
    A user message sent during the turn was steered into the running parent turn (ordinal 1) 15:43:17.748
    Parent turn ended 15:45:09.263
    Queued completion run started; the parent saw the failure 15:45:09.433

    The child failed 4 s after it was requested. The parent learned of it 3 min 23 s later, 0.17 s after its own turn ended, so the delay equals whatever is left of the parent turn. Until then the parent behaved as if the child were still working, and the user had to tell it in chat that the child had failed.

    This matters most for quota failures: the child fails within seconds, but the parent cannot fall back to another model until its turn ends. Workaround in use: delegate_task with mode: "wait" and a short timeoutMs, which returns the failure in the tool result.

  3. Alb11747 commented on Nov 13, 2026

    @Alb11747
    ContributorAuthor

    This still happens on current main (eb14ddb). A repro that needs no Claude login is in #36454.

    Posted by Claude Opus 5.5 on behalf of Alb11747.

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