From 1d4e72fc54ef31010b81c033a7d838a1a7242c95 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Mar 2026 00:03:55 +0000
Subject: [PATCH 1/5] Initial plan
From c954598afb4ce20f127e6d0e1b195c64499b0f5c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 11 Mar 2026 00:41:45 +0000
Subject: [PATCH 2/5] Update code for Microsoft.Extensions.AI.Abstractions
10.4.0 breaking changes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Rename FunctionApprovalRequestContent → ToolApprovalRequestContent
- Rename FunctionApprovalResponseContent → ToolApprovalResponseContent
- Rename UserInputRequestContent → ToolApprovalRequestContent
- Rename UserInputResponseContent → ToolApprovalResponseContent
- Update .FunctionCall property → .ToolCall with FunctionCallContent casts where needed
- Update .Id property → .RequestId on the renamed types
- Rename FunctionApprovalRequestEventGenerator → ToolApprovalRequestEventGenerator
- Rename FunctionApprovalResponseEventGenerator → ToolApprovalResponseEventGenerator
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
dotnet/Directory.Packages.props | 26 ++++-----
.../AGUI/Step04_HumanInLoop/Client/Program.cs | 14 ++---
.../ServerFunctionApprovalClientAgent.cs | 22 ++++----
.../ServerFunctionApprovalServerAgent.cs | 16 +++---
.../Agent_With_OpenAIResponses/Program.cs | 4 +-
.../Agent_OpenAI_Step02_Reasoning/Program.cs | 4 +-
.../OpenAIResponseClientAgent.cs | 9 ++-
.../Program.cs | 4 +-
.../Program.cs | 2 +-
.../Program.cs | 10 ++--
.../Agents/Agent_Step11_Middleware/Program.cs | 6 +-
.../Program.cs | 6 +-
.../Program.cs | 6 +-
.../Agents/GroupChatToolApproval/Program.cs | 10 ++--
.../OpenAIResponsesAgentClient.cs | 2 +-
.../M365Agent/AFAgentApplication.cs | 6 +-
.../AgentResponseUpdateExtensions.cs | 4 +-
.../FunctionApprovalRequestEventGenerator.cs | 17 +++---
.../FunctionApprovalResponseEventGenerator.cs | 10 ++--
...ingChatCompletionUpdateCollectionResult.cs | 2 +
.../OpenAIResponseClientExtensions.cs | 12 +++-
.../ObjectModel/InvokeAzureAgentExecutor.cs | 2 +-
.../ObjectModel/InvokeFunctionToolExecutor.cs | 2 +-
.../AIAgentHostOptions.cs | 2 +-
.../Specialized/AIAgentHostExecutor.cs | 20 +++----
.../Workflows/Execution/WorkflowRunner.cs | 6 +-
.../FunctionApprovalTests.cs | 24 ++++----
.../OpenAIResponsesIntegrationTests.cs | 1 -
.../InvokeToolWorkflowTest.cs | 4 +-
.../Events/ExternalInputRequestTest.cs | 6 +-
.../Events/ExternalInputResponseTest.cs | 6 +-
.../AIAgentHostExecutorTests.cs | 2 +-
.../TestRequestAgent.cs | 56 +++++++++----------
.../OpenAIResponseFixture.cs | 6 +-
34 files changed, 171 insertions(+), 158 deletions(-)
diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props
index 81ab56efd3..e51a3da419 100644
--- a/dotnet/Directory.Packages.props
+++ b/dotnet/Directory.Packages.props
@@ -33,18 +33,18 @@
-
+
-
+
-
-
-
+
+
+
@@ -63,12 +63,12 @@
-
-
-
-
+
+
+
+
-
+
@@ -76,11 +76,11 @@
-
+
-
+
@@ -109,7 +109,7 @@
-
+
diff --git a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/Program.cs b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/Program.cs
index fafe9ccf83..a6709da094 100644
--- a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/Program.cs
+++ b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/Program.cs
@@ -59,14 +59,14 @@
{
switch (content)
{
- case FunctionApprovalRequestContent approvalRequest:
+ case ToolApprovalRequestContent approvalRequest:
DisplayApprovalRequest(approvalRequest);
- Console.Write($"\nApprove '{approvalRequest.FunctionCall.Name}'? (yes/no): ");
+ Console.Write($"\nApprove '{((FunctionCallContent)approvalRequest.ToolCall).Name}'? (yes/no): ");
string? userInput = Console.ReadLine();
bool approved = userInput?.ToUpperInvariant() is "YES" or "Y";
- FunctionApprovalResponseContent approvalResponse = approvalRequest.CreateResponse(approved);
+ ToolApprovalResponseContent approvalResponse = approvalRequest.CreateResponse(approved);
if (approvalRequest.AdditionalProperties != null)
{
@@ -128,19 +128,19 @@
}
#pragma warning disable MEAI001
-static void DisplayApprovalRequest(FunctionApprovalRequestContent approvalRequest)
+static void DisplayApprovalRequest(ToolApprovalRequestContent approvalRequest)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine();
Console.WriteLine("============================================================");
Console.WriteLine("APPROVAL REQUIRED");
Console.WriteLine("============================================================");
- Console.WriteLine($"Function: {approvalRequest.FunctionCall.Name}");
+ Console.WriteLine($"Function: {((FunctionCallContent)approvalRequest.ToolCall).Name}");
- if (approvalRequest.FunctionCall.Arguments != null)
+ if (((FunctionCallContent)approvalRequest.ToolCall).Arguments != null)
{
Console.WriteLine("Arguments:");
- foreach (var arg in approvalRequest.FunctionCall.Arguments)
+ foreach (var arg in ((FunctionCallContent)approvalRequest.ToolCall).Arguments)
{
Console.WriteLine($" {arg.Key} = {arg.Value}");
}
diff --git a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs
index ee0191fd98..3ba4fe3fd6 100644
--- a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs
+++ b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs
@@ -9,7 +9,7 @@
///
/// A delegating agent that handles server function approval requests and responses.
-/// Transforms between FunctionApprovalRequestContent/FunctionApprovalResponseContent
+/// Transforms between ToolApprovalRequestContent/ToolApprovalResponseContent
/// and the server's request_approval tool call pattern.
///
internal sealed class ServerFunctionApprovalClientAgent : DelegatingAIAgent
@@ -50,14 +50,14 @@ protected override async IAsyncEnumerable RunCoreStreamingA
}
#pragma warning disable MEAI001 // Type is for evaluation purposes only
- private static FunctionResultContent ConvertApprovalResponseToToolResult(FunctionApprovalResponseContent approvalResponse, JsonSerializerOptions jsonOptions)
+ private static FunctionResultContent ConvertApprovalResponseToToolResult(ToolApprovalResponseContent approvalResponse, JsonSerializerOptions jsonOptions)
{
return new FunctionResultContent(
- callId: approvalResponse.Id,
+ callId: approvalResponse.RequestId,
result: JsonSerializer.SerializeToElement(
new ApprovalResponse
{
- ApprovalId = approvalResponse.Id,
+ ApprovalId = approvalResponse.RequestId,
Approved = approvalResponse.Approved
},
jsonOptions));
@@ -89,7 +89,7 @@ private static List ProcessOutgoingServerFunctionApprovals(
{
List? result = null;
- Dictionary approvalRequests = [];
+ Dictionary approvalRequests = [];
for (var messageIndex = 0; messageIndex < messages.Count; messageIndex++)
{
var message = messages[messageIndex];
@@ -102,21 +102,21 @@ private static List ProcessOutgoingServerFunctionApprovals(
var content = message.Contents[contentIndex];
// Handle pending approval requests (transform to tool call)
- if (content is FunctionApprovalRequestContent approvalRequest &&
+ if (content is ToolApprovalRequestContent approvalRequest &&
approvalRequest.AdditionalProperties?.TryGetValue("original_function", out var originalFunction) == true &&
originalFunction is FunctionCallContent original)
{
- approvalRequests[approvalRequest.Id] = approvalRequest;
+ approvalRequests[approvalRequest.RequestId] = approvalRequest;
transformedContents ??= CopyContentsUpToIndex(message.Contents, contentIndex);
transformedContents.Add(original);
}
// Handle pending approval responses (transform to tool result)
- else if (content is FunctionApprovalResponseContent approvalResponse &&
- approvalRequests.TryGetValue(approvalResponse.Id, out var correspondingRequest))
+ else if (content is ToolApprovalResponseContent approvalResponse &&
+ approvalRequests.TryGetValue(approvalResponse.RequestId, out var correspondingRequest))
{
transformedContents ??= CopyContentsUpToIndex(message.Contents, contentIndex);
transformedContents.Add(ConvertApprovalResponseToToolResult(approvalResponse, jsonSerializerOptions));
- approvalRequests.Remove(approvalResponse.Id);
+ approvalRequests.Remove(approvalResponse.RequestId);
correspondingRequest.AdditionalProperties?.Remove("original_function");
}
// Skip historical approval content
@@ -198,7 +198,7 @@ private static AgentResponseUpdate ProcessIncomingServerApprovalRequests(
var functionCallArgs = (Dictionary?)approvalRequest.FunctionArguments?
.Deserialize(jsonSerializerOptions.GetTypeInfo(typeof(Dictionary)));
- var approvalRequestContent = new FunctionApprovalRequestContent(
+ var approvalRequestContent = new ToolApprovalRequestContent(
id: approvalRequest.ApprovalId,
new FunctionCallContent(
callId: approvalRequest.ApprovalId,
diff --git a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs
index 62209792f6..67d2fe2aa8 100644
--- a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs
+++ b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs
@@ -9,7 +9,7 @@
///
/// A delegating agent that handles function approval requests on the server side.
-/// Transforms between FunctionApprovalRequestContent/FunctionApprovalResponseContent
+/// Transforms between ToolApprovalRequestContent/ToolApprovalResponseContent
/// and the request_approval tool call pattern for client communication.
///
internal sealed class ServerFunctionApprovalAgent : DelegatingAIAgent
@@ -50,7 +50,7 @@ protected override async IAsyncEnumerable RunCoreStreamingA
}
#pragma warning disable MEAI001 // Type is for evaluation purposes only
- private static FunctionApprovalRequestContent ConvertToolCallToApprovalRequest(FunctionCallContent toolCall, JsonSerializerOptions jsonSerializerOptions)
+ private static ToolApprovalRequestContent ConvertToolCallToApprovalRequest(FunctionCallContent toolCall, JsonSerializerOptions jsonSerializerOptions)
{
if (toolCall.Name != "request_approval" || toolCall.Arguments == null)
{
@@ -67,7 +67,7 @@ reqObj is JsonElement argsElement &&
throw new InvalidOperationException("Failed to deserialize approval request from tool call");
}
- return new FunctionApprovalRequestContent(
+ return new ToolApprovalRequestContent(
id: request.ApprovalId,
new FunctionCallContent(
callId: request.ApprovalId,
@@ -75,7 +75,7 @@ reqObj is JsonElement argsElement &&
arguments: request.FunctionArguments));
}
- private static FunctionApprovalResponseContent ConvertToolResultToApprovalResponse(FunctionResultContent result, FunctionApprovalRequestContent approval, JsonSerializerOptions jsonSerializerOptions)
+ private static ToolApprovalResponseContent ConvertToolResultToApprovalResponse(FunctionResultContent result, ToolApprovalRequestContent approval, JsonSerializerOptions jsonSerializerOptions)
{
var approvalResponse = result.Result is JsonElement je ?
(ApprovalResponse?)je.Deserialize(jsonSerializerOptions.GetTypeInfo(typeof(ApprovalResponse))) :
@@ -121,7 +121,7 @@ private static List ProcessIncomingFunctionApprovals(
// Track approval ID to original call ID mapping
_ = new Dictionary();
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
- Dictionary trackedRequestApprovalToolCalls = new(); // Remote approvals
+ Dictionary trackedRequestApprovalToolCalls = new(); // Remote approvals
for (int messageIndex = 0; messageIndex < messages.Count; messageIndex++)
{
var message = messages[messageIndex];
@@ -181,11 +181,11 @@ private static AgentResponseUpdate ProcessOutgoingApprovalRequests(
{
var content = update.Contents[i];
#pragma warning disable MEAI001 // Type is for evaluation purposes only
- if (content is FunctionApprovalRequestContent request)
+ if (content is ToolApprovalRequestContent request)
{
updatedContents ??= [.. update.Contents];
- var functionCall = request.FunctionCall;
- var approvalId = request.Id;
+ var functionCall = (FunctionCallContent)request.ToolCall;
+ var approvalId = request.RequestId;
var approvalData = new ApprovalRequest
{
diff --git a/dotnet/samples/02-agents/AgentProviders/Agent_With_OpenAIResponses/Program.cs b/dotnet/samples/02-agents/AgentProviders/Agent_With_OpenAIResponses/Program.cs
index 611f3f9a9a..baa6677a4f 100644
--- a/dotnet/samples/02-agents/AgentProviders/Agent_With_OpenAIResponses/Program.cs
+++ b/dotnet/samples/02-agents/AgentProviders/Agent_With_OpenAIResponses/Program.cs
@@ -11,8 +11,8 @@
AIAgent agent = new OpenAIClient(
apiKey)
- .GetResponsesClient(model)
- .AsAIAgent(instructions: "You are good at telling jokes.", name: "Joker");
+ .GetResponsesClient()
+ .AsAIAgent(model: model, instructions: "You are good at telling jokes.", name: "Joker");
// Invoke the agent and output the text result.
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
diff --git a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs
index d13d0d5346..12e30dc203 100644
--- a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs
+++ b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Program.cs
@@ -10,8 +10,8 @@
var model = Environment.GetEnvironmentVariable("OPENAI_CHAT_MODEL_NAME") ?? "gpt-5";
var client = new OpenAIClient(apiKey)
- .GetResponsesClient(model)
- .AsIChatClient().AsBuilder()
+ .GetResponsesClient()
+ .AsIChatClient(model).AsBuilder()
.ConfigureOptions(o =>
{
o.Reasoning = new()
diff --git a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs
index 196bd64922..4deb134fd7 100644
--- a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs
+++ b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/OpenAIResponseClientAgent.cs
@@ -20,19 +20,21 @@ public class OpenAIResponseClientAgent : DelegatingAIAgent
/// Optional instructions for the agent.
/// Optional name for the agent.
/// Optional description for the agent.
+ /// Optional default model ID to use for requests. Required when using a plain (not via Azure OpenAI).
/// Optional instance of
public OpenAIResponseClientAgent(
ResponsesClient client,
string? instructions = null,
string? name = null,
string? description = null,
+ string? model = null,
ILoggerFactory? loggerFactory = null) :
this(client, new()
{
Name = name,
Description = description,
ChatOptions = new ChatOptions() { Instructions = instructions },
- }, loggerFactory)
+ }, model, loggerFactory)
{
}
@@ -41,10 +43,11 @@ public OpenAIResponseClientAgent(
///
/// Instance of
/// Options to create the agent.
+ /// Optional default model ID to use for requests. Required when using a plain (not via Azure OpenAI).
/// Optional instance of
public OpenAIResponseClientAgent(
- ResponsesClient client, ChatClientAgentOptions options, ILoggerFactory? loggerFactory = null) :
- base(new ChatClientAgent((client ?? throw new ArgumentNullException(nameof(client))).AsIChatClient(), options, loggerFactory))
+ ResponsesClient client, ChatClientAgentOptions options, string? model = null, ILoggerFactory? loggerFactory = null) :
+ base(new ChatClientAgent((client ?? throw new ArgumentNullException(nameof(client))).AsIChatClient(model), options, loggerFactory))
{
}
diff --git a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs
index 8004770c21..dbd11ce3c6 100644
--- a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs
+++ b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step04_CreateFromOpenAIResponseClient/Program.cs
@@ -10,10 +10,10 @@
var model = Environment.GetEnvironmentVariable("OPENAI_CHAT_MODEL_NAME") ?? "gpt-4o-mini";
// Create a ResponsesClient directly from OpenAIClient
-ResponsesClient responseClient = new OpenAIClient(apiKey).GetResponsesClient(model);
+ResponsesClient responseClient = new OpenAIClient(apiKey).GetResponsesClient();
// Create an agent directly from the ResponsesClient using OpenAIResponseClientAgent
-OpenAIResponseClientAgent agent = new(responseClient, instructions: "You are good at telling jokes.", name: "Joker");
+OpenAIResponseClientAgent agent = new(responseClient, instructions: "You are good at telling jokes.", name: "Joker", model: model);
ResponseItem userMessage = ResponseItem.CreateUserMessageItem("Tell me a joke about a pirate.");
diff --git a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs
index 921acbad0d..603f8b8e7b 100644
--- a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs
+++ b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step05_Conversation/Program.cs
@@ -22,7 +22,7 @@
ConversationClient conversationClient = openAIClient.GetConversationClient();
// Create an agent directly from the ResponsesClient using OpenAIResponseClientAgent
-ChatClientAgent agent = new(openAIClient.GetResponsesClient(model).AsIChatClient(), instructions: "You are a helpful assistant.", name: "ConversationAgent");
+ChatClientAgent agent = new(openAIClient.GetResponsesClient().AsIChatClient(model), instructions: "You are a helpful assistant.", name: "ConversationAgent");
ClientResult createConversationResult = await conversationClient.CreateConversationAsync(BinaryContent.Create(BinaryData.FromString("{}")));
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step01_UsingFunctionToolsWithApprovals/Program.cs b/dotnet/samples/02-agents/Agents/Agent_Step01_UsingFunctionToolsWithApprovals/Program.cs
index 5bdfc9421c..8ff4181a51 100644
--- a/dotnet/samples/02-agents/Agents/Agent_Step01_UsingFunctionToolsWithApprovals/Program.cs
+++ b/dotnet/samples/02-agents/Agents/Agent_Step01_UsingFunctionToolsWithApprovals/Program.cs
@@ -36,11 +36,11 @@ static string GetWeather([Description("The location to get the weather for.")] s
// For simplicity, we are assuming here that only function approvals are pending.
AgentSession session = await agent.CreateSessionAsync();
AgentResponse response = await agent.RunAsync("What is the weather like in Amsterdam?", session);
-List approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+List approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
// For streaming use:
// var updates = await agent.RunStreamingAsync("What is the weather like in Amsterdam?", session).ToListAsync();
-// approvalRequests = updates.SelectMany(x => x.Contents).OfType().ToList();
+// approvalRequests = updates.SelectMany(x => x.Contents).OfType().ToList();
while (approvalRequests.Count > 0)
{
@@ -48,18 +48,18 @@ static string GetWeather([Description("The location to get the weather for.")] s
List userInputResponses = approvalRequests
.ConvertAll(functionApprovalRequest =>
{
- Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {functionApprovalRequest.FunctionCall.Name}");
+ Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {((FunctionCallContent)functionApprovalRequest.ToolCall).Name}");
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false)]);
});
// Pass the user input responses back to the agent for further processing.
response = await agent.RunAsync(userInputResponses, session);
- approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+ approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
// For streaming use:
// updates = await agent.RunStreamingAsync(userInputResponses, session).ToListAsync();
- // approvalRequests = updates.SelectMany(x => x.Contents).OfType().ToList();
+ // approvalRequests = updates.SelectMany(x => x.Contents).OfType().ToList();
}
Console.WriteLine($"\nAgent: {response}");
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Program.cs b/dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Program.cs
index 09cd540378..18969ed66e 100644
--- a/dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Program.cs
+++ b/dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Program.cs
@@ -246,7 +246,7 @@ async Task ConsolePromptingApprovalMiddleware(IEnumerable approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+ List approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
while (approvalRequests.Count > 0)
{
@@ -255,13 +255,13 @@ async Task ConsolePromptingApprovalMiddleware(IEnumerable
{
- Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {functionApprovalRequest.FunctionCall.Name}");
+ Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {((FunctionCallContent)functionApprovalRequest.ToolCall).Name}");
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false)]);
});
response = await innerAgent.RunAsync(response.Messages, session, options, cancellationToken);
- approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+ approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
}
return response;
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs
index f33fae35f4..08051a500e 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs
+++ b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs
@@ -40,7 +40,7 @@ static string GetWeather([Description("The location to get the weather for.")] s
// Check if there are any approval requests.
// For simplicity, we are assuming here that only function approvals are pending.
-List approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+List approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
while (approvalRequests.Count > 0)
{
@@ -48,7 +48,7 @@ static string GetWeather([Description("The location to get the weather for.")] s
List userInputMessages = approvalRequests
.ConvertAll(functionApprovalRequest =>
{
- Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {functionApprovalRequest.FunctionCall.Name}");
+ Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {((FunctionCallContent)functionApprovalRequest.ToolCall).Name}");
bool approved = Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false;
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(approved)]);
});
@@ -56,7 +56,7 @@ static string GetWeather([Description("The location to get the weather for.")] s
// Pass the user input responses back to the agent for further processing.
response = await agent.RunAsync(userInputMessages, session);
- approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+ approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
}
Console.WriteLine($"\nAgent: {response}");
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs
index 7ea6bc88a3..824e1507b3 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs
+++ b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs
@@ -197,7 +197,7 @@ async Task ConsolePromptingApprovalMiddleware(IEnumerable approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+ List approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
while (approvalRequests.Count > 0)
{
@@ -206,14 +206,14 @@ async Task ConsolePromptingApprovalMiddleware(IEnumerable
{
- Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {functionApprovalRequest.FunctionCall.Name}");
+ Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {((FunctionCallContent)functionApprovalRequest.ToolCall).Name}");
bool approved = Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false;
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(approved)]);
});
response = await innerAgent.RunAsync(response.Messages, session, options, cancellationToken);
- approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
+ approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().ToList();
}
return response;
diff --git a/dotnet/samples/03-workflows/Agents/GroupChatToolApproval/Program.cs b/dotnet/samples/03-workflows/Agents/GroupChatToolApproval/Program.cs
index 076e764ea8..a8d42b5342 100644
--- a/dotnet/samples/03-workflows/Agents/GroupChatToolApproval/Program.cs
+++ b/dotnet/samples/03-workflows/Agents/GroupChatToolApproval/Program.cs
@@ -17,7 +17,7 @@
//
// Demonstrate:
// - Using custom GroupChatManager with agents that have approval-required tools.
-// - Handling FunctionApprovalRequestContent in group chat scenarios.
+// - Handling ToolApprovalRequestContent in group chat scenarios.
// - Multi-round group chat with tool approval interruption and resumption.
using System.ComponentModel;
@@ -101,16 +101,16 @@ private static async Task Main()
{
case RequestInfoEvent e:
{
- if (e.Request.TryGetDataAs(out FunctionApprovalRequestContent? approvalRequestContent))
+ if (e.Request.TryGetDataAs(out ToolApprovalRequestContent? approvalRequestContent))
{
Console.WriteLine();
Console.WriteLine($"[APPROVAL REQUIRED] From agent: {e.Request.PortInfo.PortId}");
- Console.WriteLine($" Tool: {approvalRequestContent.FunctionCall.Name}");
- Console.WriteLine($" Arguments: {JsonSerializer.Serialize(approvalRequestContent.FunctionCall.Arguments)}");
+ Console.WriteLine($" Tool: {((FunctionCallContent)approvalRequestContent.ToolCall).Name}");
+ Console.WriteLine($" Arguments: {JsonSerializer.Serialize(((FunctionCallContent)approvalRequestContent.ToolCall).Arguments)}");
Console.WriteLine();
// Approve the tool call request
- Console.WriteLine($"Tool: {approvalRequestContent.FunctionCall.Name} approved");
+ Console.WriteLine($"Tool: {((FunctionCallContent)approvalRequestContent.ToolCall).Name} approved");
await run.SendResponseAsync(e.Request.CreateResponse(approvalRequestContent.CreateResponse(approved: true)));
}
diff --git a/dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs b/dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs
index 0d2470762e..839c8e75a1 100644
--- a/dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs
+++ b/dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.Web/OpenAIResponsesAgentClient.cs
@@ -27,7 +27,7 @@ public override async IAsyncEnumerable RunStreamingAsync(
Transport = new HttpClientPipelineTransport(httpClient)
};
- var openAiClient = new ResponsesClient(model: agentName, credential: new ApiKeyCredential("dummy-key"), options: options).AsIChatClient();
+ var openAiClient = new ResponsesClient(credential: new ApiKeyCredential("dummy-key"), options: options).AsIChatClient(agentName);
var chatOptions = new ChatOptions()
{
ConversationId = sessionId
diff --git a/dotnet/samples/05-end-to-end/M365Agent/AFAgentApplication.cs b/dotnet/samples/05-end-to-end/M365Agent/AFAgentApplication.cs
index 7e58819a65..502c57204e 100644
--- a/dotnet/samples/05-end-to-end/M365Agent/AFAgentApplication.cs
+++ b/dotnet/samples/05-end-to-end/M365Agent/AFAgentApplication.cs
@@ -122,7 +122,7 @@ private static ChatMessage HandleUserInput(ITurnContext turnContext)
&& valueElement.GetProperty("requestJson") is JsonElement requestJsonElement
&& requestJsonElement.ValueKind == JsonValueKind.String)
{
- var requestContent = JsonSerializer.Deserialize(requestJsonElement.GetString()!, JsonUtilities.DefaultOptions);
+ var requestContent = JsonSerializer.Deserialize(requestJsonElement.GetString()!, JsonUtilities.DefaultOptions);
return new ChatMessage(ChatRole.User, [requestContent!.CreateResponse(approvedJsonElement.ValueKind == JsonValueKind.True)]);
}
@@ -138,7 +138,7 @@ private static ChatMessage HandleUserInput(ITurnContext turnContext)
/// The list of to which the adaptive cards will be added.
private static void HandleUserInputRequests(AgentResponse response, ref List? attachments)
{
- foreach (FunctionApprovalRequestContent functionApprovalRequest in response.Messages.SelectMany(m => m.Contents).OfType())
+ foreach (ToolApprovalRequestContent functionApprovalRequest in response.Messages.SelectMany(m => m.Contents).OfType())
{
var functionApprovalRequestJson = JsonSerializer.Serialize(functionApprovalRequest, JsonUtilities.DefaultOptions);
@@ -152,7 +152,7 @@ private static void HandleUserInputRequests(AgentResponse response, ref List ToStreamingResponse
TextReasoningContent => new TextReasoningContentEventGenerator(context.IdGenerator, seq, outputIndex),
FunctionCallContent => new FunctionCallEventGenerator(context.IdGenerator, seq, outputIndex, context.JsonSerializerOptions),
FunctionResultContent => new FunctionResultEventGenerator(context.IdGenerator, seq, outputIndex),
- FunctionApprovalRequestContent => new FunctionApprovalRequestEventGenerator(context.IdGenerator, seq, outputIndex, context.JsonSerializerOptions),
- FunctionApprovalResponseContent => new FunctionApprovalResponseEventGenerator(context.IdGenerator, seq, outputIndex),
+ ToolApprovalRequestContent => new ToolApprovalRequestEventGenerator(context.IdGenerator, seq, outputIndex, context.JsonSerializerOptions),
+ ToolApprovalResponseContent => new ToolApprovalResponseEventGenerator(context.IdGenerator, seq, outputIndex),
ErrorContent => new ErrorContentEventGenerator(context.IdGenerator, seq, outputIndex),
UriContent uriContent when uriContent.HasTopLevelMediaType("image") => new ImageContentEventGenerator(context.IdGenerator, seq, outputIndex),
DataContent dataContent when dataContent.HasTopLevelMediaType("image") => new ImageContentEventGenerator(context.IdGenerator, seq, outputIndex),
diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Streaming/FunctionApprovalRequestEventGenerator.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Streaming/FunctionApprovalRequestEventGenerator.cs
index 4e565b0784..54e18168b2 100644
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Streaming/FunctionApprovalRequestEventGenerator.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Streaming/FunctionApprovalRequestEventGenerator.cs
@@ -12,33 +12,34 @@ namespace Microsoft.Agents.AI.Hosting.OpenAI.Responses.Streaming;
/// A generator for streaming events from function approval request content.
/// This is a non-standard DevUI extension for human-in-the-loop scenarios.
///
-internal sealed class FunctionApprovalRequestEventGenerator(
+internal sealed class ToolApprovalRequestEventGenerator(
IdGenerator idGenerator,
SequenceNumber seq,
int outputIndex,
JsonSerializerOptions jsonSerializerOptions) : StreamingEventGenerator
{
- public override bool IsSupported(AIContent content) => content is FunctionApprovalRequestContent;
+ public override bool IsSupported(AIContent content) => content is ToolApprovalRequestContent;
public override IEnumerable ProcessContent(AIContent content)
{
- if (content is not FunctionApprovalRequestContent approvalRequest)
+ if (content is not ToolApprovalRequestContent approvalRequest)
{
- throw new InvalidOperationException("FunctionApprovalRequestEventGenerator only supports FunctionApprovalRequestContent.");
+ throw new InvalidOperationException("ToolApprovalRequestEventGenerator only supports ToolApprovalRequestContent.");
}
+ var functionCall = (FunctionCallContent)approvalRequest.ToolCall;
yield return new StreamingFunctionApprovalRequested
{
SequenceNumber = seq.Increment(),
OutputIndex = outputIndex,
- RequestId = approvalRequest.Id,
+ RequestId = approvalRequest.RequestId,
ItemId = idGenerator.GenerateMessageId(),
FunctionCall = new FunctionCallInfo
{
- Id = approvalRequest.FunctionCall.CallId,
- Name = approvalRequest.FunctionCall.Name,
+ Id = functionCall.CallId,
+ Name = functionCall.Name,
Arguments = JsonSerializer.SerializeToElement(
- approvalRequest.FunctionCall.Arguments,
+ functionCall.Arguments,
jsonSerializerOptions.GetTypeInfo(typeof(IDictionary)))
}
};
diff --git a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Streaming/FunctionApprovalResponseEventGenerator.cs b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Streaming/FunctionApprovalResponseEventGenerator.cs
index ab4af8f408..df1379cfbb 100644
--- a/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Streaming/FunctionApprovalResponseEventGenerator.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI/Responses/Streaming/FunctionApprovalResponseEventGenerator.cs
@@ -11,25 +11,25 @@ namespace Microsoft.Agents.AI.Hosting.OpenAI.Responses.Streaming;
/// A generator for streaming events from function approval response content.
/// This is a non-standard DevUI extension for human-in-the-loop scenarios.
///
-internal sealed class FunctionApprovalResponseEventGenerator(
+internal sealed class ToolApprovalResponseEventGenerator(
IdGenerator idGenerator,
SequenceNumber seq,
int outputIndex) : StreamingEventGenerator
{
- public override bool IsSupported(AIContent content) => content is FunctionApprovalResponseContent;
+ public override bool IsSupported(AIContent content) => content is ToolApprovalResponseContent;
public override IEnumerable ProcessContent(AIContent content)
{
- if (content is not FunctionApprovalResponseContent approvalResponse)
+ if (content is not ToolApprovalResponseContent approvalResponse)
{
- throw new InvalidOperationException("FunctionApprovalResponseEventGenerator only supports FunctionApprovalResponseContent.");
+ throw new InvalidOperationException("ToolApprovalResponseEventGenerator only supports ToolApprovalResponseContent.");
}
yield return new StreamingFunctionApprovalResponded
{
SequenceNumber = seq.Increment(),
OutputIndex = outputIndex,
- RequestId = approvalResponse.Id,
+ RequestId = approvalResponse.RequestId,
Approved = approvalResponse.Approved,
ItemId = idGenerator.GenerateMessageId()
};
diff --git a/dotnet/src/Microsoft.Agents.AI.OpenAI/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResult.cs b/dotnet/src/Microsoft.Agents.AI.OpenAI/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResult.cs
index db0c7a8673..34c07ea73f 100644
--- a/dotnet/src/Microsoft.Agents.AI.OpenAI/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResult.cs
+++ b/dotnet/src/Microsoft.Agents.AI.OpenAI/ChatClient/AsyncStreamingChatCompletionUpdateCollectionResult.cs
@@ -1,5 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
+#pragma warning disable OPENAI001 // Experimental OpenAI features
+
using System.ClientModel;
using OpenAI.Chat;
diff --git a/dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIResponseClientExtensions.cs b/dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIResponseClientExtensions.cs
index 98561704f2..da7826e785 100644
--- a/dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIResponseClientExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.OpenAI/Extensions/OpenAIResponseClientExtensions.cs
@@ -26,6 +26,7 @@ public static class OpenAIResponseClientExtensions
/// Creates an AI agent from an using the OpenAI Response API.
///
/// The to use for the agent.
+ /// Optional default model ID to use for requests. Required when using a plain (not via Azure OpenAI).
/// Optional system instructions that define the agent's behavior and personality.
/// Optional name for the agent for identification purposes.
/// Optional description of the agent's capabilities and purpose.
@@ -37,6 +38,7 @@ public static class OpenAIResponseClientExtensions
/// Thrown when is .
public static ChatClientAgent AsAIAgent(
this ResponsesClient client,
+ string? model = null,
string? instructions = null,
string? name = null,
string? description = null,
@@ -58,6 +60,7 @@ public static ChatClientAgent AsAIAgent(
Tools = tools,
}
},
+ model,
clientFactory,
loggerFactory,
services);
@@ -68,6 +71,7 @@ public static ChatClientAgent AsAIAgent(
///
/// The to use for the agent.
/// Full set of options to configure the agent.
+ /// Optional default model ID to use for requests. Required when using a plain (not via Azure OpenAI).
/// Provides a way to customize the creation of the underlying used by the agent.
/// Optional logger factory for enabling logging within the agent.
/// An optional to use for resolving services required by the instances being invoked.
@@ -76,6 +80,7 @@ public static ChatClientAgent AsAIAgent(
public static ChatClientAgent AsAIAgent(
this ResponsesClient client,
ChatClientAgentOptions options,
+ string? model = null,
Func? clientFactory = null,
ILoggerFactory? loggerFactory = null,
IServiceProvider? services = null)
@@ -83,7 +88,7 @@ public static ChatClientAgent AsAIAgent(
Throw.IfNull(client);
Throw.IfNull(options);
- var chatClient = client.AsIChatClient();
+ var chatClient = client.AsIChatClient(model);
if (clientFactory is not null)
{
@@ -100,13 +105,14 @@ public static ChatClientAgent AsAIAgent(
/// This corresponds to setting the "store" property in the JSON representation to false.
///
/// The client.
+ /// Optional default model ID to use for requests. Required when using a plain (not via Azure OpenAI).
/// An that can be used to converse via the that does not store responses for later retrieval.
/// is .
[Experimental(DiagnosticIds.Experiments.AgentsAIExperiments)]
- public static IChatClient AsIChatClientWithStoredOutputDisabled(this ResponsesClient responseClient)
+ public static IChatClient AsIChatClientWithStoredOutputDisabled(this ResponsesClient responseClient, string? model = null)
{
return Throw.IfNull(responseClient)
- .AsIChatClient()
+ .AsIChatClient(model)
.AsBuilder()
.ConfigureOptions(x => x.RawRepresentationFactory = _ => new CreateResponseOptions() { StoredOutputEnabled = false })
.Build();
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/InvokeAzureAgentExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/InvokeAzureAgentExecutor.cs
index c8cde902fa..24653af0f2 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/InvokeAzureAgentExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/InvokeAzureAgentExecutor.cs
@@ -150,7 +150,7 @@ [.. agentResponse.Messages
foreach (ChatMessage responseMessage in agentResponse.Messages)
{
- if (responseMessage.Contents.Any(content => content is UserInputRequestContent))
+ if (responseMessage.Contents.Any(content => content is ToolApprovalRequestContent))
{
yield return responseMessage;
continue;
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/InvokeFunctionToolExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/InvokeFunctionToolExecutor.cs
index 0e95bebe63..baa6f9c6b8 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/InvokeFunctionToolExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/ObjectModel/InvokeFunctionToolExecutor.cs
@@ -68,7 +68,7 @@ public static class Steps
// If approval is required, add user input request content
if (requireApproval)
{
- requestMessage.Contents.Add(new FunctionApprovalRequestContent(this.Id, functionCall));
+ requestMessage.Contents.Add(new ToolApprovalRequestContent(this.Id, functionCall));
}
AgentResponse agentResponse = new([requestMessage]);
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/AIAgentHostOptions.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/AIAgentHostOptions.cs
index 623981e204..c981b5d801 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows/AIAgentHostOptions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows/AIAgentHostOptions.cs
@@ -21,7 +21,7 @@ public sealed class AIAgentHostOptions
public bool EmitAgentResponseEvents { get; set; }
///
- /// Gets or sets a value indicating whether should be intercepted and sent
+ /// Gets or sets a value indicating whether should be intercepted and sent
/// as a message to the workflow for handling, instead of being raised as a request.
///
public bool InterceptUserInputRequests { get; set; }
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs b/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs
index a38f49681a..6876ddbb99 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows/Specialized/AIAgentHostExecutor.cs
@@ -19,7 +19,7 @@ internal sealed class AIAgentHostExecutor : ChatProtocolExecutor
private AgentSession? _session;
private bool? _currentTurnEmitEvents;
- private AIContentExternalHandler? _userInputHandler;
+ private AIContentExternalHandler? _userInputHandler;
private AIContentExternalHandler? _functionCallHandler;
private static readonly ChatProtocolExecutorOptions s_defaultChatProtocolOptions = new()
@@ -38,7 +38,7 @@ public AIAgentHostExecutor(AIAgent agent, AIAgentHostOptions options) : base(id:
private ProtocolBuilder ConfigureUserInputHandling(ProtocolBuilder protocolBuilder)
{
- this._userInputHandler = new AIContentExternalHandler(
+ this._userInputHandler = new AIContentExternalHandler(
ref protocolBuilder,
portId: $"{this.Id}_UserInput",
intercepted: this._options.InterceptUserInputRequests,
@@ -59,13 +59,13 @@ protected override ProtocolBuilder ConfigureProtocol(ProtocolBuilder protocolBui
}
private ValueTask HandleUserInputResponseAsync(
- UserInputResponseContent response,
+ ToolApprovalResponseContent response,
IWorkflowContext context,
CancellationToken cancellationToken)
{
- if (!this._userInputHandler!.MarkRequestAsHandled(response.Id))
+ if (!this._userInputHandler!.MarkRequestAsHandled(response.RequestId))
{
- throw new InvalidOperationException($"No pending UserInputRequest found with id '{response.Id}'.");
+ throw new InvalidOperationException($"No pending UserInputRequest found with id '{response.RequestId}'.");
}
List implicitTurnMessages = [new ChatMessage(ChatRole.User, [response])];
@@ -164,7 +164,7 @@ protected override ValueTask TakeTurnAsync(List messages, IWorkflow
private async ValueTask InvokeAgentAsync(IEnumerable messages, IWorkflowContext context, bool emitEvents, CancellationToken cancellationToken = default)
{
#pragma warning disable MEAI001
- Dictionary userInputRequests = new();
+ Dictionary userInputRequests = new();
Dictionary functionCalls = new();
AgentResponse response;
@@ -218,15 +218,15 @@ void ExtractUnservicedRequests(IEnumerable contents)
{
foreach (AIContent content in contents)
{
- if (content is UserInputRequestContent userInputRequest)
+ if (content is ToolApprovalRequestContent userInputRequest)
{
// It is an error to simultaneously have multiple outstanding user input requests with the same ID.
- userInputRequests.Add(userInputRequest.Id, userInputRequest);
+ userInputRequests.Add(userInputRequest.RequestId, userInputRequest);
}
- else if (content is UserInputResponseContent userInputResponse)
+ else if (content is ToolApprovalResponseContent userInputResponse)
{
// If the set of messages somehow already has a corresponding user input response, remove it.
- _ = userInputRequests.Remove(userInputResponse.Id);
+ _ = userInputRequests.Remove(userInputResponse.RequestId);
}
else if (content is FunctionCallContent functionCall)
{
diff --git a/dotnet/src/Shared/Workflows/Execution/WorkflowRunner.cs b/dotnet/src/Shared/Workflows/Execution/WorkflowRunner.cs
index 0f4f0c9217..503cf1d34c 100644
--- a/dotnet/src/Shared/Workflows/Execution/WorkflowRunner.cs
+++ b/dotnet/src/Shared/Workflows/Execution/WorkflowRunner.cs
@@ -306,7 +306,7 @@ private async IAsyncEnumerable ProcessInputMessageAsync(ChatMessage
requestItem switch
{
FunctionCallContent functionCall when !functionCall.InformationalOnly => await InvokeFunctionAsync(functionCall).ConfigureAwait(false),
- FunctionApprovalRequestContent functionApprovalRequest => ApproveFunction(functionApprovalRequest),
+ ToolApprovalRequestContent functionApprovalRequest => ApproveFunction(functionApprovalRequest),
McpServerToolApprovalRequestContent mcpApprovalRequest => ApproveMCP(mcpApprovalRequest),
_ => HandleUnknown(requestItem),
};
@@ -325,9 +325,9 @@ private async IAsyncEnumerable ProcessInputMessageAsync(ChatMessage
return null;
}
- ChatMessage ApproveFunction(FunctionApprovalRequestContent functionApprovalRequest)
+ ChatMessage ApproveFunction(ToolApprovalRequestContent functionApprovalRequest)
{
- Notify($"INPUT - Approving Function: {functionApprovalRequest.FunctionCall.Name}");
+ Notify($"INPUT - Approving Function: {((FunctionCallContent)functionApprovalRequest.ToolCall).Name}");
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(approved: true)]);
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/FunctionApprovalTests.cs b/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/FunctionApprovalTests.cs
index 296217f931..683c4c0cb4 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/FunctionApprovalTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/FunctionApprovalTests.cs
@@ -20,7 +20,7 @@ public sealed class FunctionApprovalTests : ConformanceTestBase
// Streaming request JSON for OpenAI Responses API
private const string StreamingRequestJson = @"{""model"":""gpt-4o-mini"",""input"":""test"",""stream"":true}";
- #region FunctionApprovalRequestContent Tests
+ #region ToolApprovalRequestContent Tests
[Fact]
public async Task FunctionApprovalRequest_GeneratesCorrectEvent_SuccessAsync()
@@ -34,7 +34,7 @@ public async Task FunctionApprovalRequest_GeneratesCorrectEvent_SuccessAsync()
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall = new(FunctionId, FunctionName, arguments);
- FunctionApprovalRequestContent approvalRequest = new(RequestId, functionCall);
+ ToolApprovalRequestContent approvalRequest = new(RequestId, functionCall);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
@@ -81,7 +81,7 @@ public async Task FunctionApprovalRequest_WithComplexArguments_GeneratesCorrectE
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall = new(FunctionId, FunctionName, arguments);
- FunctionApprovalRequestContent approvalRequest = new(RequestId, functionCall);
+ ToolApprovalRequestContent approvalRequest = new(RequestId, functionCall);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
@@ -114,7 +114,7 @@ public async Task FunctionApprovalRequest_EmitsCorrectEventSequence_SuccessAsync
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall = new("call-1", "test_function", new Dictionary());
- FunctionApprovalRequestContent approvalRequest = new("req-1", functionCall);
+ ToolApprovalRequestContent approvalRequest = new("req-1", functionCall);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
@@ -150,7 +150,7 @@ public async Task FunctionApprovalRequest_SequenceNumbersAreCorrect_SuccessAsync
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall = new("call-1", "test", new Dictionary());
- FunctionApprovalRequestContent approvalRequest = new("req-1", functionCall);
+ ToolApprovalRequestContent approvalRequest = new("req-1", functionCall);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
@@ -173,7 +173,7 @@ public async Task FunctionApprovalRequest_SequenceNumbersAreCorrect_SuccessAsync
#endregion
- #region FunctionApprovalResponseContent Tests
+ #region ToolApprovalResponseContent Tests
[Fact]
public async Task FunctionApprovalResponse_Approved_GeneratesCorrectEvent_SuccessAsync()
@@ -187,7 +187,7 @@ public async Task FunctionApprovalResponse_Approved_GeneratesCorrectEvent_Succes
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall = new(FunctionId, FunctionName, arguments);
- FunctionApprovalResponseContent approvalResponse = new(RequestId, approved: true, functionCall);
+ ToolApprovalResponseContent approvalResponse = new(RequestId, approved: true, functionCall);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
@@ -221,7 +221,7 @@ public async Task FunctionApprovalResponse_Rejected_GeneratesCorrectEvent_Succes
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall = new(FunctionId, FunctionName, new Dictionary { ["path"] = "/important.txt" });
- FunctionApprovalResponseContent approvalResponse = new(RequestId, approved: false, functionCall);
+ ToolApprovalResponseContent approvalResponse = new(RequestId, approved: false, functionCall);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
@@ -249,7 +249,7 @@ public async Task FunctionApprovalResponse_EmitsCorrectEventSequence_SuccessAsyn
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall = new("call-1", "test_function", new Dictionary());
- FunctionApprovalResponseContent approvalResponse = new("req-1", approved: true, functionCall);
+ ToolApprovalResponseContent approvalResponse = new("req-1", approved: true, functionCall);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
@@ -279,7 +279,7 @@ public async Task MixedContent_ApprovalRequestAndText_GeneratesMultipleEvents_Su
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall = new("call-mixed-1", "test", new Dictionary());
- FunctionApprovalRequestContent approvalRequest = new("req-mixed-1", functionCall);
+ ToolApprovalRequestContent approvalRequest = new("req-mixed-1", functionCall);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
@@ -308,10 +308,10 @@ public async Task MixedContent_MultipleApprovalRequests_GeneratesMultipleEvents_
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates
FunctionCallContent functionCall1 = new("call-multi-1", "function1", new Dictionary());
- FunctionApprovalRequestContent approvalRequest1 = new("req-multi-1", functionCall1);
+ ToolApprovalRequestContent approvalRequest1 = new("req-multi-1", functionCall1);
FunctionCallContent functionCall2 = new("call-multi-2", "function2", new Dictionary());
- FunctionApprovalRequestContent approvalRequest2 = new("req-multi-2", functionCall2);
+ ToolApprovalRequestContent approvalRequest2 = new("req-multi-2", functionCall2);
#pragma warning restore MEAI001
HttpClient client = await this.CreateTestServerAsync(AgentName, "You are a test agent.", string.Empty, (msg) =>
diff --git a/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/OpenAIResponsesIntegrationTests.cs b/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/OpenAIResponsesIntegrationTests.cs
index 0b9441d633..987e2c4d16 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/OpenAIResponsesIntegrationTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/OpenAIResponsesIntegrationTests.cs
@@ -1273,7 +1273,6 @@ private async Task SendRawResponseAsync(
private ResponsesClient CreateResponseClient(string agentName)
{
return new ResponsesClient(
- model: "test-model",
credential: new ApiKeyCredential("test-api-key"),
options: new OpenAIClientOptions
{
diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.IntegrationTests/InvokeToolWorkflowTest.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.IntegrationTests/InvokeToolWorkflowTest.cs
index 9d5efa6b6d..ce27940f21 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.IntegrationTests/InvokeToolWorkflowTest.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.IntegrationTests/InvokeToolWorkflowTest.cs
@@ -123,9 +123,9 @@ private async Task> ProcessFunctionCallsAsync(
foreach (ChatMessage message in toolRequest.AgentResponse.Messages)
{
// Handle approval requests if present
- foreach (FunctionApprovalRequestContent approvalRequest in message.Contents.OfType())
+ foreach (ToolApprovalRequestContent approvalRequest in message.Contents.OfType())
{
- this.Output.WriteLine($"APPROVAL REQUEST: {approvalRequest.FunctionCall.Name}");
+ this.Output.WriteLine($"APPROVAL REQUEST: {((FunctionCallContent)approvalRequest.ToolCall).Name}");
// Auto-approve for testing
results.Add(approvalRequest.CreateResponse(approved: true));
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Events/ExternalInputRequestTest.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Events/ExternalInputRequestTest.cs
index cebdc60cb9..5d3b399cbe 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Events/ExternalInputRequestTest.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Events/ExternalInputRequestTest.cs
@@ -34,7 +34,7 @@ public void VerifySerializationWithRequests()
ChatRole.Assistant,
[
new McpServerToolApprovalRequestContent("call1", new McpServerToolCallContent("call1", "testmcp", "server-name")),
- new FunctionApprovalRequestContent("call2", new FunctionCallContent("call2", "result1")),
+ new ToolApprovalRequestContent("call2", new FunctionCallContent("call2", "result1")),
new FunctionCallContent("call3", "myfunc"),
new TextContent("Heya"),
])));
@@ -49,8 +49,8 @@ public void VerifySerializationWithRequests()
McpServerToolApprovalRequestContent mcpRequest = AssertContent(messageCopy);
Assert.Equal("call1", mcpRequest.Id);
- FunctionApprovalRequestContent functionRequest = AssertContent(messageCopy);
- Assert.Equal("call2", functionRequest.Id);
+ ToolApprovalRequestContent functionRequest = AssertContent(messageCopy);
+ Assert.Equal("call2", functionRequest.RequestId);
FunctionCallContent functionCall = AssertContent(messageCopy);
Assert.Equal("call3", functionCall.CallId);
diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Events/ExternalInputResponseTest.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Events/ExternalInputResponseTest.cs
index 384664a68c..842a024203 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Events/ExternalInputResponseTest.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Events/ExternalInputResponseTest.cs
@@ -33,7 +33,7 @@ public void VerifySerializationWithResponses()
ChatRole.Assistant,
[
new McpServerToolApprovalRequestContent("call1", new McpServerToolCallContent("call1", "testmcp", "server-name")).CreateResponse(approved: true),
- new FunctionApprovalRequestContent("call2", new FunctionCallContent("call2", "result1")).CreateResponse(approved: true),
+ new ToolApprovalRequestContent("call2", new FunctionCallContent("call2", "result1")).CreateResponse(approved: true),
new FunctionResultContent("call3", 33),
new TextContent("Heya"),
]));
@@ -48,8 +48,8 @@ public void VerifySerializationWithResponses()
McpServerToolApprovalResponseContent mcpApproval = AssertContent(responseMessage);
Assert.Equal("call1", mcpApproval.Id);
- FunctionApprovalResponseContent functionApproval = AssertContent(responseMessage);
- Assert.Equal("call2", functionApproval.Id);
+ ToolApprovalResponseContent functionApproval = AssertContent(responseMessage);
+ Assert.Equal("call2", functionApproval.RequestId);
FunctionResultContent functionResult = AssertContent(responseMessage);
Assert.Equal("call3", functionResult.CallId);
diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/AIAgentHostExecutorTests.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/AIAgentHostExecutorTests.cs
index 2ea117856f..063bd77cda 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/AIAgentHostExecutorTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/AIAgentHostExecutorTests.cs
@@ -229,7 +229,7 @@ public async Task Test_AgentHostExecutor_InterceptsRequestsIFFConfiguredAsync(bo
responses = ExtractAndValidateRequestContents();
break;
case TestAgentRequestType.UserInputRequest:
- responses = ExtractAndValidateRequestContents();
+ responses = ExtractAndValidateRequestContents();
break;
default:
throw new NotSupportedException();
diff --git a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/TestRequestAgent.cs b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/TestRequestAgent.cs
index 4faeff29a1..5547b2a539 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/TestRequestAgent.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/TestRequestAgent.cs
@@ -33,7 +33,7 @@ protected override ValueTask CreateSessionCoreAsync(CancellationTo
=> new(requestType switch
{
TestAgentRequestType.FunctionCall => new TestRequestAgentSession(),
- TestAgentRequestType.UserInputRequest => new TestRequestAgentSession(),
+ TestAgentRequestType.UserInputRequest => new TestRequestAgentSession(),
_ => throw new NotSupportedException(),
});
@@ -41,7 +41,7 @@ protected override ValueTask DeserializeSessionCoreAsync(JsonEleme
=> new(requestType switch
{
TestAgentRequestType.FunctionCall => new TestRequestAgentSession(),
- TestAgentRequestType.UserInputRequest => new TestRequestAgentSession(),
+ TestAgentRequestType.UserInputRequest => new TestRequestAgentSession(),
_ => throw new NotSupportedException(),
});
@@ -179,58 +179,58 @@ public void ProcessResponse(FunctionResultContent response, TestRequestAgentSess
}
}
- private sealed class FunctionApprovalStrategy : IRequestResponseStrategy
+ private sealed class FunctionApprovalStrategy : IRequestResponseStrategy
{
- public UserInputResponseContent CreatePairedResponse(UserInputRequestContent request)
+ public ToolApprovalResponseContent CreatePairedResponse(ToolApprovalRequestContent request)
{
- if (request is not FunctionApprovalRequestContent approvalRequest)
+ if (request is not ToolApprovalRequestContent approvalRequest)
{
- throw new InvalidOperationException($"Invalid request: Expecting {typeof(FunctionApprovalResponseContent)}, got {request.GetType()}");
+ throw new InvalidOperationException($"Invalid request: Expecting {typeof(ToolApprovalResponseContent)}, got {request.GetType()}");
}
- return new FunctionApprovalResponseContent(approvalRequest.Id, true, approvalRequest.FunctionCall);
+ return new ToolApprovalResponseContent(approvalRequest.RequestId, true, approvalRequest.ToolCall);
}
- public IEnumerable<(string, UserInputRequestContent)> CreateRequests(int count)
+ public IEnumerable<(string, ToolApprovalRequestContent)> CreateRequests(int count)
{
for (int i = 0; i < count; i++)
{
string id = Guid.NewGuid().ToString("N");
- UserInputRequestContent request = new FunctionApprovalRequestContent(id, new(id, "TestFunction"));
+ ToolApprovalRequestContent request = new ToolApprovalRequestContent(id, new FunctionCallContent(id, "TestFunction"));
yield return (id, request);
}
}
- public void ProcessResponse(UserInputResponseContent response, TestRequestAgentSession session)
+ public void ProcessResponse(ToolApprovalResponseContent response, TestRequestAgentSession session)
{
- if (session.UnservicedRequests.TryGetValue(response.Id, out UserInputRequestContent? request))
+ if (session.UnservicedRequests.TryGetValue(response.RequestId, out ToolApprovalRequestContent? request))
{
- if (request is not FunctionApprovalRequestContent approvalRequest)
+ if (request is not ToolApprovalRequestContent approvalRequest)
{
- throw new InvalidOperationException($"Invalid request: Expecting {typeof(FunctionApprovalResponseContent)}, got {request.GetType()}");
+ throw new InvalidOperationException($"Invalid request: Expecting {typeof(ToolApprovalResponseContent)}, got {request.GetType()}");
}
- if (response is not FunctionApprovalResponseContent approvalResponse)
+ if (response is not ToolApprovalResponseContent approvalResponse)
{
- throw new InvalidOperationException($"Invalid response: Expecting {typeof(FunctionApprovalResponseContent)}, got {response.GetType()}");
+ throw new InvalidOperationException($"Invalid response: Expecting {typeof(ToolApprovalResponseContent)}, got {response.GetType()}");
}
approvalResponse.Approved.Should().BeTrue();
- approvalResponse.FunctionCall.As().Should().Be(approvalRequest.FunctionCall);
- session.ServicedRequests.Add(response.Id);
- session.UnservicedRequests.Remove(response.Id);
+ ((FunctionCallContent)approvalResponse.ToolCall).Should().Be((FunctionCallContent)approvalRequest.ToolCall);
+ session.ServicedRequests.Add(response.RequestId);
+ session.UnservicedRequests.Remove(response.RequestId);
}
- else if (session.ServicedRequests.Contains(response.Id))
+ else if (session.ServicedRequests.Contains(response.RequestId))
{
- throw new InvalidOperationException($"Seeing duplicate response with id {response.Id}");
+ throw new InvalidOperationException($"Seeing duplicate response with id {response.RequestId}");
}
- else if (session.PairedRequests.Contains(response.Id))
+ else if (session.PairedRequests.Contains(response.RequestId))
{
- throw new InvalidOperationException($"Seeing explicit response to initially paired request with id {response.Id}");
+ throw new InvalidOperationException($"Seeing explicit response to initially paired request with id {response.RequestId}");
}
else
{
- throw new InvalidOperationException($"Seeing response to nonexistent request with id {response.Id}");
+ throw new InvalidOperationException($"Seeing response to nonexistent request with id {response.RequestId}");
}
}
}
@@ -261,7 +261,7 @@ private static string RetrieveId(TRequest request)
return request switch
{
FunctionCallContent functionCall => functionCall.CallId,
- UserInputRequestContent userInputRequest => userInputRequest.Id,
+ ToolApprovalRequestContent userInputRequest => userInputRequest.RequestId,
_ => throw new NotSupportedException($"Unknown request type {typeof(TRequest)}"),
};
}
@@ -295,12 +295,12 @@ internal IEnumerable