Skip to content

Conversation

@SergeyMenshykh
Copy link
Member

@SergeyMenshykh SergeyMenshykh commented Feb 9, 2026

Motivation and Context

Currently, Structured Output (SO) in AF is supported by ChatClientAgent only and can be "enabled" either via the ResponseFormat property or the RunAsync<T> instance method.

However, if ChatClientAgent is decorated by, let's say, an Open Telemetry decorator, the agent users lose access to the RunAsync<T> methods because they are instance methods of ChatClientAgent rather than members of the AIAgent class.

Additionally, AF does not provide SO support for the other agents, i.e., A2A, which do not support SO natively.

Furthermore, there's no way to provide SO configuration via the ResponseFormat property to any agent except ChatClientAgent at agent invocation because AgentRunOptions don't have the property and it only exists on ChatClientAgentRunOptions.

Description

  • Add the ResponseFormat property to the AgentRunOptions to communicate the agent's SO configuration.
  • Add RunAsync<T> non-virtual methods to the AIAgent base abstract class.
  • Add the StructuredOutputAgent decorator to add SO support to agents that don't natively support SO.
  • Add the UseStructuredOutput extension method for the AIAgentBuilder, allowing easy registration of the decorator during the agent configuration step.
  • Restructure the SO sample to showcase different ways of working with SO in AF.

Closes: #2874, #1057, #1642, #2683, #3231

SergeyMenshykh and others added 7 commits January 30, 2026 14:30
* delete deserialize method of agent response

* order usings

* Update dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs

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

* Update dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs

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

* Update dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs

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

* Update dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs

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

* Update dotnet/samples/M365Agent/Agents/WeatherForecastAgent.cs

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

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* add support for so

* restore lost xml comment part

* fix using ordering

* Update dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgentStructuredOutput.cs

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

* Update dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgentStructuredOutput.cs

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

* Update dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgent_SO_WithFormatResponseTests.cs

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

* addressw pr review comments

* address pr review feedback

* address pr review comments

* fix compilation issues after the latest merge with main

* remove unnecessry options

* remove RunAsync<object> methods

* address code review feedback

* address pr review feedback

* make copy constructor protected

* address pr review feedback

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* add decorator that adds structured output support to agents that don't natively support it.

* Update dotnet/src/Microsoft.Agents.AI/StructuredOutput/StructuredOutputAgentResponse.cs

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

* Update dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs

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

* address pr review feedback

---------

Co-authored-by: westey <164392973+westey-m@users.noreply.github.com>
* wrap primitives and arrays

* fix file encoding

* address review comments
@SergeyMenshykh SergeyMenshykh self-assigned this Feb 9, 2026
Copilot AI review requested due to automatic review settings February 9, 2026 13:54
@SergeyMenshykh SergeyMenshykh moved this to In Review in Agent Framework Feb 9, 2026
@markwallace-microsoft markwallace-microsoft added documentation Improvements or additions to documentation .NET labels Feb 9, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR broadens and standardizes Structured Output (SO) support across .NET Agent Framework agents by moving SO configuration onto the common AgentRunOptions surface and adding typed RunAsync<T> APIs to AIAgent, while also introducing a decorator-based fallback (StructuredOutputAgent) for agents that can’t produce SO natively.

Changes:

  • Add AgentRunOptions.ResponseFormat + cloning support, and implement AIAgent.RunAsync<T> that drives SO via ResponseFormat (including wrapping for primitives/arrays).
  • Introduce StructuredOutputAgent (+ options/response) and UseStructuredOutput builder extension to enable SO for non-native agents.
  • Update unit/integration tests, conformance tests, samples, and add an ADR documenting the design and tradeoffs.

Reviewed changes

