You wrote your first LLM call with the OpenAI SDK. Then the customer asked for Azure. Then someone wanted to try Claude, compliance demanded a local model, and AWS showed up with the group’s Bedrock deal. Five SDKs, five message types, five ways to stream — and your business logic knitted into every one of them. In .NET we’ve seen this movie before: we stopped coding against a concrete logger the day ILogger arrived. For AI, the interface playing that role exists: Microsoft.Extensions.AI — MEAI for short.

This five-episode series sets up MEAI from scratch: today the abstractions and the pipeline, then tools and typed outputs, then the multi-cloud splits (Azure AI Foundry, Anthropic, AWS Bedrock), local models (Ollama, Foundry Local), and to close, a production RAG with real-world pitfalls. You’ll see: it’s not rocket science.

Two packages, two interfaces

MEAI consists of two NuGet packages with crisp roles:

Package Contents Who references it
Microsoft.Extensions.AI.Abstractions the exchange types: IChatClient, IEmbeddingGenerator, ChatMessage libraries that implement a provider
Microsoft.Extensions.AI the middleware: tool invocation, caching, telemetry, DI your application

The two interfaces to remember:

  • IChatClient — the conversation: text (or images) in, a response out;
  • IEmbeddingGenerator<string, Embedding<float>> — text becomes vectors, the building block of every RAG (we already used it in build your RAG in .NET).

First contact — no credit card required

The shortest path to trying it runs through a local model via OllamaOllamaSharp implements IChatClient natively:

using Microsoft.Extensions.AI;
using OllamaSharp;

IChatClient client = new OllamaApiClient(
    new Uri("http://localhost:11434/"), "phi3:mini");

Console.WriteLine(await client.GetResponseAsync("Explain embeddings in one sentence."));

And the day that prototype has to run on Azure OpenAI:

using Azure.AI.OpenAI;
using Azure.Identity;

IChatClient client = new AzureOpenAIClient(
        new Uri(endpoint), new DefaultAzureCredential())
    .GetChatClient("gpt-5-mini")
    .AsIChatClient();          // ← the bridge into MEAI

Nothing else changes. Your business logic talks to IChatClient; the provider is an injection detail. It’s the contract this blog already applied in the .NET RAG, and it’s what makes the rest of this series possible — every third-party SDK’s AsIChatClient() is a plug that fits the same socket.

The conversation, multi-turn edition

GetResponseAsync also accepts a full history — you own the state, not the SDK:

var messages = new List<ChatMessage>
{
    new(ChatRole.System, "You are a technical docs assistant. Keep answers short."),
    new(ChatRole.User, "What is Microsoft.Extensions.AI?"),
};

var response = await client.GetResponseAsync(messages);
messages.AddRange(response.Messages);       // archive the reply
messages.Add(new(ChatRole.User, "Why not use the OpenAI SDK directly?"));
var followUp = await client.GetResponseAsync(messages);

For streaming, GetStreamingResponseAsync returns an IAsyncEnumerable of updates — one await foreach and your UI renders tokens as they arrive, whatever provider sits behind.

The real superpower: the pipeline

MEAI’s philosophy is ASP.NET Core middleware: every IChatClient can decorate another. The builder assembles the chain:

builder.Services.AddChatClient(services =>
    innerClient                       // Ollama, Azure, Anthropic… doesn't matter
        .AsBuilder()
        .UseDistributedCache()        // same questions → served from cache
        .UseFunctionInvocation()      // automatic tool calling (episode 2)
        .UseOpenTelemetry()           // standard GenAI traces
        .Build(services));

Caching, telemetry, tool invocation, rate limiting: cross-cutting concerns, written once, applied to any model. It’s exactly the click we had with HttpClientFactory and its handlers — and if you followed our OpenTelemetry article, you already know what UseOpenTelemetry() emits: the GenAI semantic conventions, dashboard-ready.

Why it became THE standard

The decisive argument isn’t comfort, it’s the ecosystem: Semantic Kernel and the Microsoft Agent Framework are built on it, the MCP C# SDK plugs straight into it, the Microsoft.Extensions.AI.Evaluations library depends on it, and providers now ship the adapter themselves — OpenAI, Azure, Anthropic (official SDK), AWS, OllamaSharp. Code against IChatClient and you get all of that for free.

The map of the series

# Date Episode
1 today One interface to rule them all — you are here
2 September 10 tools, typed outputs and middleware
3 September 11 same code, three clouds: Foundry, Anthropic, Bedrock
4 September 12 going local: Ollama and Foundry Local
5 September 13 production RAG: six pitfalls and their fixes

A word of honesty

  • An abstraction always leaks a little: a provider’s exotic options go through raw properties, and a model that can’t do tool calling won’t learn it by magic because it wears the interface. MEAI unifies the plumbing, not the capabilities.
  • The ecosystem moves fast: this series’ examples are verified against MEAI 10.x (summer 2026), but pin your versions and read the release notes — some provider adapters still carry a preview label.

In short

  • Microsoft.Extensions.AI = the ILogger of AI: two interfaces (IChatClient, IEmbeddingGenerator), one abstractions package, one middleware package.
  • The provider becomes an injection detail: AsIChatClient() and your business logic never moves again.
  • The middleware pipeline (cache, telemetry, tools…) is written once and applies to every model.
  • Semantic Kernel, Agent Framework, MCP, evals: the whole .NET ecosystem converges on these interfaces.

Tomorrow we give the model arms: AIFunctionFactory, automatic tool invocation, typed responses with GetResponseAsync<T> — and the middleware that makes it all observable. And that, honestly… is not rocket science.