Address PR review comments: experimental attrs, doc fixes, token propagation

- Add [Experimental(OPENAI001)] to all 7 public Hosting types per reviewer request
- Fix McpConsentContext XML doc: 'Thread-static' -> 'Async-local' (AsyncLocal
  flows with ExecutionContext, not thread-static)
- Expand UserAgentMiddleware test regex to match prerelease versions (e.g. 1.0.0-rc.4)
- Propagate CancellationToken in AgentFrameworkResponseHandler session save

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
alliscode
2026-04-21 12:16:04 -07:00
Unverified
parent a01e3f14b2
commit 22a2fb15ef
9 changed files with 25 additions and 4 deletions
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Threading;
using Azure.AI.AgentServer.Responses;
@@ -9,6 +10,7 @@ using Azure.AI.AgentServer.Responses.Models;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Shared.DiagnosticIds;
namespace Microsoft.Agents.AI.Foundry.Hosting;
@@ -17,6 +19,7 @@ namespace Microsoft.Agents.AI.Foundry.Hosting;
/// with agent-framework <see cref="AIAgent"/> instances, enabling agent-framework agents and workflows
/// to be hosted as Azure Foundry Hosted Agents.
/// </summary>
[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
public class AgentFrameworkResponseHandler : ResponseHandler
{
private readonly IServiceProvider _serviceProvider;
@@ -275,7 +278,7 @@ public class AgentFrameworkResponseHandler : ResponseHandler
// Persist session after streaming completes (successful or not)
if (session is not null && !string.IsNullOrWhiteSpace(sessionConversationId))
{
await sessionStore.SaveSessionAsync(agent, sessionConversationId, session, CancellationToken.None).ConfigureAwait(false);
await sessionStore.SaveSessionAsync(agent, sessionConversationId, session, cancellationToken).ConfigureAwait(false);
}
}
}
@@ -1,7 +1,9 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Shared.DiagnosticIds;
namespace Microsoft.Agents.AI.Foundry.Hosting;
@@ -13,6 +15,7 @@ namespace Microsoft.Agents.AI.Foundry.Hosting;
/// allowing conversations to be resumed across HTTP requests, application restarts,
/// or different service instances in hosted scenarios.
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
public abstract class AgentSessionStore
{
/// <summary>
@@ -1,8 +1,10 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Diagnostics.CodeAnalysis;
using Azure.AI.Projects.Agents;
using Microsoft.Extensions.AI;
using Microsoft.Shared.DiagnosticIds;
namespace Microsoft.Agents.AI.Foundry.Hosting;
@@ -10,6 +12,7 @@ namespace Microsoft.Agents.AI.Foundry.Hosting;
/// Extension methods for <see cref="FoundryAITool"/> that require Azure.AI.Projects 2.1.0-beta.1+
/// types (e.g. <see cref="ToolboxRecord"/>, <see cref="ToolboxVersion"/>).
/// </summary>
[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
public static class FoundryAIToolExtensions
{
/// <summary>
@@ -1,12 +1,15 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Shared.DiagnosticIds;
namespace Microsoft.Agents.AI.Foundry.Hosting;
/// <summary>
/// Options for Foundry Toolbox MCP integration.
/// </summary>
[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
public sealed class FoundryToolboxOptions
{
/// <summary>
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
@@ -11,6 +12,7 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Microsoft.Shared.DiagnosticIds;
using ModelContextProtocol.Client;
namespace Microsoft.Agents.AI.Foundry.Hosting;
@@ -33,6 +35,7 @@ namespace Microsoft.Agents.AI.Foundry.Hosting;
/// lazily connected otherwise.
/// </para>
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
public sealed class FoundryToolboxService : IHostedService, IAsyncDisposable
{
private readonly FoundryToolboxOptions _options;
@@ -1,9 +1,11 @@
// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Shared.DiagnosticIds;
namespace Microsoft.Agents.AI.Foundry.Hosting;
@@ -25,6 +27,7 @@ namespace Microsoft.Agents.AI.Foundry.Hosting;
/// such as Redis, SQL Server, or Azure Cosmos DB.
/// </para>
/// </remarks>
[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
public sealed class InMemoryAgentSessionStore : AgentSessionStore
{
private readonly ConcurrentDictionary<string, JsonElement> _sessions = new();
@@ -31,9 +31,9 @@ internal sealed class RequestConsentState
}
/// <summary>
/// Thread-static (AsyncLocal) context that enables <see cref="ConsentAwareMcpClientAIFunction"/>
/// Async-local context that enables <see cref="ConsentAwareMcpClientAIFunction"/>
/// to signal a consent error back to <see cref="AgentFrameworkResponseHandler"/> through the
/// <see cref="FunctionInvokingChatClient"/> tool loop.
/// <see cref="FunctionInvokingChatClient"/> tool loop. Flows with the async ExecutionContext.
/// </summary>
internal static class McpConsentContext
{
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading.Tasks;
using Azure.AI.AgentServer.Responses;
@@ -11,6 +12,7 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Shared.DiagnosticIds;
namespace Microsoft.Agents.AI.Foundry.Hosting;
@@ -18,6 +20,7 @@ namespace Microsoft.Agents.AI.Foundry.Hosting;
/// Extension methods for registering agent-framework agents as Foundry Hosted Agents
/// using the Azure AI Responses Server SDK.
/// </summary>
[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
public static class FoundryHostingExtensions
{
/// <summary>
@@ -20,7 +20,7 @@ namespace Microsoft.Agents.AI.Foundry.UnitTests.Hosting;
/// </summary>
public sealed partial class UserAgentMiddlewareTests : IAsyncDisposable
{
private const string VersionedUserAgentPattern = @"agent-framework-dotnet/\d+\.\d+\.\d+";
private const string VersionedUserAgentPattern = @"agent-framework-dotnet/\d+\.\d+\.\d+(-[\w.]+)?";
private WebApplication? _app;
private HttpClient? _httpClient;