Copilot reviewed 48 out of 48 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
dotnet/src/Microsoft.Agents.AI.Abstractions/AgentRunOptions.cs Adds ResponseFormat and Clone() to make SO configuration available on the base options type.
dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgent.cs Makes AIAgent partial to host new typed structured output APIs.
dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgentStructuredOutput.cs Implements AIAgent.RunAsync<T> via AgentRunOptions.ResponseFormat, including schema wrapping for non-object roots.
dotnet/src/Microsoft.Agents.AI.Abstractions/AgentResponse.cs Removes Deserialize/TryDeserialize APIs and adds a copy constructor used by typed responses.
dotnet/src/Microsoft.Agents.AI.Abstractions/AgentResponse{T}.cs Reworks typed responses to deserialize from Text, including unwrap logic for wrapped schemas.
dotnet/src/Microsoft.Agents.AI/StructuredOutput/StructuredOutputAgent.cs Adds decorator that converts inner agent text into structured JSON using an IChatClient.
dotnet/src/Microsoft.Agents.AI/StructuredOutput/StructuredOutputAgentOptions.cs Adds configuration surface for the SO decorator (system message + chat options).
dotnet/src/Microsoft.Agents.AI/StructuredOutput/StructuredOutputAgentResponse.cs Adds response type that preserves the original (inner) response alongside SO output.
dotnet/src/Microsoft.Agents.AI/StructuredOutput/AIAgentBuilderExtensions.cs Adds UseStructuredOutput to register the SO decorator via AIAgentBuilder.
dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgent.cs Plumbs AgentRunOptions.ResponseFormat into ChatOptions.ResponseFormat during invocation.
dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgentCustomOptions.cs Updates typed RunAsync<T> overloads to return AgentResponse<T> and removes legacy schema flag parameter.
dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgentRunOptions.cs Adds Clone() override to preserve derived options during typed runs.
dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgentRunResponse{T}.cs Removes ChatClientAgentResponse<T> wrapper in favor of AgentResponse<T>.
dotnet/src/Microsoft.Agents.AI.DurableTask/DurableAgentRunOptions.cs Moves ResponseFormat usage to base options + adds Clone() override for derived durable options.
dotnet/src/Microsoft.Agents.AI.DurableTask/DurableAIAgent.cs Removes durable-specific RunAsync<T> in favor of base AIAgent typed APIs and base ResponseFormat.
dotnet/src/Microsoft.Agents.AI.DurableTask/DurableAIAgentProxy.cs Aligns response format selection with new base AgentRunOptions.ResponseFormat.
dotnet/src/Microsoft.Agents.AI.DurableTask/CHANGELOG.md Adds changelog entry noting the ResponseFormat migration for SO.
dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentRunOptionsTests.cs Adds clone tests including ResponseFormat.
dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseTests.cs Updates tests away from removed Deserialize/TryDeserialize helpers.
dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIAgentStructuredOutputTests.cs Adds coverage for wrapping/unwrapping behavior and typed result extraction.
dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/TestJsonSerializerContext.cs Registers Species in the test source-generated serializer context.
dotnet/tests/Microsoft.Agents.AI.DurableTask.UnitTests/DurableAgentRunOptionsTests.cs Adds clone tests ensuring ResponseFormat is carried via base options.
dotnet/tests/Microsoft.Agents.AI.UnitTests/StructuredOutput/StructuredOutputAgentTests.cs Adds unit tests validating decorator behavior, option precedence, and error handling.
dotnet/tests/Microsoft.Agents.AI.UnitTests/StructuredOutput/StructuredOutputAgentResponseTests.cs Adds tests for preservation of the original response.
dotnet/tests/Microsoft.Agents.AI.UnitTests/StructuredOutput/AIAgentBuilderExtensionsTests.cs Adds tests for UseStructuredOutput DI resolution and configuration.
dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgent_StructuredOutput_WithRunAsyncTests.cs Adds focused tests for generic RunAsync<T> behavior on ChatClientAgent.
dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgent_StructuredOutput_WithFormatResponseTests.cs Adds tests for ResponseFormat precedence across initialization/invocation/run options.
dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgentRunOptionsTests.cs Adds clone tests for derived run options including deep-clone of nested ChatOptions.
dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgentTests.cs Removes older structured output test coverage now split into dedicated files.
dotnet/tests/Microsoft.Agents.AI.UnitTests/Models/Animal.cs Adds model type used in structured output tests.
dotnet/tests/Microsoft.Agents.AI.UnitTests/Models/Species.cs Adds enum model used in structured output tests.
dotnet/tests/AgentConformance.IntegrationTests/StructuredOutputRunTests.cs Adds cross-agent conformance suite for ResponseFormat and typed RunAsync<T>.
dotnet/tests/AgentConformance.IntegrationTests/Support/Constants.cs Makes constants public for cross-test-project reuse.
dotnet/tests/AgentConformance.IntegrationTests/Support/SessionCleanup.cs Makes cleanup helper public for cross-test-project reuse.
dotnet/tests/OpenAIAssistant.IntegrationTests/OpenAIAssistantStructuredOutputRunTests.cs Adds structured output conformance instantiation for OpenAI Assistant.
dotnet/tests/OpenAIChatCompletion.IntegrationTests/OpenAIChatCompletionStructuredOutputRunTests.cs Adds structured output conformance instantiation for OpenAI ChatCompletion.
dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponseStructuredOutputRunTests.cs Adds structured output conformance instantiation for OpenAI Responses.
dotnet/tests/AzureAIAgentsPersistent.IntegrationTests/AzureAIAgentsPersistentStructuredOutputRunTests.cs Adds structured output conformance instantiation for Azure AI Agents persistent variant.
dotnet/tests/AzureAI.IntegrationTests/AIProjectClientFixture.cs Enables creating a ChatClientAgent with options for initialization-time SO configuration.
dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentStructuredOutputRunTests.cs Adds integration coverage for initialization-time ResponseFormat on AIProjectClient agents.
dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/Program.cs Restructures sample to demonstrate multiple SO approaches including middleware/decorator.
dotnet/samples/GettingStarted/Agents/Agent_Step05_StructuredOutput/README.md Adds documentation for the updated structured output sample and scenarios.
dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs Updates sample to deserialize via JsonSerializer after removal of AgentResponse helpers.
dotnet/samples/GettingStarted/Workflows/_Foundational/08_WriterCriticWorkflow/Program.cs Updates workflow sample to use direct JsonSerializer.Deserialize with explicit error handling.
dotnet/samples/M365Agent/Agents/WeatherForecastAgent.cs Replaces removed AgentResponse deserialization helpers with local JSON helper.
dotnet/samples/GettingStarted/AGUI/Step05_StateManagement/Server/SharedStateAgent.cs Replaces removed AgentResponse deserialization helpers with local JSON helper.
dotnet/samples/AGUIClientServer/AGUIDojoServer/SharedState/SharedStateAgent.cs Replaces removed AgentResponse deserialization helpers with local JSON helper.
docs/decisions/0015-structured-output.md Adds ADR capturing motivation, options considered, and selected approach for SO improvements.
Comments suppressed due to low confidence (1)

dotnet/src/Microsoft.Agents.AI.Abstractions/AIAgentStructuredOutput.cs:158

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation .NET

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

.NET: Structured Output calling does not work with lists/array if ResponseFormat is used, but works if .RunAsync<> is used

2 participants