How to Build AI Apps in .NET Using Microsoft.Extensions.AI
If I were building a modern AI-powered .NET application today, I would not start by wiring my whole app directly to one model SDK.
That might feel fast at the beginning, but it usually becomes messy later. Controllers start knowing too much. Business services get tied to one provider. Testing becomes awkward. Swapping providers becomes painful. And once you add tools, structured output, embeddings, logging, and tracing, the code can get harder to manage than it should be.
That is why I like Microsoft.Extensions.AI.
It gives me a way to build AI features using patterns that already feel natural in .NET: abstractions, dependency injection, middleware-style pipelines, and typed models. If you have been following my broader AI-for-developers content, this fits nicely with the same practical direction I talk about in How Developers Use AI in Real Projects and Best AI APIs for Developers in 2026.
Table of Contents
- Why this library matters
- What Microsoft.Extensions.AI includes
- The mental model I recommend
- Start with the right packages
- A practical ASP.NET Core setup
- Why I strongly prefer structured output
- Function calling is where apps become more useful
- Embeddings matter when search matters
- The pipeline model is one of the best parts
- My production recommendations
- Final thoughts
- FAQ
Why this library matters
The biggest benefit here is not “AI magic.” It is architecture quality.
With Microsoft.Extensions.AI, I can build my app around an abstraction like IChatClient instead of tightly coupling my business logic to one provider SDK. That means my controllers and services stay cleaner, my code is easier to test, and swapping providers later becomes much less painful.
That also means I can keep provider-specific setup in startup or dependency injection, which is exactly where it belongs in a well-structured .NET application.
What Microsoft.Extensions.AI includes
At a high level, Microsoft.Extensions.AI revolves around a few important building blocks:
- IChatClient for chat and generation scenarios
- IEmbeddingGenerator<TInput,TEmbedding> for embeddings
- higher-level support for function invocation, telemetry, and caching
- middleware-style composition through a chat client pipeline
This is one of the reasons the library feels familiar to .NET developers. It does not force us into a strange new architecture. It lets us build AI apps using patterns we already trust.
The mental model I recommend
This is the structure I would use for a real application:
ASP.NET Core API / Web App
↓
Application Service
↓
IChatClient
↓
Microsoft.Extensions.AI pipeline
(function invocation, caching, telemetry, tracing)
↓
Azure OpenAI / OpenAI-compatible / local model
That architecture keeps the app clean. My controller does not need to know how the provider authenticates. My service does not need to know the internals of function invocation middleware. And my domain logic stays easier to test and maintain.
Start with the right packages
For a typical Azure OpenAI setup, I would start with packages like these:
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Identity
dotnet add package Microsoft.Extensions.AI
dotnet add package Microsoft.Extensions.AI.OpenAI
This gives you the Azure OpenAI client, authentication support, and the Microsoft.Extensions.AI abstractions and integrations you need to build against IChatClient.
A practical ASP.NET Core setup
Here is the kind of setup I like because it keeps the provider details in dependency injection and lets the rest of the app depend only on IChatClient.
Program.cs
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Extensions.AI;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddChatClient(services =>
{
var endpoint = builder.Configuration["AzureOpenAI:Endpoint"]
?? throw new InvalidOperationException("AzureOpenAI:Endpoint is missing.");
var deployment = builder.Configuration["AzureOpenAI:Deployment"]
?? throw new InvalidOperationException("AzureOpenAI:Deployment is missing.");
IChatClient innerClient = new AzureOpenAIClient(
new Uri(endpoint),
new DefaultAzureCredential())
.GetChatClient(deployment)
.AsIChatClient();
return innerClient
.AsBuilder()
.UseFunctionInvocation()
.Build(services);
});
var app = builder.Build();
app.MapPost("/api/travel/plan", async (TravelRequest request, IChatClient chatClient) =>
{
var prompt = $"""
Create a {request.Days}-day travel plan for {request.City}.
Return:
- city
- days
- itinerary
Each itinerary item should include:
- dayNumber
- morning
- afternoon
- evening
- budgetNote
Keep the plan practical and realistic.
""";
var response = await chatClient.GetResponseAsync<TravelPlan>(
prompt,
new ChatOptions
{
Temperature = 0.2f
});
return Results.Ok(response.Result);
});
app.Run();
public record TravelRequest(string City, int Days);
public record TravelPlan(
string City,
int Days,
List<DayPlan> Itinerary);
public record DayPlan(
int DayNumber,
string Morning,
string Afternoon,
string Evening,
string BudgetNote);
This pattern is one of the biggest reasons I recommend Microsoft.Extensions.AI for .NET developers. The application code depends on a clean abstraction, not on provider-specific wiring everywhere.
Why I strongly prefer structured output
In real applications, I rarely want “just text.”
Most of the time, I want something my application can use safely:
- a classification
- an extracted record
- a recommendation object
- a summarized support ticket
- a DTO that can move to the next workflow step
That is why structured output matters so much. Instead of asking the model for plain text and then parsing it manually, I can ask it to return a result that matches a .NET type. That reduces fragile parsing and makes the code much cleaner.
If you are new to retrieval and typed AI workflows, pair this post with What Is RAG in AI? A Simple Guide for Developers so the bigger picture is easier to understand.
Function calling is where apps become more useful
Function calling is one of the most practical parts of this stack.
It allows the model to use approved .NET functions so the app can do more than just generate text. That is where AI apps start feeling like real business applications.
A simple example looks like this:
string GetCurrentWeather(string location, string unit)
{
return $"{location}: 72 degrees {unit}, light rain";
}
var chatOptions = new ChatOptions
{
Tools =
[
AIFunctionFactory.Create(
GetCurrentWeather,
"get_current_weather",
"Gets the current weather for a location")
]
};
var response = await chatClient.GetResponseAsync(
"Should I carry an umbrella in Seattle today? Use the weather tool if needed.",
chatOptions);
Now the model can use safe, approved functions such as:
- checking order status
- reading account details
- looking up inventory
- returning shipping information
- calling internal APIs in a controlled way
That is a much more valuable enterprise pattern than only returning text responses.
Embeddings matter when search matters
Not every AI app needs embeddings immediately. But when you want semantic search, retrieval, or RAG, embeddings become very important.
A simplified example could look like this:
using Microsoft.Extensions.AI;
ReadOnlyMemory<float> vector =
await generator.GenerateVectorAsync("How do I reset my password?");
I think about it this way:
- use IChatClient for generation and conversation
- use IEmbeddingGenerator for retrieval and semantic similarity
If your next step is building search-backed answers, read What Is RAG in AI? A Simple Guide for Developers next.
The pipeline model is one of the best parts
This is another reason I like Microsoft.Extensions.AI.
The library lets us layer behaviors around the base chat client in a pipeline. That means I can add capabilities like function invocation, caching, tracing, and telemetry without stuffing those concerns directly into controller or business logic.
Instead of mixing everything together, I can compose the capabilities around the client. That feels very natural to experienced .NET developers, and that familiarity is a big advantage.
My production recommendations
If I were building a real enterprise feature with this stack, I would keep the plan simple:
- Start with IChatClient
- Keep provider setup in dependency injection
- Prefer structured output whenever the app expects data, not prose
- Add function calling only for safe and intentional operations
- Add embeddings when retrieval is actually needed
- Add observability and evaluation before trying to scale
That gives you a much stronger foundation than jumping too early into a large AI architecture.
Final thoughts
What I like most about Microsoft.Extensions.AI is that it lets me build AI applications the same way I already like building .NET applications.
- clean abstractions
- dependency injection
- typed models
- reusable services
- composable pipelines
And that matters a lot.
Because in real projects, AI is not just a prompt. It is part of an application architecture.
So if you are a .NET developer looking for a clean way to add AI without turning your codebase into a prototype that never matures, this is one of the best places to start.
And if you are mapping out your broader AI stack, also read Best AI APIs for Developers in 2026 and How Developers Use AI in Real Projects to connect the tooling choices back to real implementation patterns.
FAQ
What is Microsoft.Extensions.AI in .NET?
It is Microsoft’s abstraction layer for building AI-enabled .NET applications using common interfaces such as IChatClient and IEmbeddingGenerator<TInput,TEmbedding>, with higher-level support for pipeline-style capabilities like telemetry, caching, and function invocation.
What is IChatClient used for?
IChatClient is the main abstraction for interacting with AI services that provide chat capabilities. It is the interface you build against when you want your app to send prompts and receive model responses in a clean, provider-friendly way.
Can I return typed results instead of plain text?
Yes. One of the best parts of this approach is structured output. You can request responses that conform to a .NET type instead of manually parsing freeform text.
Does Microsoft.Extensions.AI support function calling?
Yes. You can expose approved .NET methods as tools and let the model use them in a controlled way through the chat pipeline.
When should I use embeddings?
Use embeddings when you need semantic search, retrieval, similarity matching, or RAG-style workflows.
Want more practical AI and .NET guides like this? Follow AINexArch for hands-on developer tutorials, architecture patterns, and real-world AI implementation ideas.
