Skip to content

fix(server): resumed Claude subagents keep their own model and effort label - #14272

Closed
spiky02plateau wants to merge 1 commit into
pingdotgg:mainfrom
spiky02plateau:fix/subagent-row-model-effort
Closed

spiky02plateau wants to merge 1 commit into
pingdotgg:mainfrom
spiky02plateau:fix/subagent-row-model-effort

Conversation

@spiky02plateau

@spiky02plateau spiky02plateau commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

What Changed

When a finished Claude subagent is revived with SendMessage, its row in the agents list now keeps the subagent's model instead of switching to the parent session's model. Subagent rows also stop showing the session's effort level; effort appears only when the Agent call sets it explicitly.

Why

Reviving a finished subagent makes the SDK register the same task again, with the SendMessage call as its launching tool. That call names no model or effort, so the adapter fell back to the session's selection and the row showed the parent's model while the subagent kept running on its own. Subagents that received a message while still running were unaffected, because no new task_started arrives for them.

Effort had a second problem: when the Agent call set no effort, the row showed the session's effort. An agent definition can set its own effort, and the SDK reports no per-subagent effort on any stream message, so the row could show medium for a subagent running on high. The contract describes the field as "effort when known", so the adapter now reports effort only when the launch input sets it, and keeps the known value across a resume.

Scope is the Claude adapter's task_started handling. Model refinement from subagent snapshots and the client reducers are unchanged.

Closes #14842

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Summary by CodeRabbit

  • Bug Fixes
    • Task status now reflects explicitly selected effort settings, rather than incorrectly reporting the session’s effort when none was specified for the task.
    • Resumed agents retain the model and effort selected when they were originally launched, keeping task details consistent across the session.

Reviving a finished subagent with SendMessage re-registers the same task
under the SendMessage call, which names no model or effort, so the row
fell back to the session's model and effort. Re-registration now keeps
what is already known for the task.

Subagent effort also defaulted to the session's effort, which is wrong
whenever an agent definition sets its own. The SDK reports no per-agent
effort, so effort is shown only when the launch input sets it.
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Sep 29, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Sep 29, 2026
@macroscopeapp

macroscopeapp Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at eb08085

Macroscope's review found this PR approvable — This is a small, well-tested Claude adapter bug fix that corrects resumed subagent metadata without changing the underlying model or effort used by the runtime. The production impact is limited to task labeling and state retention, with no new capability, schema change, or deployment impact.

Notes:

  • Diff unchanged. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: d394f9f1-7c6c-4c25-acdc-d45966ddf9a5

📥 Commits

Reviewing files that changed from the base of the PR and between d2c9281 and eb08085.

📒 Files selected for processing (2)
  • apps/server/src/provider/Layers/ClaudeAdapter.test.ts
  • apps/server/src/provider/Layers/ClaudeAdapter.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

Claude task registration now selects the model from launch input, recorded task state, or session state. It uses explicit or previously recorded task effort, not session effort. Tests cover omitted launch values and resumed-agent model and effort retention.

Changes

Claude agent registration

Layer / File(s) Summary
Task model, effort, and resume behavior
apps/server/src/provider/Layers/ClaudeAdapter.ts, apps/server/src/provider/Layers/ClaudeAdapter.test.ts
Task registration falls back to the recorded task model and effort when launch values are absent. Session effort is no longer stored, and existing run handles are reused. Tests cover omitted launch values and resumed-agent event values.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Bug fix

Suggested reviewers: t3dotgg

Merge Risk: ⚪ Minimal · up to eb080

No actionable merge-blocking issue was identified in Claude subagent metadata registration or resume behavior. The change is mergeable after normal checks.

Security Architecture Review

Security architecture risk: 🔵 Low · up to eb080

Resumed tasks now retain their own displayed settings instead of inheriting session settings. No new privilege path was found, but behavior during overlapping lifecycle events is not fully established.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The examined change affects task metadata and lifecycle-event output within the existing provider path; it does not establish an additional execution or privilege path.

Trust Boundaries and Controls

  • observed — Task ownership continues to come from the in-flight launching tool’s agent attribution. Retained model, effort, and run handles do not replace that attribution.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the problem, intended behavior, implementation scope, and linked issue. It does not follow the required template headings and does not provide focused verification steps or ob… Add the required Problem, Change, Scope and approval, and Verification sections. Include the specific tests run, their observed results, and anything not checked. Link the triaged issue with approval evidence, or explain why this focused fi…
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: resumed Claude subagents retain their own model and effort label.
Full details: Description check

Explanation

