Unified AI Gateway for .NET -- access OpenAI, Anthropic, Google Gemini, and more through a single, consistent API with automatic failover, streaming, and prompt chaining.
$ dotnet add package Noundry.AIG.Client
Noundry AI Gateway (AIG) is a production-ready .NET multi-provider AI gateway. It provides a unified interface for OpenAI, Anthropic, Google Gemini, and any OpenAI-compatible endpoint. The gateway is available as a hosted BYOK (Bring Your Own Key) service at https://api.noundry.ai or can be self-hosted.
Single API for OpenAI, Anthropic, Google, Nebius, Together AI, Groq, Ollama, and LM Studio.
Automatic failover using the order parameter. First successful provider wins.
Real-time SSE-based streaming from all providers via IAsyncEnumerable.
Sequential prompts where each step's output feeds into the next input automatically.
Convert DataTable, DataSet, and collections to token-efficient TOON format (~40% token savings).
SQLite-based request logging via Noundry Tuxedo with usage statistics endpoints.
Noundry.AIG/
src/
Noundry.AIG.Core # Models, interfaces, extensions
Noundry.AIG.Providers # OpenAI, Anthropic, Google implementations
Noundry.AIG.Client # Client library (NuGet package)
Noundry.AIG.Api # ASP.NET Core Web API
Design patterns: Factory (ProviderFactory), Builder (PromptBuilder), Strategy (IAiProvider), Repository (IAnalyticsRepository).
using Noundry.AIG.Client;
using Noundry.AIG.Client.Builders;
using Noundry.AIG.Client.Configuration;
using Noundry.AIG.Core.Extensions;
using Noundry.AIG.Core.Models;
using Noundry.AIG.Providers;
// Configure the client
var options = new AigClientOptions
{
UseLocalProviders = true,
EnableRetries = true,
MaxRetries = 3,
ProviderConfigs = new Dictionary<string, ProviderConfig>
{
["openai"] = new ProviderConfig
{
ApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
},
["anthropic"] = new ProviderConfig
{
ApiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY"),
ApiVersionHeaderValue = "2023-06-01"
}
}
};
var aigClient = new AigClient(new ProviderFactory(httpClientFactory), options);
// Send a request
var prompt = new PromptBuilder()
.WithModel("openai/gpt-4")
.WithTemperature(0.7f)
.AddSystemMessage("You are a helpful assistant.")
.AddUserMessage("Explain quantum computing.")
.Build();
var response = await aigClient.SendAsync(prompt);
Console.WriteLine(response.GetTextContent());
Models use the format {provider}/{model}. The provider prefix routes the request to the correct API.
| Provider | Example Models |
|---|---|
openai | openai/gpt-4, openai/gpt-4-turbo, openai/gpt-3.5-turbo |
anthropic | anthropic/claude-sonnet-4, anthropic/claude-3-opus, anthropic/claude-3-haiku |
google | google/gemini-pro, google/gemini-pro-vision |
Custom OpenAI-compatible endpoints (Nebius, Together AI, Groq, Ollama, LM Studio) are also supported by configuring a custom ApiEndpoint on the provider config.
The fluent PromptBuilder constructs AiRequest objects with type-safe configuration.
| Method | Description |
|---|---|
| WithModel(string) | Set single model in "provider/model" format |
| WithModels(params string[]) | Set multiple models for fallback |
| AddSystemMessage(string) | Add system prompt message |
| AddUserMessage(string) | Add user message |
| AddAssistantMessage(string) | Add assistant message (multi-turn) |
| WithTemperature(float) | 0.0 (deterministic) to 2.0 (creative) |
| WithMaxTokens(int) | Maximum tokens to generate |
| WithStreaming(bool) | Enable/disable streaming |
| WithTopP(float) | Top-p nucleus sampling (0.0 to 1.0) |
| WithStopSequences(params string[]) | Set stop sequences |
| Build() | Build the AiRequest object |
var request = new PromptBuilder()
.WithModel("anthropic/claude-sonnet-4")
.AddSystemMessage("You are a creative storyteller.")
.AddUserMessage("Start a story about a robot.")
.AddAssistantMessage("In a world of circuits and steel...")
.AddUserMessage("What happens next?")
.Build();
Chain multiple AI calls where each step's output feeds into the next. Each step can use a different model.
var chain = new ChainPromptBuilder()
.WithDefaultModel("anthropic/claude-sonnet-4")
.AddStep("Generate Idea", _ =>
new PromptBuilder()
.AddUserMessage("Give me a random creative writing topic."))
.AddStep("Write Content", previousOutput =>
new PromptBuilder()
.AddUserMessage($"Write a short paragraph about: {previousOutput}"))
.AddStep("Translate", previousOutput =>
new PromptBuilder()
.WithModel("openai/gpt-4")
.AddUserMessage($"Translate to Spanish:\n{previousOutput}"));
var result = await chain.ExecuteAsync(aigClient);
if (result.Success)
{
Console.WriteLine($"Final output: {result.FinalOutput}");
// Access individual step results
foreach (var step in result.Steps)
Console.WriteLine($"{step.StepName}: {step.Output}");
}
Try multiple providers in order until one succeeds. Useful for high-availability scenarios.
var prompt = new PromptBuilder()
.WithModels(
"openai/gpt-4",
"anthropic/claude-sonnet-4",
"google/gemini-pro"
)
.AddUserMessage("Generate a story idea.")
.Build();
var response = await aigClient.SendMultiAsync(prompt);
if (response.HasSuccess)
{
Console.WriteLine($"Response from: {response.FirstSuccess.Provider}");
Console.WriteLine(response.FirstSuccess.GetTextContent());
}
var prompt = new PromptBuilder()
.WithModel("openai/gpt-4")
.WithStreaming(true)
.AddUserMessage("Write a poem about nature.")
.Build();
await foreach (var chunk in aigClient.SendStreamAsync(prompt))
{
Console.Write(chunk.GetTextContent());
}
Convert data structures to TOON (Token-Oriented Object Notation) format for efficient LLM consumption. TOON reduces token usage by ~40% compared to JSON while maintaining data fidelity.
using Noundry.AIG.Core.Extensions;
// DataTable to TOON
var table = new DataTable("sales");
table.Columns.Add("product", typeof(string));
table.Columns.Add("qty", typeof(int));
table.Rows.Add("Widget", 10);
var toonData = table.ToToon();
// Output: sales[1]{product,qty}:
// Widget,10
// Collection to TOON
var users = new List<User> { new { Id = 1, Name = "Alice" } };
var toon = users.ToToon(new ToonOptions { RootName = "users" });
The AI Gateway is deployed at https://api.noundry.ai as a BYOK service. You provide your own provider API keys via the X-API-KEY header.
# Simple request via cURL
curl -X POST "https://api.noundry.ai/v1/chat/completions" \
-H "Authorization: Bearer YOUR_GATEWAY_KEY" \
-H "X-API-KEY: Bearer YOUR_OPENAI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-4",
"messages": [{"role": "user", "content": "Hello!"}]
}'
| Endpoint | Method | Description |
|---|---|---|
| /v1/chat/completions | POST | Chat completion request |
| /v1/analytics/logs | GET | Request logs |
| /v1/analytics/usage | GET | Usage statistics |
| /health | GET | Health check (no auth) |