Repository navigation
fix(server): Claude subagents keep their model after a usage-limit notice - #17097
jieyuexing wants to merge 1 commit into
Conversation
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a narrowly scoped Claude adapter bug fix that prevents synthetic usage-limit/API notice frames from replacing a subagent’s real model, with targeted regression coverage. It introduces no schema, security, deployment, product-default, or static-analysis changes. You can add or adjust custom eligibility rules. Learn more. |
Dismissing prior approval to re-evaluate af954a9
…tice Claude stamps its own notices, such as a usage-limit or API error message, with the model "<synthetic>". When such a frame arrived under a running background subagent, the adapter took it as the subagent's model snapshot and overwrote the real model, so the subagent card showed "<synthetic>". Ignore "<synthetic>" like an empty model, matching how the adapter already treats it for goal frames. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
af954a9 to
92aab78
Compare
|
Note Drafted by Claude Opus 5.5 in Claude Code (running inside T3 Code); reviewed and posted by @jieyuexing Rebased onto current The subagent model is now passed through
|
Dismissing prior approval to re-evaluate 92aab78
Problem
When Claude hits a usage limit or an API error while a background subagent is running, the CLI emits an assistant frame under that subagent's
parent_tool_use_idwithmodel: "<synthetic>".ClaudeAdapterV2treats every non-emptymessage.modelunder a subagent as that subagent's model snapshot. So it replaced the real model (for examplehaikuorclaude-opus-5-5) with<synthetic>, and the subagent card showed<synthetic>as its model.Seen on
0.0.46-nightly.20261007. A thread started 14 background subagents and 12 of them failed on a usage limit. 13 of the 14 subagent rows ended up withmodel = "<synthetic>". The one that kept its real model had completed before the limit.Fix
Treat
"<synthetic>"like an empty model when taking the subagent model snapshot. The same variable feeds both the update of a registered subagent and the pending-launch record (rememberPendingClaudeSubagentLaunch), so one check covers both paths. The adapter already treats"<synthetic>"as Claude's own notice for goal frames (nextClaudeGoal, and the goal check in the root-frame handler).This is a very small, focused fix for an obvious bug, so it is submitted without a prior issue under CONTRIBUTING.
<synthetic>is a sentinel, not a model, and the change does not affect any real model value.Verification
synthetic-aftercase to the existing parameterized testrecords the subagent model from %s without inheriting the parent override. The subagent is launched withmodel: "haiku", then a<synthetic>frame arrives under it, and the test asserts the model stayshaiku.expected '<synthetic>' to equal 'haiku'.vp test run apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.tspasses (158 tests).vp lintandvp fmt --checkon the two changed files are clean.tsc --noEmitinapps/serverreports no errors.Not covered: no live run against a rate-limited Claude account. #14670 / #14672 fix the same sentinel showing up in the Usage model list; this PR is the subagent card.
Model: Claude Opus 5.5 (1M context), harness: Claude Code running inside T3 Code.
🤖 Generated with Claude Code