If you’ve read other guides on this site, one type keeps appearing: IChatClient. It comes from Microsoft.Extensions.AI, and it’s arguably the most important building block in the .NET AI stack — the layer that stops you from coupling your app to a single AI vendor. This article explains what it is and why it matters.
The problem it solves
Without an abstraction, calling OpenAI, Azure OpenAI, Claude, Gemini, or a local model each means a different client, different method names, and vendor-specific types threaded through your code. Switching providers — or A/B testing two — becomes a rewrite. That’s the problem Microsoft.Extensions.AI removes.
The two core interfaces
Microsoft.Extensions.AI defines provider-agnostic interfaces, the same way Microsoft.Extensions.Logging gave .NET one logging API over many providers:
IChatClient— send messages, get responses (streaming or not), with tools and structured output. Every chat provider implements it.IEmbeddingGenerator— turn text into embedding vectors, provider-agnostically.
Your code depends on the interface; a provider package supplies the implementation.
What using it looks like
// Your code only knows about IChatClient — not which vendor is behind it.
IChatClient chat = /* injected: OpenAI, Azure, Claude, Gemini, or Ollama */;
var response = await chat.GetResponseAsync("Explain CQRS in two sentences.");
Console.WriteLine(response);
// Streaming works the same way, regardless of provider:
await foreach (var update in chat.GetStreamingResponseAsync("Now give an example."))
Console.Write(update);
Swap the provider in one place (usually your DI registration) and everything downstream is unchanged.
Why it’s a big deal
- No vendor lock-in. Switch models with a config change, not a refactor.
- Easy benchmarking. Run the same code against several providers and compare on your eval set (choosing a model).
- Testability. Substitute a fake
IChatClientin unit tests — no real API calls, fast and free. - Middleware. Because it’s an interface, you can wrap it: add caching, logging, telemetry, or rate-limiting as decorators around any provider.
- It’s the foundation. The Microsoft Agent Framework and most .NET AI tooling build on these interfaces — learn them once, use them everywhere.
Middleware in practice
The decorator pattern is where it shines. Want to cache responses, add OpenTelemetry observability, or enforce a rate limit? You wrap the IChatClient in a pipeline — the same idea as ASP.NET Core middleware — so those concerns are provider-independent and composable.
Note: method names (
GetResponseAsync,GetStreamingResponseAsync) are still stabilizing; verify against the current .NET AI docs. The design — provider-agnostic interfaces with pluggable implementations and middleware — is the durable core of .NET’s AI story.
Takeaway
Microsoft.Extensions.AI is to AI providers what Microsoft.Extensions.Logging is to loggers: one interface, many implementations. Depend on IChatClient and IEmbeddingGenerator, and you get no vendor lock-in, trivial provider swapping and benchmarking, easy testing, and composable middleware for caching, telemetry, and rate-limiting. It’s the layer that makes every other .NET AI decision reversible — which is exactly why it shows up in nearly every guide here.
Have a correction or a topic you want covered? Email mani.bc72@gmail.com.