The description explains the problem, intended behavior, implementation scope, and linked issue. It does not follow the required template headings and does not provide focused verification steps or observed test results. It also does not clearly document maintainer approval or why the change qualifies as an obvious bug fix.

Resolution

Add the required Problem, Change, Scope and approval, and Verification sections. Include the specific tests run, their observed results, and anything not checked. Link the triaged issue with approval evidence, or explain why this focused fix does not require prior approval.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

incognitojam added a commit to incognitojam/styal that referenced this pull request Sep 29, 2026
…ard (#539)

> [!NOTE]
> A Claude subagent's own background shells and nested agents leaked
into the parent timeline as "Received N updates" rows and one-agent
"Kicked off 1 subagent" cards. The server now attributes those tasks to
the subagent that started them, and web and mobile keep them inside that
subagent's single spawn card.

## Problem

When a Claude subagent started its own background shells or its own
agents, the parent thread's timeline filled with stray rows. Each
finished shell became a "Received N updates" row. Each nested agent
became a separate "Kicked off 1 subagent" card, placed wherever it
happened to start, often between unrelated messages.

The clients already hide a subagent's internal work, but only when the
task carries `agentId` (its owner). The Claude adapter never set it. It
looked for the launching tool call among streamed tool calls, but Claude
streams tool-call deltas only for the parent conversation. A subagent's
tool calls arrive only as whole `assistant` snapshots tagged with
`parent_tool_use_id`, and the adapter used those snapshots only to
refine the model name. In practice no task row ever got `agentId`.

Upstream has the same gap. The open related PRs don't cover this path:
pingdotgg#10575 still depends on child
stream events, and pingdotgg#14272 and
pingdotgg#14031 address resumed-subagent
labels and reactivation.

## Fix

- **Server (Claude adapter):** records which subagent made each tool
call from its assistant snapshots, bounded to 512 entries per session.
`task_started` uses that record when no streamed call matches. A
subagent's shells therefore carry the subagent's `agentId`, and so do
its nested agents. A resumed subagent keeps its owner. Its later
messages also still resolve to it, because they keep the original Agent
call as their parent even though the SDK re-registers the task under the
`SendMessage` call.
- **Web and mobile:** a nested agent joins its owner's spawn card
instead of opening its own. Its owner's first row has already decided
that card. The existing quiet-timeline rule already hides a subagent's
own shells once they carry `agentId`.

Existing threads are not repaired, because their persisted task rows
have no owner to group by.

## Validation

- **Live run** against an isolated dev server with a real Claude Sonnet
5.5 thread. The parent launched one background subagent and ended its
turn. After that, the subagent started a background `sleep` shell and a
nested background agent, and the nested agent started its own shell. The
persisted task rows had the expected owners:
- The subagent's shell and the nested agent were attributed to the
subagent.
  - The nested agent's shell was attributed to the nested agent.
  - When the CLI resumed the subagent on its own, it stayed unowned.
- **Timeline:** one "Ran 2 subagents ✓ completed" card at the spawn
point, with no "Received N updates" rows and no extra cards. The Agents
panel listed both agents.
- **Focused tests:** one each for the adapter, web and mobile. Each
fails without the fix and passes with it. The adapter test covers
shells, nested agents, completions, and a shell started after a resume.
Full `ClaudeAdapter.test.ts`, `session-logic.test.ts` and
`threadActivity.test.ts` pass, and server, web and mobile typecheck.
- **Not verified:** the mobile client was not run. Mobile is covered by
its unit test only.

| Before | After |
| --- | --- |
| ![Before: stray one-agent cards and update
rows](https://github.com/user-attachments/assets/3d374a25-eac6-4f88-8d7e-4103ca8d1623)
| ![After: one spawn card for the whole
run](https://github.com/user-attachments/assets/fff11b4e-b393-4c5c-a587-32b2ebdc8672)
|

---
Written by an agent (Claude Code, claude-opus-5-5).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 1, 2026 — with ChatGPT Codex Connector
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 1, 2026 16:04

Dismissing prior approval to re-evaluate eb08085

@juliusmarminge

Copy link
Copy Markdown
Member

Thanks for working on this. We merged the orchestrator V2 rewrite in #2829, and we are closing this PR as part of that transition.

This change touches ClaudeAdapter.ts, which the V2 merge removed. Claude execution now runs through ClaudeAdapterV2.

Sorry for the extra work this creates. If the change is still needed on V2, please rebuild it on current main, verify it there, and open a new PR linking back here. We're closing the current implementation without assuming the underlying request is resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:M 30-99 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Claude subagent rows show the session's effort instead of the agent definition's

2 participants