Skip to content

Add ToolAdditionContent and ToolRemovalContent for positional tool changes - #7823

Open
PederHP wants to merge 2 commits into
dotnet:mainfrom
PederHP:feat/ai-tool-changes-content
Open

PederHP wants to merge 2 commits into
dotnet:mainfrom
PederHP:feat/ai-tool-changes-content

Conversation

@PederHP

@PederHP PederHP commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Draft implementation of #7822, to make the proposal concrete. Open for discussion. The API isn't settled.

What changes

  • ToolAdditionContent / ToolRemovalContent (experimental, MEAI001) in Microsoft.Extensions.AI.Abstractions.
    • Each describes a tool becoming available, or unavailable, at the content's position in the history.
    • ToolAdditionContent.Tool is an AIFunctionDeclaration. It serializes as name, description and JSON schemas, and deserializes to a declaration.
    • Both are registered in AIJsonUtilities.DefaultOptions the way experimental content types were before stabilization (toolAddition, toolRemoval), with the [JsonDerivedType] lines left commented on AIContent.
  • OpenAI Responses client.
    • Additions in a message are sent as one additional_tools input item (role: "developer") ahead of that message's items. The OpenAI SDK has no type for it, so the JSON is built by hand, as for namespace and tool_search.
    • A tool whose first change in the history is an addition is left out of the top-level tools.
    • Removals have no Responses API form and aren't sent.
  • OpenAI Chat Completions client. It has no positional form, so the changes are applied to the tools it sends, and a message that held only tool changes is left out.
  • An internal helper, ToolChanges, in Microsoft.Extensions.AI.OpenAI, shared by both clients. Whether it should become public for adapters in other repositories is one of the open questions in [API Proposal]: Add and remove tools mid-conversation without invalidating the prompt cache #7822.

FunctionInvokingChatClient is unchanged. ChatOptions.Tools stays the set of invocable tools.

Testing

  • Unit tests for both content types: construction, and JSON round trips, both concrete and as AIContent.
  • Unit tests checking the exact wire request for the Responses mapping and the Chat Completions fallback.
  • The Microsoft.Extensions.AI.Abstractions and OpenAI test suites pass on net10.0.
  • Live check of the Responses mapping on gpt-5.4-mini and gpt-5.5. A tool introduced by a mid-conversation message with ToolAdditionContent:
    • Was accepted.
    • Read the earlier prefix from cache (3,072 and 2,560 cached tokens), where adding the same tool to ChatOptions.Tools read 0.
    • Was invoked by FunctionInvokingChatClient.

Generated with Claude Opus 5.5 (Claude Code)

Microsoft Reviewers: Open in CodeFlow

…anges

Adding or removing a tool through ChatOptions.Tools changes the tool
definitions at the start of every request and invalidates the prompt
cache. Providers now accept tool changes at a position in the
conversation instead. These experimental content types describe such a
change, ChatOptions.Tools stays the set of invocable tools, and the
OpenAI Responses client sends additions as an additional_tools item.
The Chat Completions client, which has no positional form, applies the
changes to the tools it sends.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ERjP6o4DUJYLsnWqftSufm
@github-actions github-actions Bot added the area-ai Microsoft.Extensions.AI libraries label Oct 10, 2026
@PederHP
PederHP marked this pull request as ready for review October 10, 2026 12:51
@PederHP
PederHP requested review from a team as code owners October 10, 2026 12:51
Copilot AI balanced review requested due to automatic review settings October 10, 2026 12:51

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-mode inconsistencies and repeated enumeration can produce invalid or incomplete requests.

5 open findings
What changed in this PR

Adds experimental positional tool additions/removals to AI abstractions and maps them to OpenAI APIs.

Changes:

  • Adds serializable tool-change content types.
  • Implements Responses positional additions and Chat Completions fallback behavior.
  • Adds API baselines and request/serialization tests.
File Description
test/​Libraries/​Microsoft.Extensions.AI.OpenAI.Tests/​OpenAIResponseClientTests.cs Tests Responses wire mapping.
test/​Libraries/​Microsoft.Extensions.AI.OpenAI.Tests/​OpenAIChatClientTests.cs Tests Chat Completions fallback.
test/​Libraries/​Microsoft.Extensions.AI.Abstractions.Tests/​Contents/​ToolRemovalContentTests.cs Tests removal content.
test/​Libraries/​Microsoft.Extensions.AI.Abstractions.Tests/​Contents/​ToolAdditionContentTests.cs Tests addition content.
src/​Shared/​DiagnosticIds/​DiagnosticIds.cs Registers the experiment identifier.
src/​Libraries/​Microsoft.Extensions.AI.OpenAI/​ToolChanges.cs Implements shared tool-change processing.
src/​Libraries/​Microsoft.Extensions.AI.OpenAI/​OpenAIResponsesChatClient.cs Emits positional additional_tools items.
src/​Libraries/​Microsoft.Extensions.AI.OpenAI/​OpenAIChatClient.cs Applies fallback tool changes.
src/​Libraries/​Microsoft.Extensions.AI.Abstractions/​Utilities/​AIJsonUtilities.Defaults.cs Registers experimental JSON types.
src/​Libraries/​Microsoft.Extensions.AI.Abstractions/​Microsoft.Extensions.AI.Abstractions.json Adds API baseline entries.
src/​Libraries/​Microsoft.Extensions.AI.Abstractions/​Contents/​ToolRemovalContent.cs Defines removal content.
src/​Libraries/​Microsoft.Extensions.AI.Abstractions/​Contents/​ToolAdditionContent.cs Defines addition content and serialization.
src/​Libraries/​Microsoft.Extensions.AI.Abstractions/​Contents/​AIContent.cs Documents future polymorphic registration.

🧠 Review effort: Balanced


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

