Files
agent-framework/dotnet/src/Microsoft.Agents.AI.Foundry.Hosting/AIProjectClientToolboxExtensions.cs
T
5fe8941ff9 .NET: dotnet: Add server-side Foundry Toolbox support and fix SDK beta.4 br… (#5450)
* dotnet: Add server-side Foundry Toolbox support and fix SDK beta.4 breaking 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>

* fix: reuse endpoint variable in CreateSampleToolboxAsync

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: pass endpoint through static local functions to avoid capture

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>

* refactor: remove unused projectClient param from CreateSampleToolboxAsync

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Program.cs

Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>

* Update dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step25_ToolboxServerSideTools/Program.cs

Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>

* Removing GetToolbocVersion.

* Removing tests for GetToolboxVersion

* fix: map cached/reasoning token counts in ConvertUsage instead of hardcoding 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>

---------

Co-authored-by: alliscode <bentho@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
2026-04-23 18:52:03 +00:00

58 lines
2.5 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Foundry.Hosting;
using Microsoft.Extensions.AI;
using Microsoft.Shared.DiagnosticIds;
using Microsoft.Shared.Diagnostics;
#pragma warning disable OPENAI001
#pragma warning disable AAIP001 // AgentToolboxes is experimental in Azure.AI.Projects.Agents
namespace Azure.AI.Projects;
/// <summary>
/// Provides extension methods on <see cref="AIProjectClient"/> for fetching
/// Foundry toolbox definitions as server-side tools.
/// </summary>
/// <remarks>
/// These extensions mirror Python's <c>FoundryChatClient.get_toolbox()</c> pattern,
/// allowing a single call on the project client to retrieve tools ready for use
/// with <c>AsAIAgent(model, instructions, tools: ...)</c>.
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
public static class AIProjectClientToolboxExtensions
{
/// <summary>
/// Fetches a toolbox from the Foundry project and returns its tools as <see cref="AITool"/> instances
/// ready for use as server-side tools in the Responses API.
/// </summary>
/// <param name="projectClient">The <see cref="AIProjectClient"/> to use. Cannot be <see langword="null"/>.</param>
/// <param name="name">The name of the toolbox to fetch.</param>
/// <param name="version">
/// The specific toolbox version to fetch. When <see langword="null"/>, the toolbox's
/// default version is resolved automatically.
/// </param>
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
/// <returns>A read-only list of <see cref="AITool"/> instances from the toolbox.</returns>
/// <exception cref="System.ArgumentNullException">
/// Thrown when <paramref name="projectClient"/> or <paramref name="name"/> is <see langword="null"/>.
/// </exception>
public static async Task<IReadOnlyList<AITool>> GetToolboxToolsAsync(
this AIProjectClient projectClient,
string name,
string? version = null,
CancellationToken cancellationToken = default)
{
Throw.IfNull(projectClient);
Throw.IfNullOrWhitespace(name);
var toolboxClient = projectClient.AgentAdministrationClient.GetAgentToolboxes();
var toolboxVersion = await FoundryToolbox.GetToolboxVersionCoreAsync(toolboxClient, name, version, cancellationToken).ConfigureAwait(false);
return toolboxVersion.ToAITools();
}
}