fix(claude-agent-sdk): use msg_id for tool-call parent_message_id on fallback path (#2118)#2153
Conversation
…fallback path The non-streaming fallback branch (how a programmatic subagent's own turn arrives, as a complete AssistantMessage) computes the correct assistant message id (msg_id) to build/upsert that message, but passes the stale current_message_id — already None on this path — into handle_tool_use_block(), so the tool call's TOOL_CALL_START carries no parent_message_id. Fixes ag-ui-protocol#2118
|
@jpr5 — this one wasn't pre-discussed on the issue (no response there), but the fix is small and self-contained, so I went ahead and opened it. Would appreciate a look when you have a moment. |
…gent-parent-message-id
BenTaylorDev
left a comment
There was a problem hiding this comment.
Verified locally (bootstrapped the Python package and ran it):
- Correct fix: hoisting
msg_id = current_message_id or str(uuid.uuid4())above theAssistantMessage-only branch means the tool-use block'sparent_message_idis the same id used to build the assistant message, so a fallback-path tool call now points at its containing message instead ofNone(#2118). It also stays consistent with the streaming path, and theUserMessagecase is harmless (tool_use blocks only appear inAssistantMessage, so the loop won't match there). - RED→GREEN confirmed: reverting just
parent_message_id=msg_idback tocurrent_message_idfails the new test withassert None is not None; the fix passes it. - The test is solid — it asserts the id is non-null, is not the SDK's
parent_tool_use_id, and is a real id present in the run'sMESSAGES_SNAPSHOT(not a placeholder). - Full suite: 107 passed.
One coordination note (not a change request): this overlaps #2152, which edits the same fallback region — it adds unstreamed_fallback_ids.add(msg_id) right after the msg_id = … line inside the AssistantMessage branch, whereas this PR hoists msg_id out of that branch. They don't conflict semantically, but whichever lands second will need a small rebase. Worth sequencing them since both are yours.
I bless the code with a glad heart.
Python Preview PackagesVersion
Install with uvAdd the TestPyPI index to your [[tool.uv.index]]
name = "testpypi"
url = "https://test.pypi.org/simple/"
explicit = trueThen install the packages you need: # Core SDK
uv add 'ag-ui-protocol==0.0.0.dev1783839093' --index testpypi
# Integrations (each already depends on the matching ag-ui-protocol preview)
uv add 'ag-ui-langgraph==0.0.0.dev1783839093' --index testpypi
uv add 'ag-ui-crewai==0.0.0.dev1783839093' --index testpypi
# NOTE: ag-ui-agent-spec depends on pyagentspec (git-only, not on PyPI).
# You will need to install pyagentspec separately from its git repo.
uv add 'ag-ui-agent-spec==0.0.0.dev1783839093' --index testpypi
uv add 'ag_ui_adk==0.0.0.dev1783839093' --index testpypi
uv add 'ag_ui_strands==0.0.0.dev1783839093' --index testpypiInstall with pippip install \
--index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
ag-ui-protocol==0.0.0.dev1783839093
Commit: 3f6cf92 |
@ag-ui/a2a-middleware
@ag-ui/a2ui-middleware
@ag-ui/event-throttle-middleware
@ag-ui/mcp-apps-middleware
@ag-ui/mcp-middleware
@ag-ui/a2a
@ag-ui/adk
@ag-ui/ag2
@ag-ui/agno
@ag-ui/aws-strands
@ag-ui/claude-agent-sdk
@ag-ui/crewai
@ag-ui/langchain
@ag-ui/langgraph
@ag-ui/llamaindex
@ag-ui/mastra
@ag-ui/pydantic-ai
@ag-ui/vercel-ai-sdk
@ag-ui/watsonx
@ag-ui/a2ui-toolkit
create-ag-ui-app
@ag-ui/client
@ag-ui/core
@ag-ui/encoder
@ag-ui/proto
commit: |
Fixes #2118.
Changes
msg_idonce, outside theAssistantMessage-only branch, inthe non-streaming fallback path
msg_id(not the stalecurrent_message_id, alreadyNonehere)as
parent_message_idtohandle_tool_use_block()Testing
test_subagent_tool_call_gets_parent_message_id; confirmed itfails on the pre-fix code (
parent_message_idisNone)