Comment thread src/Libraries/Microsoft.Extensions.AI.OpenAI/ToolChanges.cs
Comment thread src/Libraries/Microsoft.Extensions.AI.OpenAI/ToolChanges.cs
Comment thread src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ToolRemovalContent.cs Outdated
Comment thread test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs Outdated
@dotnet-comment-bot

Copy link
Copy Markdown
Collaborator

‼️ Found issues ‼️

Project Coverage Type Expected Actual
Microsoft.Extensions.Diagnostics.Testing Line 99 98.65 🔻
Microsoft.Extensions.Telemetry Line 93 92.32 🔻
Microsoft.Extensions.AI.OpenAI Line 75 68.97 🔻
Microsoft.Extensions.AI.OpenAI Branch 75 59.33 🔻
Microsoft.Extensions.DataIngestion.MarkItDown Line 75 4.46 🔻
Microsoft.Extensions.DataIngestion.MarkItDown Branch 75 0 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring Line 99 96.03 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring Branch 99 92.76 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring.Kubernetes Line 99 97.73 🔻
Microsoft.Extensions.ServiceDiscovery.Dns Line 75 69.93 🔻
Microsoft.Extensions.ServiceDiscovery Line 75 67.21 🔻
Microsoft.Extensions.ServiceDiscovery Branch 75 71.43 🔻
Microsoft.Extensions.ServiceDiscovery.Abstractions Line 75 42.11 🔻
Microsoft.Extensions.ServiceDiscovery.Abstractions Branch 75 42.86 🔻
Microsoft.Extensions.ServiceDiscovery.Yarp Line 75 73.85 🔻
Microsoft.Extensions.ServiceDiscovery.Yarp Branch 75 70 🔻
Microsoft.Extensions.VectorData.Abstractions Line 75 37.39 🔻
Microsoft.Extensions.VectorData.Abstractions Branch 75 22.73 🔻

🎉 Good job! The coverage increased 🎉
Update MinCodeCoverage in the project files.

Project Expected Actual
Microsoft.Extensions.Http.Diagnostics 94 95
Microsoft.Gen.BuildMetadata 97 100
Microsoft.Gen.MetadataExtractor 57 73
Microsoft.Gen.MetricsReports 67 69
Microsoft.Extensions.AI.Abstractions 82 86
Microsoft.Extensions.AI.Evaluation.NLP 0 78
Microsoft.Extensions.Caching.Hybrid 82 85
Microsoft.Extensions.DataIngestion 75 89
Microsoft.Extensions.DataIngestion.Markdig 75 90
Microsoft.Extensions.Http.Resilience 97 100

Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1630779&view=codecoverage-tab

- Materialize the messages before scanning them for tool changes, so a
  sequence that can only be enumerated once isn't consumed before the
  request is built (Responses and Chat Completions).
- Throw when ToolMode requires a function that the history removes, rather
  than sending a tool_choice for a function missing from the tools.
- Clarify the ToolAdditionContent and ToolRemovalContent remarks.
- Have the Responses test remove a tool that is actually declared, and add
  tests for single-pass histories, streaming, and the required-function case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AUeyFfwBuvSBBsvYtTiyRd
@dotnet-comment-bot

Copy link
Copy Markdown
Collaborator

‼️ Found issues ‼️

Project Coverage Type Expected Actual
Microsoft.Extensions.Diagnostics.Testing Line 99 98.65 🔻
Microsoft.Extensions.Telemetry Line 93 92.32 🔻
Microsoft.Extensions.AI.OpenAI Line 75 69.04 🔻
Microsoft.Extensions.AI.OpenAI Branch 75 59.42 🔻
Microsoft.Extensions.DataIngestion.MarkItDown Line 75 4.46 🔻
Microsoft.Extensions.DataIngestion.MarkItDown Branch 75 0 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring Line 99 96.03 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring Branch 99 92.76 🔻
Microsoft.Extensions.Diagnostics.ResourceMonitoring.Kubernetes Line 99 97.73 🔻
Microsoft.Extensions.ServiceDiscovery.Dns Line 75 68.32 🔻
Microsoft.Extensions.ServiceDiscovery Line 75 67.21 🔻
Microsoft.Extensions.ServiceDiscovery Branch 75 71.43 🔻
Microsoft.Extensions.ServiceDiscovery.Abstractions Line 75 42.11 🔻
Microsoft.Extensions.ServiceDiscovery.Abstractions Branch 75 42.86 🔻
Microsoft.Extensions.ServiceDiscovery.Yarp Line 75 73.85 🔻
Microsoft.Extensions.ServiceDiscovery.Yarp Branch 75 70 🔻
Microsoft.Extensions.VectorData.Abstractions Line 75 37.39 🔻
Microsoft.Extensions.VectorData.Abstractions Branch 75 22.73 🔻

🎉 Good job! The coverage increased 🎉
Update MinCodeCoverage in the project files.

Project Expected Actual
Microsoft.Extensions.Http.Diagnostics 94 95
Microsoft.Gen.BuildMetadata 97 100
Microsoft.Gen.MetadataExtractor 57 73
Microsoft.Gen.MetricsReports 67 69
Microsoft.Extensions.AI.Abstractions 82 86
Microsoft.Extensions.AI.Evaluation.NLP 0 78
Microsoft.Extensions.Caching.Hybrid 82 89
Microsoft.Extensions.DataIngestion 75 89
Microsoft.Extensions.DataIngestion.Markdig 75 90
Microsoft.Extensions.Http.Resilience 97 100

Full code coverage report: https://dev.azure.com/dnceng-public/public/_build/results?buildId=1630819&view=codecoverage-tab

This branch has not been deployed

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

Labels

area-ai Microsoft.Extensions.AI libraries

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants