I've been writing C# professionally for over twenty-five years. In that time, I've watched the ecosystem go through every hype cycle imaginable — WCF, Silverlight, Blazor, you name it. Most of them came with a familiar pattern: exciting promise, vendor-specific lock-in, and a rewrite two years later when the wind changed direction.
AI is the first technology wave where I've seen that pattern play out in months instead of years. Last quarter's best model is this quarter's fallback. The provider you built your entire pipeline around just changed their pricing, deprecated an endpoint, or got leapfrogged by a competitor nobody was watching.
If you're a .NET developer building anything with LLMs right now, you have a choice: wire yourself directly to one provider's SDK and pray they stay on top, or build an abstraction layer that lets you move between providers like changing a config value. I built that abstraction. It's called the Noundry AI Gateway, and it's live on NuGet today.
The Problem Is Obvious If You've Lived It
Here's what building with AI providers actually looks like in .NET right now. You install OpenAI's SDK. You write your prompt logic. You get it working. Then the client asks about Anthropic because Claude is better at their use case. Now you're installing a second SDK with a completely different API surface, different auth patterns, different response shapes, different streaming implementations.
Two providers in and you've already got an abstraction problem. Three providers in and you've got a maintenance nightmare. Every SDK has its own way of doing things, its own quirks, its own breaking changes on its own release schedule.
I kept building the same wrapper code across projects. Same patterns, same interfaces, same provider-switching logic. After the third time, I stopped and built it properly.
What the Gateway Actually Does
The Noundry AI Gateway — packaged as Noundry.AIG.Client on NuGet — gives you a single, fluent API that talks to every major AI provider. OpenAI, Anthropic, Google Gemini, and any OpenAI-compatible endpoint like Groq, Ollama, Together AI, or LM Studio. One interface. One set of patterns. Bring your own keys.
Install it:
dotnet add package Noundry.AIG.Client
Configure your providers:
var options = new AigClientOptions
{
Providers =
{
["openai"] = new ProviderConfig
{
ApiKey = "your-openai-key",
BaseUrl = "https://api.openai.com/v1"
},
["anthropic"] = new ProviderConfig
{
ApiKey = "your-anthropic-key",
BaseUrl = "https://api.anthropic.com/v1"
},
["google"] = new ProviderConfig
{
ApiKey = "your-google-key",
BaseUrl = "https://generativelanguage.googleapis.com/v1beta"
}
}
};
var factory = new ProviderFactory(options);
var client = new AigClient(factory);
Send a prompt. To any provider:
var request = new PromptBuilder()
.WithModel("anthropic/claude-sonnet-4")
.WithTemperature(0.7f)
.WithMaxTokens(1000)
.AddSystemMessage("You are a helpful assistant.")
.AddUserMessage("Explain dependency injection in C#.")
.Build();
var response = await client.SendAsync(request);
Want to switch to GPT-4? Change "anthropic/claude-sonnet-4" to "openai/gpt-4". That's it. Same builder, same response shape, same everything. Your business logic doesn't know or care which model is underneath.
Chain Prompting: Where It Gets Interesting
Single prompts are table stakes. The real power — and the reason we built chainprompting.com as a dedicated documentation site — is in chaining prompts together.
Chain prompting is exactly what it sounds like: you define a sequence of AI calls where each step's output feeds into the next step's input. Think content pipelines, translation workflows, data processing, multi-step analysis. Each step can use a different model — use Claude for creative generation, GPT-4 for structured extraction, Gemini for summarization. The gateway handles the plumbing.
var chain = new ChainPromptBuilder()
.AddStep("anthropic/claude-sonnet-4", previousOutput =>
new PromptBuilder()
.AddSystemMessage("You are a research assistant.")
.AddUserMessage("Research the topic: AI in healthcare")
.Build())
.AddStep("openai/gpt-4", previousOutput =>
new PromptBuilder()
.AddSystemMessage("You are a technical writer.")
.AddUserMessage($"Write a blog post based on: {previousOutput}")
.Build())
.AddStep("google/gemini-pro", previousOutput =>
new PromptBuilder()
.AddSystemMessage("You are an editor.")
.AddUserMessage($"Edit for clarity and conciseness: {previousOutput}")
.Build())
.Build();
var results = await client.ExecuteChainAsync(chain);
Three models. Three providers. One pipeline. Each step gets the previous step's output automatically. You're composing AI capabilities the same way you'd compose middleware in an ASP.NET pipeline — and if you're a .NET developer, that mental model should feel instantly familiar.
Automatic Failover: Because Providers Go Down
Anyone who's run AI workloads in production knows the drill. Rate limits. Outages. Capacity issues during peak hours. The gateway handles this with automatic failover — you define a priority list of models, and if the first one fails, it falls through to the next.
var request = new PromptBuilder()
.WithModels(
"openai/gpt-4",
"anthropic/claude-sonnet-4",
"google/gemini-pro"
)
.AddUserMessage("Summarize this document.")
.Build();
GPT-4 is down? The request automatically routes to Claude. Claude is rate-limited? Gemini picks it up. Your users never see the failure. This isn't aspirational architecture — it's a production pattern I needed on real projects, so I built it into the core.
Streaming That Doesn't Fight You
Every provider implements streaming differently. OpenAI uses SSE. Anthropic uses SSE with a different event format. Google has their own thing. The gateway normalizes all of it into a single IAsyncEnumerable you can consume with await foreach.
var request = new PromptBuilder()
.WithModel("anthropic/claude-sonnet-4")
.WithStreaming(true)
.AddUserMessage("Write a haiku about C#.")
.Build();
await foreach (var chunk in client.SendStreamAsync(request))
{
Console.Write(chunk.Content);
}
Same pattern whether you're streaming from OpenAI, Anthropic, or Google. Native C# async enumeration. No adapter code. No provider-specific event parsing. It just works the way .NET developers expect it to.
Multi-Provider Parallel Requests
Sometimes you don't want failover — you want to ask every provider the same question at the same time and compare results. The gateway's SendMultiAsync does exactly that.
var results = await client.SendMultiAsync(request,
"openai/gpt-4",
"anthropic/claude-sonnet-4",
"google/gemini-pro"
);
foreach (var result in results)
{
Console.WriteLine($"{result.Model}: {result.Content}");
}
This is incredibly useful for evaluation pipelines, A/B testing model quality, or building consensus-based systems where you want multiple models to weigh in. Fire them all in parallel, get all the responses back, pick the best one or aggregate them. The gateway handles the concurrency.
TOON: 40% Token Savings on Tabular Data
Here's a feature I'm genuinely excited about that has nothing to do with providers. The gateway ships with built-in support for TOON — Token-Oriented Object Notation. It's a serialization format designed specifically for sending structured data to LLMs.
If you're sending tabular data to a model — query results, CSV imports, collections of objects — JSON is wasteful. All those curly braces, repeated key names, quotation marks. You're burning tokens on syntax, not data. TOON strips that overhead out.
JSON (~85 tokens)
[{"product":"Widget","qty":10,"price":9.99},{"product":"Gadget","qty":5,"price":14.50}]
TOON (~30 tokens)
sales[2]{product,qty,price}:
Widget,10,9.99
Gadget,5,14.5
Converting is a one-liner:
var toonData = myDataTable.ToToon();
var toonCollection = myList.ToToon();
Benchmarked at 76.4% accuracy on data retrieval questions versus JSON's 75.0% — comparable fidelity at roughly 40% fewer tokens. If you're processing volume, that's real money. The TOON spec is open and has implementations in TypeScript, Python, Go, Rust, and .NET.
Why I Built This Instead of Using Semantic Kernel
I know what you're thinking. Microsoft has Semantic Kernel. LangChain has a .NET port. Why build another one?
Because I've used both, and they're solving a different problem. Semantic Kernel is an orchestration framework — it's about agents, planners, plugins, memory systems. It's a full kitchen when sometimes you just need a sharp knife.
The Noundry AI Gateway is deliberately narrow. It does one thing: give you a clean, fluent interface to talk to any AI provider from C#. No agent framework. No plugin architecture. No 47 abstractions between your code and the HTTP call. A PromptBuilder, a client, and a response. That's the entire surface area.
If you've read my Skip the Screen piece, you know I believe the best developer tools are the ones that disappear into the workflow. This gateway disappears into your code. You register it in DI, inject it where you need it, and it gets out of your way.
Production-Ready, Not Demo-Ready
This isn't a weekend experiment. The gateway is built for production .NET workloads:
- Thread-safe — HttpClientFactory with connection pooling, SemaphoreSlim concurrency control
- Resilient — Configurable retries with exponential backoff
- Observable — Built-in analytics for token usage, latency, and cost tracking
- Targets .NET 9.0 and .NET 10.0 — no legacy framework baggage
- BYOK — Bring your own API keys. Zero markup on provider costs. The gateway never touches your data
There's also a hosted API at api.noundry.ai if you want an OpenAI-compatible REST endpoint without the NuGet package — useful for non-.NET services in your architecture that still need unified provider access.
The Vercel AI SDK for .NET
If you've used the Vercel AI SDK in the JavaScript ecosystem, this is the same idea for C#. One library. Every provider. Streaming, tool use, chain prompting, failover. The JavaScript world has had this for a while. The .NET world hasn't. Now it does.
The full docs live at chainprompting.com, and the gateway reference is at noundry.com/ai-gateway. Everything is documented with real code examples — not "coming soon" placeholders.
I built this because I needed it. I shipped it because every .NET developer building with AI needs it. The provider landscape is moving too fast to be married to one SDK. Bring your own keys, point the gateway at any combination of providers, and write code that survives the next model shakeup without a rewrite.
dotnet add package Noundry.AIG.Client
One line to install. One interface to learn. Every AI provider your project will ever need.
Building AI features into a .NET application and tired of juggling provider SDKs? I built the gateway to solve exactly that problem. Check out the docs at chainprompting.com, or reach out if you want to talk AI architecture for your .NET stack.