Skip to content

Tool call changes - #1060

Draft
Akshay Sonawane (apsonawane) wants to merge 1 commit into
mainfrom
asonawane/tool-call
Draft

Tool call changes#1060
Akshay Sonawane (apsonawane) wants to merge 1 commit into
mainfrom
asonawane/tool-call

Conversation

@apsonawane

Copy link
Copy Markdown
Contributor

This pull request introduces several improvements and fixes to the handling of tool-calling and reasoning support for locally imported models, as well as enhancements to the chat session and prompt generation logic. The changes ensure that important metadata from local models is preserved, improve the processing of tool calls and reasoning blocks, and add better support for assistant tool calls in chat history.

Key changes include:

Tool-calling and Reasoning Metadata for Local Models

  • When importing local (BYOM) models, the system now merges relevant fields from their inference_model.json into the ModelInfo, preserving tool-calling and reasoning tags provided by the model author. [1] [2] [3]

Input Item and JSON Handling

  • Added a new FunctionCallInputItem type to more accurately represent function call inputs, updated the InputItem variant, and implemented corresponding JSON (de)serialization logic. The parser now distinguishes between function call inputs and outputs in the input array. [1] [2] [3] [4]

Chat Session and Prompt Processing

  • Improved chat session logic to handle cases where locally imported models lack catalog metadata, defaulting to standard tool-call markers when necessary. Adjusted prompt generation and tool-call parsing to better support reasoning models and continuous decoding. [1] [2] [3] [4] [5] [6] [7]

Assistant Tool Call History

  • Updated the chat history commit logic to ensure that assistant replies and their associated tool calls are stored together as a single message, improving replay and session continuity.

Prompt Generation Utilities

  • Added a new utility to serialize chat messages into the JSON format expected by model chat templates, including support for assistant tool calls. [1] [2] [3]

Reasoning Model Prompt Detection

  • Introduced logic to detect when a chat prompt opens with a reasoning marker, ensuring the stream splitter starts in the correct state for reasoning models.

Documentation:

  • Added a link to engineering notes describing the tool-calling fixes for MSBench and Qwen models.

@vercel

vercel Bot commented Sep 1, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
foundry-local Ready Ready Preview Sep 1, 2026 8:55pm UTC

Request Review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Tool-call inputs and reasoning output have correctness regressions, and the new documentation link is unresolved.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Improves C++ tool-calling, reasoning-stream handling, Responses API inputs, and BYOM metadata preservation.

Changes:

  • Preserves local-model tool/reasoning metadata and adds function-call inputs.
  • Enhances tool-call parsing, streaming, grammar guidance, and history replay.
  • Adds focused tests and documentation navigation.
File summaries
File Description
sdk_v2/cpp/test/internal_api/toolcalling/tool_call_utils_test.cc Tests malformed and aliased calls.
sdk_v2/cpp/test/internal_api/toolcalling/tool_call_stream_accumulator_test.cc Tests flush recovery.
sdk_v2/cpp/test/internal_api/toolcalling/grammar_test.cc Updates grammar expectations.
sdk_v2/cpp/test/internal_api/response_converter_test.cc Tests function-call inputs.
sdk_v2/cpp/test/internal_api/chat/chat_template_test.cc Tests tool-call history serialization.
sdk_v2/cpp/src/service/responses_handler.cc Emits and normalizes streamed calls.
sdk_v2/cpp/src/items/message_item.h Stores calls on messages.
sdk_v2/cpp/src/items/message_item.cc Copies stored calls.
sdk_v2/cpp/src/inferencing/generative/toolcalling/tool_call_utils.h Extends parser API.
sdk_v2/cpp/src/inferencing/generative/toolcalling/tool_call_utils.cc Adds parsing recovery and normalization.
sdk_v2/cpp/src/inferencing/generative/toolcalling/tool_call_stream_accumulator.h Recovers unterminated calls.
sdk_v2/cpp/src/inferencing/generative/toolcalling/grammar.cc Constrains guided text.
sdk_v2/cpp/src/inferencing/generative/openresponses/response_converter.cc Converts function-call inputs.
sdk_v2/cpp/src/inferencing/generative/chat/reasoning_stream_splitter.h Supports prefilled reasoning.
sdk_v2/cpp/src/inferencing/generative/chat/onnx_chat_generator.h Tracks reasoning-prefill state.
sdk_v2/cpp/src/inferencing/generative/chat/onnx_chat_generator.cc Detects prefilled reasoning and expands guidance.
sdk_v2/cpp/src/inferencing/generative/chat/chat_template.h Exposes message serialization.
sdk_v2/cpp/src/inferencing/generative/chat/chat_template.cc Serializes assistant calls.
sdk_v2/cpp/src/inferencing/generative/chat/chat_session.cc Updates parsing, streaming, and history.
sdk_v2/cpp/src/contracts/responses.h Adds function-call input contract.
sdk_v2/cpp/src/contracts/responses_json.cc Deserializes function-call inputs.
sdk_v2/cpp/src/catalog/azure_model_catalog.cc Merges BYOM metadata.
docs/README.md Links engineering notes.
Review details
  • Files reviewed: 23/23 changed files
  • Comments generated: 8
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

