// Copyright (c) Microsoft. All rights reserved.
using System.ClientModel.Primitives;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Microsoft.Agents.AI.Foundry;
///
/// Pipeline policy that captures the x-ms-served-model response header from Azure OpenAI
/// and stores it in for consumption by .
///
///
///
/// Azure OpenAI Responses API returns the deployment alias in response.model but the actual
/// model snapshot (e.g. gpt-5-nano-2025-08-07) in the x-ms-served-model response header.
/// This policy extracts the header after the HTTP roundtrip so the
/// can overwrite ChatResponse.ModelId with the true model name.
///
///
/// Registered once per OpenAIRequestPolicies instance via the MEAI 10.5.1 extension hook.
/// When the header is absent (non-Azure endpoints), the scope is not set and the
/// preserves the original model name.
///
///
internal sealed class ServedModelPolicy : PipelinePolicy
{
/// The Azure OpenAI response header that carries the actual served model name.
internal const string ServedModelHeader = "x-ms-served-model";
public static ServedModelPolicy Instance { get; } = new ServedModelPolicy();
private ServedModelPolicy()
{
}
public override void Process(PipelineMessage message, IReadOnlyList pipeline, int currentIndex)
{
ProcessNext(message, pipeline, currentIndex);
CaptureServedModel(message);
}
public override async ValueTask ProcessAsync(PipelineMessage message, IReadOnlyList pipeline, int currentIndex)
{
await ProcessNextAsync(message, pipeline, currentIndex).ConfigureAwait(false);
CaptureServedModel(message);
}
private static void CaptureServedModel(PipelineMessage message)
{
if (message.Response is null)
{
return;
}
if (message.Response.Headers.TryGetValue(ServedModelHeader, out string? servedModel)
&& !string.IsNullOrWhiteSpace(servedModel))
{
// Write into the box (reference-type mutation) so the value is visible to the
// FoundryChatClient that pushed the box before calling the inner client.
if (ServedModelScope.Current is { } box)
{
box.Value = servedModel.Trim();
}
}
}
}