structured-output
Learn how to use produce structured output with an agent
$ npx -y skills add managedcode/dotnet-skills --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Learn how to use produce structured output with an agent
Agent definition
structured-output.mdtitle: Producing Structured Output with agents
description: Learn how to use produce structured output with an agent
zone_pivot_groups: programming-languages
author: westey-m
ms.topic: tutorial
ms.author: westey
ms.date: 09/15/2025
ms.service: agent-framework
Producing Structured Output with Agents
::: zone pivot="programming-language-csharp"
This tutorial step shows you how to produce structured output with an agent, where the agent is built on the Azure OpenAI Chat Completion service.
> [!IMPORTANT] > Not all agent types support structured output. This step uses a `ChatClientAgent`, which does support structured output.
Prerequisites
For prerequisites and installing NuGet packages, see the [Create and run a simple agent](./run-agent.md) step in this tutorial.
Create the agent with structured output
The `ChatClientAgent` is built on top of any <xref:Microsoft.Extensions.AI.IChatClient> implementation. The `ChatClientAgent` uses the support for structured output that's provided by the underlying chat client.
When creating the agent, you have the option to provide the default <xref:Microsoft.Extensions.AI.ChatOptions> instance to use for the underlying chat client. This `ChatOptions` instance allows you to pick a preferred <xref:Microsoft.Extensions.AI.ChatResponseFormat>.
Various options for `ResponseFormat` are available:
- A built-in <xref:Microsoft.Extensions.AI.ChatResponseFormat.Text?displayProperty=nameWithType> property: The response will be plain text.
- A built-in <xref:Microsoft.Extensions.AI.ChatResponseFormat.Json?displayProperty=nameWithType> property: The response will be a JSON object without any particular schema.
- A custom <xref:Microsoft.Extensions.AI.ChatResponseFormatJson> instance: The response will be a JSON object that conforms to a specific schema.
This example creates an agent that produces structured output in the form of a JSON object that conforms to a specific schema.
The easiest way to produce the schema is to define a type that represents the structure of the output you want from the agent, and then use the `AIJsonUtilities.CreateJsonSchema` method to create a schema from the type.
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.AI;
public class PersonInfo
{
public string? Name { get; set; }
public int? Age { get; set; }
public string? Occupation { get; set; }
}
JsonElement schema = AIJsonUtilities.CreateJsonSchema(typeof(PersonInfo));You can then create a <xref:Microsoft.Extensions.AI.ChatOptions> instance that uses this schema for the response format.
using Microsoft.Extensions.AI;
ChatOptions chatOptions = new()
{
ResponseFormat = ChatResponseFormat.ForJsonSchema(
schema: schema,
schemaName: "PersonInfo",
schemaDescription: "Information about a person including their name, age, and occupation")
};This `ChatOptions` instance can be used when creating the agent.
using System;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using OpenAI;
AIAgent agent = new AzureOpenAIClient(
new Uri("https://<myresource>.openai.azure.com"),
new AzureCliCredential())
.GetChatClient("gpt-4o-mini")
.AsAIAgent(new ChatClientAgentOptions()
{
Name = "HelpfulAssistant",
Instructions = "You are a helpful assistant.",
ChatOptions = chatOptions
});Now you can just run the agent with some textual information that the agent can use to fill in the structured output.
var response = await agent.RunAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");The agent response can then be deserialized into the `PersonInfo` class using the `Deserialize<T>` method on the response object.
var personInfo = response.Deserialize<PersonInfo>(JsonSerializerOptions.Web);
Console.WriteLine($"Name: {personInfo.Name}, Age: {personInfo.Age}, Occupation: {personInfo.Occupation}");When streaming, the agent response is streamed as a series of updates, and you can only deserialize the response once all the updates have been received. You must assemble all the updates into a single response before deserializing it.
var updates = agent.RunStreamingAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");
personInfo = (await updates.ToAgentResponseAsync()).Deserialize<PersonInfo>(JsonSerializerOptions.Web);::: zone-end ::: zone pivot="programming-language-python"
This tutorial step shows you how to produce structured output with an agent, where the agent is built on the Azure OpenAI Chat Completion service.
> [!IMPORTANT] > Not all agent types support structured output. The `ChatAgent` supports structured output when used with compatible chat clients.
Prerequisites
For prerequisites and installing packages, see the [Create and run a simple agent](./run-agent.md) step in this tutorial.
Create the agent with structured output
The `ChatAgent` is built on top of any chat client implementation that supports structured output. The `ChatAgent` uses the `response_format` parameter to specify the desired output schema.
When creating or running the agent, you can provide a Pydantic model that defines the structure of the expected output.
Various response formats are supported based on the underlying chat client capabilities.
This example creates an agent that produces structured output in the form of a JSON object that conforms to a Pydantic model schema.
First, define a Pydantic model that represents the structure of the output you want from the agent:
from pydantic import BaseModel
class PersonInfo(BaseModel):
"""Information about a person."""
name: str | None = None
age: int | None = None
occupation: str | None = NoneNow you can create an agent using the Azure OpenAI Chat Client:
Read more
title: Producing Structured Output with agents description: Learn how to use produce structured output with an agent zone_pivot_groups: programming-languages author: westey-m ms.topic: tutorial ms.author: westey ms.date: 09/15/2025 ms.service: agent-framework
Producing Structured Output with Agents
::: zone pivot="programming-language-csharp"
This tutorial step shows you how to produce structured output with an agent, where the agent is built on the Azure OpenAI Chat Completion service.
> [!IMPORTANT] > Not all agent types support structured output. This step uses a `ChatClientAgent`, which does support structured output.
Prerequisites
For prerequisites and installing NuGet packages, see the [Create and run a simple agent](./run-agent.md) step in this tutorial.
Create the agent with structured output
The `ChatClientAgent` is built on top of any <xref:Microsoft.Extensions.AI.IChatClient> implementation. The `ChatClientAgent` uses the support for structured output that's provided by the underlying chat client.
When creating the agent, you have the option to provide the default <xref:Microsoft.Extensions.AI.ChatOptions> instance to use for the underlying chat client. This `ChatOptions` instance allows you to pick a preferred <xref:Microsoft.Extensions.AI.ChatResponseFormat>.
Various options for `ResponseFormat` are available:
- A built-in <xref:Microsoft.Extensions.AI.ChatResponseFormat.Text?displayProperty=nameWithType> property: The response will be plain text.
- A built-in <xref:Microsoft.Extensions.AI.ChatResponseFormat.Json?displayProperty=nameWithType> property: The response will be a JSON object without any particular schema.
- A custom <xref:Microsoft.Extensions.AI.ChatResponseFormatJson> instance: The response will be a JSON object that conforms to a specific schema.
This example creates an agent that produces structured output in the form of a JSON object that conforms to a specific schema.
The easiest way to produce the schema is to define a type that represents the structure of the output you want from the agent, and then use the `AIJsonUtilities.CreateJsonSchema` method to create a schema from the type.
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.AI;
public class PersonInfo
{
public string? Name { get; set; }
public int? Age { get; set; }
public string? Occupation { get; set; }
}
JsonElement schema = AIJsonUtilities.CreateJsonSchema(typeof(PersonInfo));You can then create a <xref:Microsoft.Extensions.AI.ChatOptions> instance that uses this schema for the response format.
using Microsoft.Extensions.AI;
ChatOptions chatOptions = new()
{
ResponseFormat = ChatResponseFormat.ForJsonSchema(
schema: schema,
schemaName: "PersonInfo",
schemaDescription: "Information about a person including their name, age, and occupation")
};This `ChatOptions` instance can be used when creating the agent.
using System;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using OpenAI;
AIAgent agent = new AzureOpenAIClient(
new Uri("https://<myresource>.openai.azure.com"),
new AzureCliCredential())
.GetChatClient("gpt-4o-mini")
.AsAIAgent(new ChatClientAgentOptions()
{
Name = "HelpfulAssistant",
Instructions = "You are a helpful assistant.",
ChatOptions = chatOptions
});Now you can just run the agent with some textual information that the agent can use to fill in the structured output.
var response = await agent.RunAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");The agent response can then be deserialized into the `PersonInfo` class using the `Deserialize<T>` method on the response object.
var personInfo = response.Deserialize<PersonInfo>(JsonSerializerOptions.Web);
Console.WriteLine($"Name: {personInfo.Name}, Age: {personInfo.Age}, Occupation: {personInfo.Occupation}");When streaming, the agent response is streamed as a series of updates, and you can only deserialize the response once all the updates have been received. You must assemble all the updates into a single response before deserializing it.
var updates = agent.RunStreamingAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");
personInfo = (await updates.ToAgentResponseAsync()).Deserialize<PersonInfo>(JsonSerializerOptions.Web);::: zone-end ::: zone pivot="programming-language-python"
This tutorial step shows you how to produce structured output with an agent, where the agent is built on the Azure OpenAI Chat Completion service.
> [!IMPORTANT] > Not all agent types support structured output. The `ChatAgent` supports structured output when used with compatible chat clients.
Prerequisites
For prerequisites and installing packages, see the [Create and run a simple agent](./run-agent.md) step in this tutorial.
Create the agent with structured output
The `ChatAgent` is built on top of any chat client implementation that supports structured output. The `ChatAgent` uses the `response_format` parameter to specify the desired output schema.
When creating or running the agent, you can provide a Pydantic model that defines the structure of the expected output.
Various response formats are supported based on the underlying chat client capabilities.
This example creates an agent that produces structured output in the form of a JSON object that conforms to a Pydantic model schema.
First, define a Pydantic model that represents the structure of the output you want from the agent:
from pydantic import BaseModel
class PersonInfo(BaseModel):
"""Information about a person."""
name: str | None = None
age: int | None = None
occupation: str | None = NoneNow you can create an agent using the Azure OpenAI Chat Client:
Stop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.
Repo: managedcode/dotnet-skills
Other agents on dotnet-skills.
- AGENT
Specialist orchestration agent for .NET Aspire work. Use when the problem is clearly about AppHost design, ServiceDefaults, first-party versus CommunityToolkit/Aspire integrations, dashboard and testing, `DistributedApplicationTestingBuilder`, `WebApplicationFactory`
Open agent - agent-as-function-tool
Legacy tutorial alias retained locally; the live Learn URL now resolves into the broader Function Tools surface
Open agent - agent-as-mcp-tool
Learn how to expose an agent as a tool over the MCP protocol
Open agent - create-and-run-durable-agent
Learn how to create and run a durable AI agent with Azure Functions and the durable task extension for Microsoft Agent Framework
Open agent - enable-observability
Enable OpenTelemetry for an agent so agent interactions are automatically logged
Open agent - function-tools-approvals
Learn how to use function tools with human in the loop approvals
Open agent