if (ctx.tool_output) {
// Keep marker-delimited calls out of the free-text branch so they must
// pass through the schema-constrained functioncall rule.
grammar << (known_tool_tokens ? "TEXT: /[^{<][^<]*/\n" : "TEXT: /[^{<][^{]*/\n");
Comment on lines +206 to +212
// Locally imported models may not have catalog metadata even when their
// chat template uses the standard Qwen tool-call markers.
if (tool_ctx.HasTools() && tool_ctx.tool_call_start.empty() && tool_ctx.tool_call_end.empty()) {
tool_ctx.supports_tool_calling = true;
tool_ctx.tool_call_start = "<tool_call>";
tool_ctx.tool_call_end = "</tool_call>";
}
: cached_tool_ctx_.reasoning_end)
: std::string());
: std::string(),
cached_generator_ && cached_generator_->PromptEndsInReasoning());
Comment on lines +893 to +896
auto tool_calls = assistant_reply ? std::move(assistant_reply->tool_calls)
: std::vector<ToolCallItem>{};
assistant_reply = msg;
assistant_reply->tool_calls = std::move(tool_calls);
Comment on lines +329 to +331
} else if (auto* fc = std::get_if<FunctionCallInputItem>(&input_item)) {
auto i = std::make_unique<ToolCallItem>(fc->call_id, fc->name, fc->arguments);
request.AddOwnedItem(std::move(i));
Comment on lines +327 to +332
// If a malformed call was left open before another call, parse the
// innermost complete block rather than combining both payloads.
size_t nested_start = text.rfind(tool_call_start, end_pos);
if (nested_start != std::string::npos && nested_start > start_pos) {
content_start = nested_start + tool_call_start.size();
}
Comment thread docs/README.md

Documentation for Foundry Local can be found in the following resources:

- [MSBench Tool Calling Fixes](MSBench%20Tool%20Calling%20Fixes.md): Engineering notes for the Responses API and tool-calling changes that enabled a local Qwen model to produce SWE-bench patches through MSBench.
Comment on lines +132 to +133
std::string text =
R"(<tool_call><exec_command","arguments":{"cmd":"ls"}<tool_call>{"name":"exec_command","args":{"cmd":"pwd"}}</tool_call>)";
struct MessageItem : Item {
flMessageRole role;
std::vector<MessagePart> content;
std::vector<ToolCallItem> tool_calls;

@skottmckay Scott McKay (skottmckay) Sep 2, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Does this need to be part of the MessageItem vs. multiple Items being provided in the Request (e.g. MessageItem and potentially multiple ToolResultItem instances) to keep them decoupled?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Or multiple ToolCallItem instances in the Response items.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants