You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
async for event in runner.run_async(
user_id=user_id,
session_id=session.id,
new_message=content,
run_config=RunConfig(save_input_blobs_as_artifacts=False),
):
print("\n================ EVENT ================")
print("raw event:", event)
if event.is_final_response() and event.content and event.content.parts:
for part in event.content.parts:
if getattr(part, "text", None):
parts.append(part.text)
final_usage = getattr(event, "usage_metadata", None)
print("prompt_tokens:", final_usage.prompt_token_count)
print("completion_tokens:", final_usage.candidates_token_count)
print("total_tokens:", final_usage.total_token_count)
What is broken? When LiteLLM proxies DeepSeek-V3, the model's tool calls are sometimes emitted as raw text wrapped in DeepSeek's proprietary special tokens (e.g., <|tool_calls_begin|>...) instead of being structured as standard tool_calls by LiteLLM. When this occurs, ADK-python's fallback JSON parser, _parse_tool_calls_from_text, fails to parse them into standard tool calls because the JSON object contains only the function arguments—with the function name situated outside the JSON block. As a result, _build_tool_call_from_json_dict rejects the payload because the "name" key is missing, causing the tool call to be silently dropped.
Recommendation: Should Fix (High Priority). DeepSeek-V3 is a widely used and high-performance model. Silently dropping tool calls severely impacts standard developer workflows and reliability. Merging or adapting PR fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens #5654 will resolve this cleanly.
Detailed Analysis
1. Root Cause Analysis ("What is broken?")
DeepSeek-V3 uses a custom token block to structure custom tool call emissions:
When LiteLLM returns this payload in the raw content field without translating it to standard formatted tool_calls, ADK-python delegates parsing to _split_message_content_and_tool_calls, which invokes _parse_tool_calls_from_text:
brace_index matches the starting { of the JSON block.
_JSON_DECODER.raw_decode successfully extracts the JSON dictionary {"work_dir_name": "bf01a09edc0f4c4ca376bc03d153445b"}.
Then, _build_tool_call_from_json_dict expects the JSON dictionary to have "name" and "arguments" keys. Because the JSON block parsed consists purely of the parameters dictionary (with the function name analysis_input parsed outside the JSON brace inside the <|tool_sep|> token), candidate.get("name") evaluates to None.
Consequently, _build_tool_call_from_json_dict returns None and the tool call is silently ignored, bubbling up to the user as raw text content instead of executable actions.
2. Existing Pull Requests ("Is there a linked PR that fixes this issue?")
The PR author (fuchun1010) implemented _parse_deepseek_tool_calls_from_text which specifically scans for <|tool_calls_begin|> and parses the custom format (handling markdown fences, single/multiple tool calls, and bare JSON).
It integrates it as a pre-pass step inside _parse_tool_calls_from_text.
The PR adds 8 robust unit-tests covering different permutations (e.g., code-fences, mixed formats, text-only) inside tests/unittests/models/test_litellm.py.
It is currently open, green on CI, and awaiting a review from the maintainers.
3. Recommendation
Recommendation: Should Fix (High Priority)
Rationale:
Impact: DeepSeek-V3 model integration with tool execution is a core feature. Intermittent parse failures and silent drops severely break user trust and standard developer workflows.
Activity
yfzhang1214 commentedon Mar 27, 2026
run script:
fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens
fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens
surajksharma07 commentedon Jun 5, 2026
/adk-issue-analyze
adk-bot commentedon Jun 5, 2026
GitHub Issue #5024 Analysis: LiteLLM + DeepSeek-V3 multi-tool calling fails: tool call parsing error
Executive Summary
<|tool_calls_begin|>...) instead of being structured as standardtool_callsby LiteLLM. When this occurs, ADK-python's fallback JSON parser, _parse_tool_calls_from_text, fails to parse them into standard tool calls because the JSON object contains only the function arguments—with the function name situated outside the JSON block. As a result, _build_tool_call_from_json_dict rejects the payload because the"name"key is missing, causing the tool call to be silently dropped.OPENDetailed Analysis
1. Root Cause Analysis ("What is broken?")
DeepSeek-V3 uses a custom token block to structure custom tool call emissions:
When LiteLLM returns this payload in the raw
contentfield without translating it to standard formattedtool_calls, ADK-python delegates parsing to _split_message_content_and_tool_calls, which invokes _parse_tool_calls_from_text:brace_indexmatches the starting{of the JSON block._JSON_DECODER.raw_decodesuccessfully extracts the JSON dictionary{"work_dir_name": "bf01a09edc0f4c4ca376bc03d153445b"}."name"and"arguments"keys. Because the JSON block parsed consists purely of the parameters dictionary (with the function nameanalysis_inputparsed outside the JSON brace inside the<|tool_sep|>token),candidate.get("name")evaluates toNone._build_tool_call_from_json_dictreturnsNoneand the tool call is silently ignored, bubbling up to the user as raw text content instead of executable actions.2. Existing Pull Requests ("Is there a linked PR that fixes this issue?")
fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens(OPEN)fuchun1010) implemented_parse_deepseek_tool_calls_from_textwhich specifically scans for<|tool_calls_begin|>and parses the custom format (handling markdown fences, single/multiple tool calls, and bare JSON)._parse_tool_calls_from_text.tests/unittests/models/test_litellm.py.3. Recommendation
test_litellm.pytests).Summary of Work Done
lite_llm.pyspecifically under_parse_tool_calls_from_textand_build_tool_call_from_json_dict.fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens
fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens
fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens
fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens
fix(litellm): parse DeepSeek-V3 proprietary inline tool-call tokens