diff --git a/eng/packages/General.props b/eng/packages/General.props
index 253fb51ce1b..b7066789238 100644
--- a/eng/packages/General.props
+++ b/eng/packages/General.props
@@ -16,7 +16,7 @@
     
     
     
-    
+    
     
     
     
diff --git a/eng/packages/TestOnly.props b/eng/packages/TestOnly.props
index dcfc7c03525..d8748a4ae9c 100644
--- a/eng/packages/TestOnly.props
+++ b/eng/packages/TestOnly.props
@@ -2,7 +2,7 @@
 
   
     
-    
+    
     
     
     
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md b/src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md
index 1c1c175ccd4..15859a5744d 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/CHANGELOG.md
@@ -4,6 +4,7 @@
 
 - Updated tool mappings to recognize any `AIFunctionDeclaration`.
 - Updated to accommodate the additions in `Microsoft.Extensions.AI.Abstractions`.
+- Updated to depend on OpenAI 2.4.0
 
 ## 9.8.0-preview.1.25412.6
 
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIResponsesExtensions.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIResponsesExtensions.cs
index d6b290f431b..51df2653695 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIResponsesExtensions.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/MicrosoftExtensionsAIResponsesExtensions.cs
@@ -18,7 +18,7 @@ public static class MicrosoftExtensionsAIResponsesExtensions
     /// The function to convert.
     /// An OpenAI  representing .
     ///  is .
-    public static ResponseTool AsOpenAIResponseTool(this AIFunctionDeclaration function) =>
+    public static FunctionTool AsOpenAIResponseTool(this AIFunctionDeclaration function) =>
         OpenAIResponsesChatClient.ToResponseTool(Throw.IfNull(function));
 
     /// Creates a sequence of OpenAI  instances from the specified input messages.
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIAssistantsChatClient.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIAssistantsChatClient.cs
index 01b78994f38..424185db887 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIAssistantsChatClient.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIAssistantsChatClient.cs
@@ -4,7 +4,6 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Text;
 using System.Text.Json;
