Skip to content

fix: handle missing input_json in anthropic tool call parsing#6883

Open
BillionClaw wants to merge 1 commit intoAstrBotDevs:masterfrom
BillionClaw:clawoss/fix/6866-minimax-tool-json-parse
Open

fix: handle missing input_json in anthropic tool call parsing#6883
BillionClaw wants to merge 1 commit intoAstrBotDevs:masterfrom
BillionClaw:clawoss/fix/6866-minimax-tool-json-parse

Conversation

@BillionClaw
Copy link
Contributor

@BillionClaw BillionClaw commented Mar 24, 2026

Fixes #6866

Motivation / 问题

MiniMax 2.7 (using anthropic-compatible API) sends tool_use blocks where the tool call arguments are provided incrementally via input_json_delta events. The code accumulated these deltas into an input_json string, then parsed it with json.loads().

When json.loads() fails (e.g. due to deeply nested strings with many backslash escapes in heredoc-style shell commands), the code was silently yielding the tool call with empty {} input — because the input key was initialized to {} at the start of the tool_use block, and the if/else structure had no else branch to handle the case where input_json was never accumulated.

Fix / 改动

Added an explicit else branch in the tool call parsing block. When input_json is not present (which can happen when a provider sends no incremental deltas, or as a fallback when the accumulated string fails to parse but the else branch was previously missing), fall back to the initialized input dict.

Also clarified the except block comment to note that JSONDecodeError is caught and the tool call is skipped (not yielded with empty args).

Modifications

  • astrbot/core/provider/sources/anthropic_source.py: added else: tool_info[input] = tool_info.get(input, {}) to handle missing input_json

Verification

  • ruff check and format check pass with no issues
  • No new dependencies introduced

Summary by Sourcery

Ensure anthropic-compatible tool call parsing correctly handles cases where no input_json is present or cannot be decoded, avoiding emitting empty-argument tool calls.

Bug Fixes:

  • Prevent tool calls from being yielded with empty input when input_json is missing by falling back to the existing input dict.
  • Clarify behavior when JSON decoding of tool call arguments fails, explicitly skipping the affected tool call.

When a provider (e.g. MiniMax) sends a tool_use block without
incremental input_json_delta events, the accumulated input_json
key may not exist. Add an explicit else branch to fall back to
the input dict initialized at tool_use start instead of skipping
the else branch and having input remain as the raw {} init value
with a JSONDecodeError silently yielding empty tool args.
@dosubot dosubot bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Mar 24, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves an issue where Anthropic tool calls might be processed with empty arguments if the 'input_json' field was missing or failed to parse. It introduces a robust fallback to an initialized empty dictionary for tool input and clarifies the behavior when JSON parsing errors occur, ensuring more predictable and correct tool call handling.

Highlights

  • Missing input_json handling: Implemented a fallback mechanism for Anthropic tool call parsing when 'input_json' is not present, preventing tool calls from silently yielding empty arguments.
  • Error handling clarification: Updated the comment for 'JSONDecodeError' to explicitly state that the tool call is skipped, not yielded, upon parsing failure.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Consider adding a debug-level log when the input_json key is missing and the code falls back to tool_info.get('input', {}), so it's easier to diagnose providers that never send input_json or cases where input was set earlier.
  • It may be safer to distinguish between the case where input_json was never provided and the case where it failed to parse (e.g., track a flag when deltas are seen), so you can optionally surface different logging or behavior rather than treating both as a silent fallback to {}.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider adding a debug-level log when the `input_json` key is missing and the code falls back to `tool_info.get('input', {})`, so it's easier to diagnose providers that never send `input_json` or cases where `input` was set earlier.
- It may be safer to distinguish between the case where `input_json` was never provided and the case where it failed to parse (e.g., track a flag when deltas are seen), so you can optionally surface different logging or behavior rather than treating both as a silent fallback to `{}`.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dosubot dosubot bot added the area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. label Mar 24, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request aims to fix an issue in Anthropic tool call parsing when input_json is missing. The primary change introduces an else block to handle this scenario. My review indicates that this else block is redundant due to the way the tool_info data structure is initialized, making the change a no-op. I've provided a specific comment with a suggestion to simplify the code by removing the redundant block for better clarity and maintainability. The other change, which clarifies a comment in an error handling block, is a welcome improvement.

Comment on lines 422 to +425
if "input_json" in tool_info:
tool_info["input"] = json.loads(tool_info["input_json"])
else:
tool_info["input"] = tool_info.get("input", {})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The else block here is redundant. tool_info is guaranteed to have an "input": {} entry from its initialization on line 377. If "input_json" is not present, the existing empty input dictionary is correctly used by the subsequent code. Adding an else block that re-assigns the same value makes the code more verbose and potentially confusing, as it implies the "input" key might be missing.

To improve clarity and remove the redundancy, the else block can be removed.

Suggested change
if "input_json" in tool_info:
tool_info["input"] = json.loads(tool_info["input_json"])
else:
tool_info["input"] = tool_info.get("input", {})
if "input_json" in tool_info:
tool_info["input"] = json.loads(tool_info["input_json"])

@BillionClaw
Copy link
Contributor Author

Thank you for the review! Let me know if you need any changes.

@BillionClaw
Copy link
Contributor Author

Thanks for the thorough review:

  1. Redundant else block: Agreed — since is guaranteed to be initialized to before this code runs, the else block is unnecessary. I'll remove it.

  2. Debug logging and distinguishing cases: The suggestions about adding debug-level logging and tracking whether was missing vs. failed to parse are good improvements. I'll consider those for a follow-up to keep this PR focused.

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

Labels

area:provider The bug / feature is about AI Provider, Models, LLM Agent, LLM Agent Runner. size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]minimax2.7 authropic调用方式解析代码会报“工具调用参数 JSON 解析失败”

1 participant