Repository navigation
fix(claude-agent-sdk): test against 0.1.18 after older releases left PyPI - #987
Conversation
…PyPI claude-agent-sdk 0.1.9-0.1.17 were deleted from PyPI, so the test_claude_agent_sdk(0.1.10) session could no longer install and failed every nox shard. Move the old-version matrix entry to 0.1.18, the oldest installable release, and re-record its cassettes. The integration still supports >=0.1.10. Testing 0.1.18 exposed that CLIs bundled before 2.1 call the subagent tool "Task" and emit no task_* system messages, so subagent runs produced no task spans. Recognise both tool names and synthesize a task span from the subagent tool call when no task events arrive. Tests: - correct version gates that assumed only 0.1.10 vs latest - feature-detect SDK API fields instead of pinning versions - drop dead 0.1.10 branches, including silent early returns - run the bundled-subagent tests on 0.1.18 - do not save a recording without a result message, and size gate waits for replay vs live recording Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 27298384a5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "Codex (@codex) review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".
| ctx = self._contexts.get(str(tool_use_id)) if tool_use_id is not None else None | ||
| if ctx is None or not ctx.task_synthesized or ctx.task_span is None: | ||
| continue | ||
| ctx.task_span.end() |
There was a problem hiding this comment.
Close delegated LLM spans before synthesized task spans
When an older CLI completes a synthesized subagent, the delegated context can still have an open ctx.llm_span (as in the new 0.1.18 concurrent-subagent cassette, where each subagent's final tool-use assistant message is followed by the outer Task result). This line ends the parent TASK span immediately, while the child LLM span remains open until request cleanup after the overall result, producing a child whose end time is later than its parent's. Finalize the delegated LLM span, including its pending output/usage state, before ending the synthesized task.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 57a25bd. A delegated context's open LLM span is now finalized (pending output + usage-unknown marker) before its TASK span ends. This applied to the existing task_notification path too: the new assertion in test_concurrent_subagents_produce_parallel_llm_spans_with_correct_parenting (delegated LLM span must end no later than its task) failed on both 0.1.18 and latest before the fix.
…coverage Merge the interleaved and five-parallel subagent cassette tests into the concurrent subagent test, which now also asserts per-subagent tool pairing, task-to-Agent-tool parenting and end ordering, and that parallel Agent calls share one orchestrator LLM span despite relay user messages. Drop four FakeClaudeSDKClient subagent tests whose claims those cassettes now assert on real streams. Across 0.1.18 and latest this loses 1 of 1558 covered branches, reachable only from the fakes' unrealistic message shape. Also end a subagent's open LLM span before its TASK span closes. Both the task_notification path and the synthesized-task path left the last delegated LLM span open until request cleanup, so it outlived its parent. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nt tasks _llm_parent_for_message fell back to the most recent open task span for any assistant message without a parent_tool_use_id. Every supported SDK tags subagent messages with parent_tool_use_id, so the fallback only ever caught orchestrator turns, e.g. TaskOutput polling while background subagents run, and nested them under a subagent's task. Parent those turns to the root. The fallback was the only source of an LLM parent changing within one provider message, so the llm_parent_export merge guard and its field are now dead, as is _message_starts_subagent_tool. Remove them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude-agent-sdk 0.1.9–0.1.17 were deleted from PyPI, so
test_claude_agent_sdk(0.1.10)can no longer install and fails everynoxshard (seen on #986;mainbreaks the same way on its next run). Theexclude-newercutoff in the logs is not the cause.Matrix
cassettes/0.1.18/and removedcassettes/0.1.10/.min_versionstays0.1.10; comments explain why the tested floor is higher.Server.list_tools()).Tracing fix (old CLIs)
CLIs bundled before 2.1 (2.0.72 in SDK 0.1.18) call the subagent tool
Taskand emit notask_started/task_notificationmessages, so subagent runs produced no task spans. Both tool names are now recognised. When a subagent message arrives with no task span yet, a task span is synthesized from the tool call under itsTask/Agenttool span. It ends when the orchestrator gets that tool's result. In every latest cassettetask_startedarrives before the subagent's messages, so the fallback doesn't fire there.Tests
errorparsing in 0.1.29.verbatim_prompts,AssistantMessage.usage,ResultMessage.model_usage) are feature-detected instead of version-pinned.returns that reported passes without asserting.resultmessage, so a failed or hung recording can't leave a truncated cassette. Gate waits usetransport.wait_timeout(short on replay, long when recording).Test consolidation
Agent-tool parenting and end ordering, and that parallelAgentcalls share one orchestrator LLM span despite relay user messages.FakeClaudeSDKClientsubagent tests whose claims those cassettes now assert on real streams.Span ordering fix
A subagent's last LLM span stayed open until request cleanup after its TASK span closed. This happened on the existing
task_notificationpath (latest) and on the synthesized path. The LLM span is now finalized first.Orchestrator parenting fix
_llm_parent_for_messagefell back to the most recent open task span for any assistant message without aparent_tool_use_id. Every supported SDK tags subagent messages, so the fallback only caught orchestrator turns (e.g.TaskOutputpolling while background subagents run) and nested them under a subagent's task. Those turns now parent to the root, asserted intest_multiple_bundled_subagents_keep_outer_orchestration_separate. That made thellm_parent_exportmerge guard and_message_starts_subagent_tooldead, so they're removed.Validation
nox -s "test_claude_agent_sdk(0.1.18)"(CI mode): 37 passed, 6 skippednox -s "test_claude_agent_sdk(latest)"(CI mode): 43 passedmake check-stale-cassettes,make check-unused-cassettes INTEGRATIONS=claude_agent_sdk, pre-commit, pylint: cleanSeparate from #986's Anthropic
speedchange.🤖 Generated with Claude Code