@@ -50,17 +49,9 @@ public OpenAIAssistantsChatClient(AssistantClient assistantClient, string assist
     {
         _client = Throw.IfNull(assistantClient);
         _assistantId = Throw.IfNullOrWhitespace(assistantId);
-
         _defaultThreadId = defaultThreadId;
 
-        // https://github.com/openai/openai-dotnet/issues/215
-        // The endpoint isn't currently exposed, so use reflection to get at it, temporarily. Once packages
-        // implement the abstractions directly rather than providing adapters on top of the public APIs,
-        // the package can provide such implementations separate from what's exposed in the public API.
-        Uri providerUrl = typeof(AssistantClient).GetField("_endpoint", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
-            ?.GetValue(assistantClient) as Uri ?? OpenAIClientExtensions.DefaultOpenAIEndpoint;
-
-        _metadata = new("openai", providerUrl);
+        _metadata = new("openai", assistantClient.Endpoint);
     }
 
     /// Initializes a new instance of the  class for the specified .
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIChatClient.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIChatClient.cs
index 415aef5901e..8c65766413f 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIChatClient.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIChatClient.cs
@@ -4,7 +4,6 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Text;
 using System.Text.Json;
@@ -37,18 +36,9 @@ internal sealed class OpenAIChatClient : IChatClient
     ///  is .
     public OpenAIChatClient(ChatClient chatClient)
     {
-        _ = Throw.IfNull(chatClient);
+        _chatClient = Throw.IfNull(chatClient);
 
-        _chatClient = chatClient;
-
-        // https://github.com/openai/openai-dotnet/issues/215
-        // The endpoint and model aren't currently exposed, so use reflection to get at them, temporarily. Once packages
-        // implement the abstractions directly rather than providing adapters on top of the public APIs,
-        // the package can provide such implementations separate from what's exposed in the public API.
-        Uri providerUrl = typeof(ChatClient).GetField("_endpoint", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
-            ?.GetValue(chatClient) as Uri ?? OpenAIClientExtensions.DefaultOpenAIEndpoint;
-
-        _metadata = new("openai", providerUrl, _chatClient.Model);
+        _metadata = new("openai", chatClient.Endpoint, _chatClient.Model);
     }
 
     /// 
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIEmbeddingGenerator.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIEmbeddingGenerator.cs
index 84f3c5966b8..dbe9bf10237 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIEmbeddingGenerator.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIEmbeddingGenerator.cs
@@ -4,7 +4,6 @@
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Reflection;
 using System.Threading;
 using System.Threading.Tasks;
 using Microsoft.Shared.Diagnostics;
@@ -18,9 +17,6 @@ namespace Microsoft.Extensions.AI;
 /// An  for an OpenAI .
 internal sealed class OpenAIEmbeddingGenerator : IEmbeddingGenerator>
 {
-    /// Default OpenAI endpoint.
-    private const string DefaultOpenAIEndpoint = "https://api.openai.com/v1";
-
     /// Metadata about the embedding generator.
     private readonly EmbeddingGeneratorMetadata _metadata;
 
@@ -37,24 +33,15 @@ internal sealed class OpenAIEmbeddingGenerator : IEmbeddingGenerator is not positive.
     public OpenAIEmbeddingGenerator(EmbeddingClient embeddingClient, int? defaultModelDimensions = null)
     {
-        _ = Throw.IfNull(embeddingClient);
+        _embeddingClient = Throw.IfNull(embeddingClient);
+        _dimensions = defaultModelDimensions;
+
         if (defaultModelDimensions < 1)
         {
             Throw.ArgumentOutOfRangeException(nameof(defaultModelDimensions), "Value must be greater than 0.");
         }
 
-        _embeddingClient = embeddingClient;
-        _dimensions = defaultModelDimensions;
-
-        // https://github.com/openai/openai-dotnet/issues/215
-        // The endpoint and model aren't currently exposed, so use reflection to get at them, temporarily. Once packages
-        // implement the abstractions directly rather than providing adapters on top of the public APIs,
-        // the package can provide such implementations separate from what's exposed in the public API.
-        string providerUrl = (typeof(EmbeddingClient).GetField("_endpoint", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
-            ?.GetValue(embeddingClient) as Uri)?.ToString() ??
-            DefaultOpenAIEndpoint;
-
-        _metadata = CreateMetadata("openai", providerUrl, _embeddingClient.Model, defaultModelDimensions);
+        _metadata = new("openai", embeddingClient.Endpoint, _embeddingClient.Model, defaultModelDimensions);
     }
 
     /// 
@@ -98,10 +85,6 @@ void IDisposable.Dispose()
             null;
     }
 
-    /// Creates the  for this instance.
-    private static EmbeddingGeneratorMetadata CreateMetadata(string providerName, string providerUrl, string? defaultModelId, int? defaultModelDimensions) =>
-        new(providerName, Uri.TryCreate(providerUrl, UriKind.Absolute, out Uri? providerUri) ? providerUri : null, defaultModelId, defaultModelDimensions);
-
     /// Converts an extensions options instance to an OpenAI options instance.
     private OpenAI.Embeddings.EmbeddingGenerationOptions ToOpenAIOptions(EmbeddingGenerationOptions? options)
     {
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIImageGenerator.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIImageGenerator.cs
index fe1cb399e0d..b2ceb5cb317 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIImageGenerator.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIImageGenerator.cs
@@ -45,18 +45,9 @@ internal sealed class OpenAIImageGenerator : IImageGenerator
     ///  is .
     public OpenAIImageGenerator(ImageClient imageClient)
     {
-        _ = Throw.IfNull(imageClient);
+        _imageClient = Throw.IfNull(imageClient);
 
-        _imageClient = imageClient;
-
-        // https://github.com/openai/openai-dotnet/issues/215
-        // The endpoint and model aren't currently exposed, so use reflection to get at them, temporarily. Once packages
-        // implement the abstractions directly rather than providing adapters on top of the public APIs,
-        // the package can provide such implementations separate from what's exposed in the public API.
-        Uri providerUrl = typeof(ImageClient).GetField("_endpoint", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
-            ?.GetValue(imageClient) as Uri ?? OpenAIClientExtensions.DefaultOpenAIEndpoint;
-
-        _metadata = new("openai", providerUrl, _imageClient.Model);
+        _metadata = new("openai", imageClient.Endpoint, _imageClient.Model);
     }
 
     /// 
@@ -143,7 +134,7 @@ private static ImageGenerationResponse ToImageGenerationResponse(GeneratedImageC
 
         // OpenAI doesn't expose the content type, so we need to read from the internal JSON representation.
         // https://github.com/openai/openai-dotnet/issues/561
-        IDictionary? additionalRawData = typeof(GeneratedImageCollection)
+        var additionalRawData = typeof(GeneratedImageCollection)
             .GetProperty("SerializedAdditionalRawData", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
             ?.GetValue(generatedImages) as IDictionary;
 
@@ -154,7 +145,7 @@ private static ImageGenerationResponse ToImageGenerationResponse(GeneratedImageC
             contentType = $"image/{outputFormatString}";
         }
 
-        List contents = new();
+        List contents = [];
 
         foreach (GeneratedImage image in generatedImages)
         {
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs
index b5d3c09de32..0acfef52eb0 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponsesChatClient.cs
@@ -8,7 +8,6 @@
 using System.Linq;
 using System.Reflection;
 using System.Runtime.CompilerServices;
-using System.Text;
 using System.Text.Json;
 using System.Threading;
 using System.Threading.Tasks;
@@ -47,16 +46,12 @@ public OpenAIResponsesChatClient(OpenAIResponseClient responseClient)
 
         _responseClient = responseClient;
 
-        // https://github.com/openai/openai-dotnet/issues/215
-        // The endpoint and model aren't currently exposed, so use reflection to get at them, temporarily. Once packages
-        // implement the abstractions directly rather than providing adapters on top of the public APIs,
-        // the package can provide such implementations separate from what's exposed in the public API.
-        Uri providerUrl = typeof(OpenAIResponseClient).GetField("_endpoint", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
-            ?.GetValue(responseClient) as Uri ?? OpenAIClientExtensions.DefaultOpenAIEndpoint;
+        // https://github.com/openai/openai-dotnet/issues/662
+        // Update to avoid reflection once OpenAIResponseClient.Model is exposed publicly.
         string? model = typeof(OpenAIResponseClient).GetField("_model", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
             ?.GetValue(responseClient) as string;
 
-        _metadata = new("openai", providerUrl, model);
+        _metadata = new("openai", responseClient.Endpoint, model);
     }
 
     /// 
@@ -204,7 +199,7 @@ internal static async IAsyncEnumerable FromOpenAIStreamingRe
         string? lastMessageId = null;
         ChatRole? lastRole = null;
         Dictionary outputIndexToMessages = [];
-        Dictionary? functionCallInfos = null;
+        Dictionary? functionCallItems = null;
 
         await foreach (var streamingUpdate in streamingResponseUpdates.WithCancellation(cancellationToken).ConfigureAwait(false))
         {
@@ -234,7 +229,7 @@ ChatResponseUpdate CreateUpdate(AIContent? content = null) =>
                     var update = CreateUpdate(ToUsageDetails(completedUpdate.Response) is { } usage ? new UsageContent(usage) : null);
                     update.FinishReason =
                         ToFinishReason(completedUpdate.Response?.IncompleteStatusDetails?.Reason) ??
-                        (functionCallInfos is not null ? ChatFinishReason.ToolCalls :
+                        (functionCallItems is not null ? ChatFinishReason.ToolCalls :
                         ChatFinishReason.Stop);
                     yield return update;
                     break;
@@ -248,7 +243,7 @@ ChatResponseUpdate CreateUpdate(AIContent? content = null) =>
                             break;
 
                         case FunctionCallResponseItem fcri:
-                            (functionCallInfos ??= [])[outputItemAddedUpdate.OutputIndex] = new(fcri);
+                            (functionCallItems ??= [])[outputItemAddedUpdate.OutputIndex] = fcri;
                             break;
                     }
 
@@ -283,28 +278,18 @@ ChatResponseUpdate CreateUpdate(AIContent? content = null) =>
                     break;
                 }
 
-                case StreamingResponseFunctionCallArgumentsDeltaUpdate functionCallArgumentsDeltaUpdate:
-                {
-                    if (functionCallInfos?.TryGetValue(functionCallArgumentsDeltaUpdate.OutputIndex, out FunctionCallInfo? callInfo) is true)
-                    {
-                        _ = (callInfo.Arguments ??= new()).Append(functionCallArgumentsDeltaUpdate.Delta);
-                    }
-
-                    goto default;
-                }
-
                 case StreamingResponseFunctionCallArgumentsDoneUpdate functionCallOutputDoneUpdate:
                 {
-                    if (functionCallInfos?.TryGetValue(functionCallOutputDoneUpdate.OutputIndex, out FunctionCallInfo? callInfo) is true)
+                    if (functionCallItems?.TryGetValue(functionCallOutputDoneUpdate.OutputIndex, out FunctionCallResponseItem? callInfo) is true)
                     {
-                        _ = functionCallInfos.Remove(functionCallOutputDoneUpdate.OutputIndex);
+                        _ = functionCallItems.Remove(functionCallOutputDoneUpdate.OutputIndex);
 
                         var fcc = OpenAIClientExtensions.ParseCallContent(
-                            callInfo.Arguments?.ToString() ?? string.Empty,
-                            callInfo.ResponseItem.CallId,
-                            callInfo.ResponseItem.FunctionName);
+                            functionCallOutputDoneUpdate.FunctionArguments.ToString(),
+                            callInfo.CallId,
+                            callInfo.FunctionName);
 
-                        lastMessageId = callInfo.ResponseItem.Id;
+                        lastMessageId = callInfo.Id;
                         lastRole = ChatRole.Assistant;
 
                         yield return CreateUpdate(fcc);
@@ -329,18 +314,16 @@ ChatResponseUpdate CreateUpdate(AIContent? content = null) =>
                     });
                     break;
 
-                default:
-                {
-                    if (streamingUpdate.GetType() == _internalResponseReasoningSummaryTextDeltaEventType &&
-                        _summaryTextDeltaProperty?.GetValue(streamingUpdate) is string delta)
-                    {
-                        yield return CreateUpdate(new TextReasoningContent(delta));
-                        break;
-                    }
+                // Replace with public StreamingResponseReasoningSummaryTextDelta when available
+                case StreamingResponseUpdate when
+                        streamingUpdate.GetType() == _internalResponseReasoningSummaryTextDeltaEventType &&
+                        _summaryTextDeltaProperty?.GetValue(streamingUpdate) is string delta:
+                    yield return CreateUpdate(new TextReasoningContent(delta));
+                    break;
 
+                default:
                     yield return CreateUpdate();
                     break;
-                }
             }
         }
     }
@@ -351,7 +334,7 @@ void IDisposable.Dispose()
         // Nothing to dispose. Implementation required for the IChatClient interface.
     }
 
-    internal static ResponseTool ToResponseTool(AIFunctionDeclaration aiFunction, ChatOptions? options = null)
+    internal static FunctionTool ToResponseTool(AIFunctionDeclaration aiFunction, ChatOptions? options = null)
     {
         bool? strict =
             OpenAIClientExtensions.HasStrict(aiFunction.AdditionalProperties) ??
@@ -359,9 +342,9 @@ internal static ResponseTool ToResponseTool(AIFunctionDeclaration aiFunction, Ch
 
         return ResponseTool.CreateFunctionTool(
             aiFunction.Name,
-            aiFunction.Description,
             OpenAIClientExtensions.ToOpenAIFunctionParameters(aiFunction, strict),
-            strict ?? false);
+            strict,
+            aiFunction.Description);
     }
 
     /// Creates a  from a .
@@ -419,17 +402,17 @@ private ResponseCreationOptions ToOpenAIResponseCreationOptions(ChatOptions? opt
                         break;
 
                     case HostedWebSearchTool webSearchTool:
-                        WebSearchUserLocation? location = null;
-                        if (webSearchTool.AdditionalProperties.TryGetValue(nameof(WebSearchUserLocation), out object? objLocation))
+                        WebSearchToolLocation? location = null;
+                        if (webSearchTool.AdditionalProperties.TryGetValue(nameof(WebSearchToolLocation), out object? objLocation))
                         {
-                            location = objLocation as WebSearchUserLocation;
+                            location = objLocation as WebSearchToolLocation;
                         }
 
-                        WebSearchContextSize? size = null;
-                        if (webSearchTool.AdditionalProperties.TryGetValue(nameof(WebSearchContextSize), out object? objSize) &&
-                            objSize is WebSearchContextSize)
+                        WebSearchToolContextSize? size = null;
+                        if (webSearchTool.AdditionalProperties.TryGetValue(nameof(WebSearchToolContextSize), out object? objSize) &&
+                            objSize is WebSearchToolContextSize)
                         {
-                            size = (WebSearchContextSize)objSize;
+                            size = (WebSearchToolContextSize)objSize;
                         }
 
                         result.Tools.Add(ResponseTool.CreateWebSearchTool(location, size));
@@ -690,14 +673,29 @@ private static void PopulateAnnotations(ResponseContentPart source, AIContent de
         {
             foreach (var ota in source.OutputTextAnnotations)
             {
-                (destination.Annotations ??= []).Add(new CitationAnnotation
+                CitationAnnotation ca = new()
                 {
                     RawRepresentation = ota,
-                    AnnotatedRegions = [new TextSpanAnnotatedRegion { StartIndex = ota.UriCitationStartIndex, EndIndex = ota.UriCitationEndIndex }],
-                    Title = ota.UriCitationTitle,
-                    Url = ota.UriCitationUri,
-                    FileId = ota.FileCitationFileId ?? ota.FilePathFileId,
-                });
+                };
+
+                switch (ota)
+                {
+                    case UriCitationMessageAnnotation ucma:
+                        ca.AnnotatedRegions = [new TextSpanAnnotatedRegion { StartIndex = ucma.StartIndex, EndIndex = ucma.EndIndex }];
+                        ca.Title = ucma.Title;
+                        ca.Url = ucma.Uri;
+                        break;
+
+                    case FilePathMessageAnnotation fpma:
+                        ca.FileId = fpma.FileId;
+                        break;
+
+                    case FileCitationMessageAnnotation fcma:
+                        ca.FileId = fcma.FileId;
+                        break;
+                }
+
+                (destination.Annotations ??= []).Add(ca);
             }
         }
     }
@@ -747,12 +745,4 @@ private static List ToResponseContentParts(IList
 
         return parts;
     }
-
-    /// POCO representing function calling info.
-    /// Used to concatenation information for a single function call from across multiple streaming updates.
-    private sealed class FunctionCallInfo(FunctionCallResponseItem item)
-    {
-        public readonly FunctionCallResponseItem ResponseItem = item;
-        public StringBuilder? Arguments;
-    }
 }
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAISpeechToTextClient.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAISpeechToTextClient.cs
index 2e2503335f3..06051a54c26 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAISpeechToTextClient.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAISpeechToTextClient.cs
@@ -5,7 +5,6 @@
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.IO;
-using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Threading;
 using System.Threading.Tasks;
@@ -37,18 +36,9 @@ internal sealed class OpenAISpeechToTextClient : ISpeechToTextClient
     /// The underlying client.
     public OpenAISpeechToTextClient(AudioClient audioClient)
     {
-        _ = Throw.IfNull(audioClient);
+        _audioClient = Throw.IfNull(audioClient);
 
-        _audioClient = audioClient;
-
-        // https://github.com/openai/openai-dotnet/issues/215
-        // The endpoint and model aren't currently exposed, so use reflection to get at them, temporarily. Once packages
-        // implement the abstractions directly rather than providing adapters on top of the public APIs,
-        // the package can provide such implementations separate from what's exposed in the public API.
-        Uri providerUrl = typeof(AudioClient).GetField("_endpoint", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
-            ?.GetValue(audioClient) as Uri ?? OpenAIClientExtensions.DefaultOpenAIEndpoint;
-
-        _metadata = new("openai", providerUrl, _audioClient.Model);
+        _metadata = new("openai", audioClient.Endpoint, _audioClient.Model);
     }
 
     /// 
diff --git a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/ChatClientIntegrationTests.cs b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/ChatClientIntegrationTests.cs
index c87625cf143..448de8d11df 100644
--- a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/ChatClientIntegrationTests.cs
+++ b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/ChatClientIntegrationTests.cs
@@ -942,7 +942,7 @@ public virtual async Task OpenTelemetry_CanEmitTracesAndMetrics()
 
         var activity = Assert.Single(activities);
         Assert.StartsWith("chat", activity.DisplayName);
-        Assert.StartsWith("http", (string)activity.GetTagItem("server.address")!);
+        Assert.Contains(".", (string)activity.GetTagItem("server.address")!);
         Assert.Equal(chatClient.GetService()?.ProviderUri?.Port, (int)activity.GetTagItem("server.port")!);
         Assert.NotNull(activity.Id);
         Assert.NotEmpty(activity.Id);
@@ -1276,7 +1276,7 @@ public virtual async Task SummarizingChatReducer_Streaming()
             new(ChatRole.Assistant, "That sounds impactful! AI in education has so much potential."),
             new(ChatRole.User, "Yes, we focus on personalized learning experiences."),
             new(ChatRole.Assistant, "Personalized learning is the future of education!"),
-            new(ChatRole.User, "What's my name and profession?")
+            new(ChatRole.User, "Was anyone named in the conversation? Provide their name and job.")
         ];
 
         StringBuilder sb = new();
@@ -1296,7 +1296,7 @@ public virtual async Task SummarizingChatReducer_Streaming()
                 Assert.Contains("Bob", m.Text);
             },
             m => Assert.StartsWith("Personalized learning", m.Text, StringComparison.Ordinal),
-            m => Assert.Equal("What's my name and profession?", m.Text));
+            m => Assert.Equal("Was anyone named in the conversation? Provide their name and job.", m.Text));
 
         string responseText = sb.ToString();
         Assert.Contains("Bob", responseText);
diff --git a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIChatClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIChatClientTests.cs
index 640dab54f8e..bdf3b2e7c0a 100644
--- a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIChatClientTests.cs
+++ b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIChatClientTests.cs
@@ -8,8 +8,6 @@
 using System.ComponentModel;
 using System.Linq;
 using System.Net.Http;
-using System.Text.Json;
-using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Caching.Distributed;
 using Microsoft.Extensions.Caching.Memory;
@@ -655,22 +653,6 @@ public async Task ChatOptions_Overwrite_NullPropertiesInRawRepresentation_Stream
         Assert.Equal("Hello! How can I assist you today?", responseText);
     }
 
