fix(studio): coerce tool-call arguments before replaying to custom endpoints (#9039) by Souravrajvi0 · Pull Request #9300 · unslothai/unsloth · GitHub
Skip to content

fix(studio): coerce tool-call arguments before replaying to custom endpoints (#9039) - #9300

Closed
Souravrajvi0 wants to merge 2 commits into
unslothai:mainfrom
Souravrajvi0:feat/fix-tool-call-args-custom-endpoint-9039-b25b
Closed

fix(studio): coerce tool-call arguments before replaying to custom endpoints (#9039)#9300
Souravrajvi0 wants to merge 2 commits into
unslothai:mainfrom
Souravrajvi0:feat/fix-tool-call-args-custom-endpoint-9039-b25b

Conversation

@Souravrajvi0

Copy link
Copy Markdown
Contributor

Summary

Fixes #9039: tool calling via a custom OpenAI-compatible endpoint no longer poisons the chat history with malformed tool_calls[].function.arguments, which caused invalid_request_error on every follow-up send.

Root cause

When Studio proxies to a custom endpoint (vLLM, llama.cpp, etc.) and runs the tool loop, assistant tool-call arguments were replayed verbatim upstream. Two common failure modes:

  1. Concatenated streaming fragments — delta index restarts produce strings like '{"query":"first"}{"query":"second"}' that are not valid JSON.
  2. Dict-shaped arguments — some clients send function.arguments as an object instead of the OpenAI wire-format JSON string.

Strict endpoints reject those with invalid tool call arguments. Once that turn is in history, every subsequent request fails and the chat freezes.

The frontend already had toolCallReplayArguments (#8754); the backend proxy/tool loop did not.

Fix

  • Add coerce_tool_call_replay_arguments() and coerce_messages_tool_calls_for_wire() mirroring the frontend helper.
  • Apply coercion in:
    • studio_tool_loop.py (tool loop replay to external providers)
    • _build_external_messages() (outbound messages to custom endpoints)
    • external_provider.py (after markup neutralization for template-applying providers)

Test plan

…dpoints (unslothai#9039)

Malformed streamed tool-call JSON (concatenated delta fragments, dict-shaped
arguments) was forwarded verbatim to OpenAI-compatible custom endpoints and
poisoned every follow-up turn with invalid_request_error. Mirror the frontend
toolCallReplayArguments helper on the backend and apply it in the external
message builder, provider proxy, and studio tool loop replay path.
@oobabooga

Copy link
Copy Markdown
Member

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 869f939392

ℹ️ 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 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 address that feedback".

"""
if isinstance(args_text, str) and args_text:
try:
json.loads(args_text)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Catch recursion while validating replay arguments

When a custom endpoint streams a syntactically valid but deeply nested argument value, json.loads(args_text) can raise RecursionError. _normalized_call explicitly catches this condition so a pathological provider response does not terminate the tool loop, but this newly added second parse lets it escape, causing a server error mid-stream instead of replaying the safely wrapped structured arguments. Catch RecursionError here and proceed to the fallback.

Useful? React with 👍 / 👎.

@oobabooga

Copy link
Copy Markdown
Member

I believe the issue this PR aims to fix is already solved on main, see #9039 (comment).

@Souravrajvi0

Copy link
Copy Markdown
Contributor Author

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Tool calling fails with "invalid tool call arguments (invalid_request_error)" on every chat via custom endpoint

3 participants