.NET: dotnet: Add server-side Foundry Toolbox support and fix SDK beta.4 br…#5450
.NET: dotnet: Add server-side Foundry Toolbox support and fix SDK beta.4 br…#5450alliscode merged 11 commits intomicrosoft:mainfrom
Conversation
…eaking changes Add FoundryToolbox and AIProjectClient extensions to Microsoft.Agents.AI.Foundry.Hosting for server-side toolbox tool integration matching Python's FoundryChatClient.get_toolbox() pattern. Tools are fetched from the Foundry project SDK and passed as server-side tools in the Responses API request. New files: - FoundryToolbox.cs: Core implementation using AgentAdministrationClient SDK - AIProjectClientToolboxExtensions.cs: Extension methods on AIProjectClient - Agent_Step25_ToolboxServerSideTools sample with create helper and combine flow - 19 unit tests covering param validation, conversion, sanitization, and extensions SDK breaking changes (Azure.AI.AgentServer.Responses beta.3 -> beta.4): - FunctionToolCallOutputResource renamed to OutputItemFunctionToolCallOutput - AzureAIAgentServerResponsesModelFactory made internal, replaced with direct constructors - ResponseUsage constructor now requires non-null token details parameters Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds .NET support for Foundry “toolbox” server-side tools (matching the Python get_toolbox() pattern) and updates the codebase to accommodate Azure.AI.AgentServer.Responses beta.4 SDK breaking changes.
Changes:
- Introduces
FoundryToolbox+AIProjectClientextension methods to fetch toolbox versions/tools and convert them toAIToolinstances for Responses API server-side tools. - Updates Foundry.Hosting converters/tests for Azure.AI.AgentServer.Responses beta.4 model/type renames and constructor changes.
- Adds a new Foundry toolbox sample and expands unit test coverage + test data for toolbox scenarios.
Show a summary per file
| File | Description |
|---|---|
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/TestDataUtil.cs | Adds helpers to load new toolbox-related JSON fixtures. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/TestData/ToolboxRecordResponse.json | Adds mock toolbox record payload (default version resolution). |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/TestData/ToolboxVersionResponse.json | Adds mock toolbox version payload for conversion tests. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/TestData/ToolboxVersionWithDecorationFields.json | Adds payload exercising sanitization of decoration fields on hosted tools. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Microsoft.Agents.AI.Foundry.UnitTests.csproj | Pins Azure.AI.Projects beta for toolbox APIs; copies new test data. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/WorkflowIntegrationTests.cs | Replaces removed model factory usage with direct CreateResponse construction. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/OutputConverterTests.cs | Updates tests to construct CreateResponse directly. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/InputConverterTests.cs | Updates tests for renamed output item types and direct constructors. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/FoundryToolboxTests.cs | Adds unit tests covering toolbox fetch, conversion, and sanitization behavior. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/AgentFrameworkResponseHandlerTests.cs | Updates request creation patterns for beta.4 SDK changes. |
| dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/AgentFrameworkResponseHandlerTelemetryTests.cs | Updates request creation patterns for beta.4 SDK changes. |
| dotnet/src/Microsoft.Agents.AI.Foundry.Hosting/OutputConverter.cs | Adjusts ResponseUsage creation for new required token-details parameters. |
| dotnet/src/Microsoft.Agents.AI.Foundry.Hosting/InputConverter.cs | Updates output item handling for renamed tool-call output type. |
| dotnet/src/Microsoft.Agents.AI.Foundry.Hosting/FoundryToolbox.cs | Adds the core toolbox fetch + tool sanitization/conversion implementation. |
| dotnet/src/Microsoft.Agents.AI.Foundry.Hosting/AIProjectClientToolboxExtensions.cs | Adds AIProjectClient extension methods to fetch toolbox versions/tools. |
| dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/README.md | Documents the new toolbox server-side tools sample. |
| dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Program.cs | Implements sample flows for loading/combining toolboxes and running an agent. |
| dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Agent_Step25_ToolboxServerSideTools.csproj | Adds the new sample project and pins Azure.AI.Projects beta. |
| dotnet/agent-framework-dotnet.slnx | Adds the new sample project to the solution. |
| dotnet/Directory.Packages.props | Bumps Azure.AI.AgentServer.* package versions to beta.4-compatible set. |
Copilot's findings
- Files reviewed: 20/20 changed files
- Comments generated: 3
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 89%
✓ Correctness
This PR bumps Azure.AI.AgentServer.* package versions, adds Foundry toolbox support (FoundryToolbox, AIProjectClientToolboxExtensions), adapts to SDK type renames (FunctionToolCallOutputResource → OutputItemFunctionToolCallOutput, factory → direct constructors), and adds comprehensive unit tests. The changes are internally consistent and correctly handle the SDK API migration. No correctness bugs were found.
✓ Security Reliability
This PR adds Foundry toolbox support (new FoundryToolbox class and AIProjectClient extensions), bumps Azure SDK package versions, and adapts existing code to renamed/changed API types. From a security and reliability perspective, the changes are sound: input validation uses Throw.IfNull/IfNullOrWhitespace consistently, JSON round-tripping in SanitizeAndConvert uses standard Azure SDK ModelReaderWriter patterns, no secrets are hardcoded, environment variables are used for configuration in the sample, and DefaultAzureCredential is used for authentication. The VersionOverride in sample/test csproj files (2.1.0-beta.1 vs central 2.0.0) is intentional for toolbox API access. No security or reliability issues found.
✓ Test Coverage
The PR adds substantial test coverage for the new FoundryToolbox functionality (parameter validation, conversion, HTTP integration, extension methods). However, there are two notable test coverage gaps: (1) the error path where GetToolboxVersionCoreAsync throws InvalidOperationException when a toolbox has no default version is untested, and (2) the test named GetToolsAsync_ReturnsConvertedAIToolsAsync actually calls GetToolboxVersionAsync + ToAITools() instead of the GetToolsAsync convenience method, leaving that method without a functional test. Additionally, the SanitizeAndConvert decoration-stripping test uses a weak assertion that only checks NotNull rather than verifying the fields were actually removed.
✗ Design Approach
The toolbox-loading API addition is directionally sound, but two parts of the change take the wrong design approach: the new sample provisions its toolbox by deleting any existing fixed-name toolbox on every run, which is destructive for shared Foundry projects, and the
ResponseUsageupdate adapts to the new SDK shape by hardcoding detail objects to zero instead of preserving the cached/reasoning token counts the framework already carries throughUsageDetailselsewhere.
Flagged Issues
- dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Program.cs:117 unconditionally deletes and recreates a fixed-name toolbox on every run, destroying existing project state in shared Foundry projects. Use create-if-missing semantics or a unique sample-specific toolbox name so the sample doesn't mutate real resources.
- dotnet/src/Microsoft.Agents.AI.Foundry.Hosting/OutputConverter.cs:261-265 hardcodes token detail objects to zero, discarding
UsageDetails.AdditionalCountsdata that the framework preserves elsewhere (e.g.,MessageMerger.cs:278-303). Map these counts intoResponseUsageInputTokensDetailsandResponseUsageOutputTokensDetails, following the same pattern used inAgentResponseExtensions.cs:247-262.
Automated review by alliscode's agents
alliscode
left a comment
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 78%
✓ Correctness
This PR bumps Azure.AI.AgentServer.* SDK packages, adapts code to breaking API changes (type renames, constructor signature changes), and adds new FoundryToolbox functionality for fetching and converting Foundry toolbox tools into AITool instances for server-side use. The changes are well-structured with thorough parameter validation, proper error handling, and comprehensive tests. I found no correctness bugs — the type renames (FunctionToolCallOutputResource → OutputItemFunctionToolCallOutput), constructor changes (ResponseUsage), and new toolbox sanitization logic all appear correct based on verified code patterns in the repository.
✓ Security Reliability
This PR adapts to Azure SDK version bumps (Azure.AI.AgentServer.Core/Invocations/Responses), adds new FoundryToolbox functionality for fetching and converting Foundry toolbox tools to AITool instances, and updates tests for renamed SDK types (FunctionToolCallOutputResource → OutputItemFunctionToolCallOutput, factory methods → direct constructors). The code follows established patterns: proper input validation via Throw.IfNull/IfNullOrWhitespace, correct async/ConfigureAwait(false) usage, and comprehensive test coverage including parameter validation, mock HTTP integration, and sanitization of decoration fields. No security vulnerabilities, injection risks, resource leaks, or unhandled failure modes were identified.
✓ Test Coverage
The PR adds Foundry toolbox support (FoundryToolbox, AIProjectClientToolboxExtensions) with good test coverage including parameter validation, conversion, mock HTTP integration, and extension method tests. Existing tests were updated to accommodate SDK type renames. However, there are two notable test coverage gaps: (1) no test for GetToolboxVersionCoreAsync when DefaultVersion is null on the toolbox record (which throws InvalidOperationException), and (2) the SanitizeAndConvert tests only cover function and code_interpreter tool types but not the custom tool type (which is also exempted from stripping) or other non-function types like mcp/web_search/file_search. Additionally, the GetToolsAsync path through the static FoundryToolbox class is only tested indirectly — the direct static method is never exercised end-to-end with mock HTTP.
✓ Design Approach
This PR adds Foundry toolbox support via a new
FoundryToolboxclass andAIProjectClientToolboxExtensions, bumps three Azure.AI.AgentServer.* package versions, and adapts to breaking SDK changes (type renames, removed factory methods). The design is generally sound. One notable issue:ConvertUsageinOutputConverter.csnow hardcodes0forinputTokensDetailsandoutputTokensDetailswhile also failing to carry forwardexisting.InputTokensDetails/existing.OutputTokensDetailsduring accumulation — meaning that if a futureUsageDetailssource ever provides cached or audio token counts, they will be silently dropped on the second and subsequent accumulation pass. TheSanitizeAndConvertJSON round-trip workaround is an unavoidable consequence of an external API mismatch (toolbox API adds decoration fields that the Responses API rejects on hosted tool types), is clearly documented, and has no cleaner alternative given sealed SDK model types. The shift fromAzureAIAgentServerResponsesModelFactoryfactory methods to direct object initializers throughout tests is correctly driven by the SDK bump removing those factory overloads.
Suggestions
- Expand SanitizeAndConvert test coverage beyond "function" and "code_interpreter" to include the "custom" tool type (which shares the preservation path at FoundryToolbox.cs line 162) and an MCP tool type with decoration fields to verify stripping works for the real-world hosted tool scenario mentioned in the sample and code comments.
- In ConvertUsage (OutputConverter.cs), the accumulation of
existingdiscardsexisting.InputTokensDetailsandexisting.OutputTokensDetails, replacing them with hardcoded 0. The accumulation loop already carries forward raw token counts fromexisting; the details should be treated consistently so that if UsageDetails gains cached/audio token fields, the second call in a multi-update stream does not silently zero out values from the first call.
Automated review by alliscode's agents
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Static local functions cannot capture top-level variables. Thread the endpoint parameter through Main, CombineToolboxes, and CreateSampleToolboxAsync. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Automated Code Review
Reviewers: 4 | Confidence: 87%
✗ Correctness
The PR adds Foundry toolbox support with new extension methods, tests, and a sample. Beyond the existing unresolved review comments (which I will not duplicate), I found two new issues: (1) the sample's
CreateSampleToolboxAsyncis astaticlocal function that references the enclosing top-level variableendpoint, which is a C# compile error (CS8421), and (2) the README documents env var names (AZURE_AI_PROJECT_ENDPOINT,AZURE_AI_MODEL_DEPLOYMENT_NAME) that don't match the code (FOUNDRY_PROJECT_ENDPOINT_2,FOUNDRY_MODEL), and the error message at line 28 also references the wrong env var name.
✗ Security Reliability
The PR adds Foundry toolbox support with new extension methods, a sample, and corresponding tests. The most notable new issue is a misleading environment variable name in the sample: the code reads
FOUNDRY_PROJECT_ENDPOINT_2but the error message and README both referenceAZURE_AI_PROJECT_ENDPOINT, which will confuse users who follow the documentation. The existing unresolved comments about hardcoded zero usage details, whitespace validation on DefaultVersion, the sample re-creating clients, and README wording remain valid and are not restated here.
✗ Test Coverage
The new FoundryToolbox feature has good test coverage for the happy paths (parameter validation, tool conversion, HTTP integration with mocks, extension methods). However, there are two notable test coverage gaps: (1) the error path in
GetToolboxVersionCoreAsyncwhereDefaultVersionis null is not tested, and (2) the existing usage/token tests inOutputConverterTestsonly assert that aResponseCompletedEventexists — none verify the actual token counts or the newly addedinputTokensDetails/outputTokensDetailsfields, making theConvertUsagechange effectively untested beyond 'no exception'.
✗ Design Approach
Beyond the issues already raised on this PR, I found one additional design problem: the new Step25 sample exposes a one-off environment-variable contract (
FOUNDRY_PROJECT_ENDPOINT_2/FOUNDRY_MODEL) that diverges from the rest of the Foundry samples and from its own README. That leaks a local setup detail into a public sample, so readers who follow the documented sample conventions will configure the wrong variables and fail before they reach the toolbox scenario itself.
Flagged Issues
- Program.cs:
CreateSampleToolboxAsyncis declaredstaticbut captures the top-level variableendpoint, producing CS8421. Either removestaticor passendpointas a parameter.
Suggestions
- The existing usage tests (
ConvertUpdatesToEventsAsync_UsageContent_IncludesUsageInCompletedAsync,MultipleUsageUpdates_AccumulatesTokensAsync) only assert that aResponseCompletedEventis emitted — they never verify actual InputTokens/OutputTokens/TotalTokens values. Adding assertions on theUsageproperty would catch regressions, especially given theConvertUsagechanges adding detail objects.
Automated review by alliscode's agents
…sync Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…xServerSideTools/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…xServerSideTools/Program.cs Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
…xServerSideTools/Program.cs Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
…gent-framework into toolbox-improvements
…dcoding zeros Extract InputTokenDetails.CachedTokenCount and OutputTokenDetails.ReasoningTokenCount from UsageDetails.AdditionalCounts, matching the pattern in AgentResponseExtensions. Also accumulate detail counts when merging with existing usage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add FoundryToolbox and AIProjectClient extensions to Microsoft.Agents.AI.Foundry.Hosting for server-side toolbox tool integration matching Python's FoundryChatClient.get_toolbox() pattern. Tools are fetched from the Foundry project SDK and passed as server-side tools in the Responses API request.
New files:
SDK breaking changes (Azure.AI.AgentServer.Responses beta.3 -> beta.4):
Contribution Checklist