-    /// Used to create the JSON payload for an OpenAI chat tool description.
-    internal sealed class ChatToolJson
-    {
-        [JsonPropertyName("type")]
-        public string Type { get; set; } = "object";
-
-        [JsonPropertyName("required")]
-        public HashSet Required { get; set; } = [];
-
-        [JsonPropertyName("properties")]
-        public Dictionary Properties { get; set; } = [];
-
-        [JsonPropertyName("additionalProperties")]
-        public bool AdditionalProperties { get; set; }
-    }
-
     [Fact]
     public async Task StronglyTypedOptions_AllSent()
     {
diff --git a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientIntegrationTests.cs b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientIntegrationTests.cs
index 630af9e34b0..007e86288f5 100644
--- a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientIntegrationTests.cs
+++ b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientIntegrationTests.cs
@@ -27,7 +27,7 @@ public async Task UseWebSearch_AnnotationsReflectResults()
         SkipIfNotEnabled();
 
         var response = await ChatClient.GetResponseAsync(
-            "Write a paragraph about the three most recent blog posts on the .NET blog. Cite your sources.",
+            "Write a paragraph about .NET based on at least three recent news articles. Cite your sources.",
             new() { Tools = [new HostedWebSearchTool()] });
 
         ChatMessage m = Assert.Single(response.Messages);
diff --git a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs
index ca71aee550f..014fae0d39f 100644
--- a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs
+++ b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIResponseClientTests.cs
@@ -8,7 +8,6 @@
 using System.ComponentModel;
 using System.Linq;
 using System.Net.Http;
-using System.Text.Json;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Caching.Distributed;
 using Microsoft.Extensions.Caching.Memory;
@@ -543,20 +542,70 @@ public async Task ChatOptions_DoNotOverwrite_NotNullPropertiesInRawRepresentatio
     {
         const string Input = """
             {
-              "input":[{"type":"message","role":"user","content":[{"type":"input_text","text":"hello"}]}],
-              "model":"gpt-4o-mini",
-              "max_output_tokens":10,
-              "previous_response_id":"resp_42",
-              "top_p":0.5,
-              "temperature":0.5,
-              "parallel_tool_calls":true,
-              "text": {"format": {"type": "text"}
-            },
-              "tool_choice":"auto",
-              "tools":[
-                {"description":"Gets the age of the specified person.","name":"GetPersonAge","parameters":{"additionalProperties":false,"properties":{"personName":{"description":"The person whose age is being requested","type":"string"}},"required":["personName"],"type":"object"},"strict":false,"type":"function"},
-                {"description":"Gets the age of the specified person.","name":"GetPersonAge","parameters":{"additionalProperties":false,"properties":{"personName":{"description":"The person whose age is being requested","type":"string"}},"required":["personName"],"type":"object"},"strict":false,"type":"function"}
-              ]
+                "temperature": 0.5,
+                "top_p": 0.5,
+                "previous_response_id": "resp_42",
+                "model": "gpt-4o-mini",
+                "max_output_tokens": 10,
+                "text": {
+                    "format": {
+                        "type": "text"
+                    }
+                },
+                "tools": [
+                    {
+                        "type": "function",
+                        "name": "GetPersonAge",
+                        "description": "Gets the age of the specified person.",
+                        "parameters": {
+                            "type": "object",
+                            "required": [
+                                "personName"
+                            ],
+                            "properties": {
+                                "personName": {
+                                    "description": "The person whose age is being requested",
+                                    "type": "string"
+                                }
+                            },
+                            "additionalProperties": false
+                        },
+                        "strict": null
+                    },
+                    {
+                        "type": "function",
+                        "name": "GetPersonAge",
+                        "description": "Gets the age of the specified person.",
+                        "parameters": {
+                            "type": "object",
+                            "required": [
+                                "personName"
+                            ],
+                            "properties": {
+                                "personName": {
+                                    "description": "The person whose age is being requested",
+                                    "type": "string"
+                                }
+                            },
+                            "additionalProperties": false
+                        },
+                        "strict": null
+                    }
+                ],
+                "tool_choice": "auto",
+                "input": [
+                    {
+                        "type": "message",
+                        "role": "user",
+                        "content": [
+                            {
+                                "type": "input_text",
+                                "text": "hello"
+                            }
+                        ]
+                    }
+                ],
+                "parallel_tool_calls": true
             }
             """;
 
@@ -640,7 +689,7 @@ public async Task ChatOptions_DoNotOverwrite_NotNullPropertiesInRawRepresentatio
                         TextFormat = ResponseTextFormat.CreateTextFormat()
                     },
                 };
-                openAIOptions.Tools.Add(ToOpenAIResponseChatTool(tool));
+                openAIOptions.Tools.Add(tool.AsOpenAIResponseTool());
                 return openAIOptions;
             },
             ModelId = null,
@@ -775,14 +824,6 @@ public async Task MultipleOutputItems_NonStreaming()
         Assert.Equal(36, response.Usage.TotalTokenCount);
     }
 
-    /// Converts an Extensions function to an OpenAI response chat tool.
-    private static ResponseTool ToOpenAIResponseChatTool(AIFunction aiFunction)
-    {
-        var tool = JsonSerializer.Deserialize(aiFunction.JsonSchema)!;
-        var functionParameters = BinaryData.FromBytes(JsonSerializer.SerializeToUtf8Bytes(tool));
-        return ResponseTool.CreateFunctionTool(aiFunction.Name, aiFunction.Description, functionParameters);
-    }
-
     private static IChatClient CreateResponseClient(HttpClient httpClient, string modelId) =>
         new OpenAIClient(
             new ApiKeyCredential("apikey"),