BYOK.Core
1.0.0
dotnet add package BYOK.Core --version 1.0.0
NuGet\Install-Package BYOK.Core -Version 1.0.0
<PackageReference Include="BYOK.Core" Version="1.0.0" />
<PackageVersion Include="BYOK.Core" Version="1.0.0" />
<PackageReference Include="BYOK.Core" />
paket add BYOK.Core --version 1.0.0
#r "nuget: BYOK.Core, 1.0.0"
#:package BYOK.Core@1.0.0
#addin nuget:?package=BYOK.Core&version=1.0.0
#tool nuget:?package=BYOK.Core&version=1.0.0
BYOK RX — Bring Your Own Key
One interface client, multiple providers.
Route AI requests across multiple LLM providers with automatic fallback, all through a unified IChatClient interface.
Features
- Unified interface — single
IChatClientthat routes to OpenAI, Anthropic, Groq, DeepSeek, Ollama, OpenRouter, and any OpenAI-compatible provider - Automatic fallback — define fallback chains per model; if a provider fails, BYOK tries the next one
- Model aliases — friendly names like
"fast"or"cheap"that resolve to real model paths - Per-provider key rotation — each provider gets its own API key provider; keys can rotate at runtime without restart
- Function calling — built-in support through
Microsoft.Extensions.AI.FunctionInvokingChatClient - OpenTelemetry ready — providers expose
ChatClientMetadatafor observability instrumentation - Dependency injection —
AddBYOKClient()extension forIServiceCollection
Install
dotnet add package BYOK.Core
dotnet add package BYOK.OpenAI
dotnet add package BYOK.Anthropic
Quick Start
using Microsoft.Extensions.AI;
using BYOK.Core;
using BYOK.OpenAI;
using BYOK.Anthropic;
var openAiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? "";
var anthropicKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY") ?? "";
var groqKey = Environment.GetEnvironmentVariable("GROQ_API_KEY") ?? "";
var byok = BYOKClient.Create(options =>
{
options.UseOpenAI(openAiKey);
options.UseAnthropic(anthropicKey);
options.UseGroq(groqKey);
options.Routing.ForModelId("openai:gpt-5.4-mini")
.FallbackTo("groq:llama-4-maverick");
options.Routing.ForAlias("fast")
.Try("anthropic:claude-sonnet-5");
options.DefaultTimeout = TimeSpan.FromSeconds(100);
});
var messages = new List<ChatMessage>
{
new(ChatRole.System, "You are a helpful assistant."),
new(ChatRole.User, "Hello!")
};
var chatOptions = new ChatOptions
{
ModelId = "openai:gpt-5.4-mini"
};
var response = await byok.GetResponseAsync(messages, chatOptions);
Console.WriteLine($"Result: {response.Text}");
Dependency injection
services.AddBYOKClient(options =>
{
options.UseOpenAI(openAiKey);
options.UseAnthropic(anthropicKey);
options.Routing.ForModelId("openai:gpt-5.4-mini")
.FallbackTo("groq:llama-4-maverick");
});
Then inject IChatClient anywhere:
public class MyService(IChatClient chatClient)
{
public async Task RunAsync()
{
var response = await chatClient.GetResponseAsync(messages, new ChatOptions
{
ModelId = "openai:gpt-5.4-mini"
});
}
}
Usage
Route format
Set ModelId to "{providerName}:{modelId}" and BYOK routes to the right provider:
ModelId = "openai:gpt-5.4-mini"
| Route | Provider | Model |
|---|---|---|
openai:gpt-5.4-mini |
openai | gpt-5.4-mini |
groq:llama-4-maverick |
groq | llama-4-maverick |
deepseek:deepseek-v4-flash |
deepseek | deepseek-v4-flash |
ollama:llama4 |
ollama | llama4 |
anthropic:claude-sonnet-5 |
anthropic | claude-sonnet-5 |
The provider name must match one registered via UseOpenAICompatible(), UseAnthropicCompatible(), or one of the built-in extensions.
Built-in providers
| Extension | Provider name (default) | Notes |
|---|---|---|
UseOpenAI() |
openai |
api.openai.com/v1 |
UseOpenAICompatible() |
custom | Any OpenAI-compatible endpoint |
UseGroq() |
groq |
api.groq.com/openai/v1 |
UseOpenRouter() |
openrouter |
openrouter.ai/api/v1 |
UseOllama() |
ollama |
localhost:11434/v1 (no API key needed) |
UseDeepSeek() |
deepseek |
api.deepseek.com/v1 |
UseAnthropic() |
anthropic |
api.anthropic.com |
UseAnthropicCompatible() |
custom | Any Anthropic-compatible endpoint |
UseDeepSeekAnthropic() |
deepseek-anthropic |
api.deepseek.com/anthropic |
UseOllamaAnthropic() |
ollama-anthropic |
localhost:11434 (Anthropic-compatible) |
Fallback
options.Routing.ForModelId("openai:gpt-5.4-mini")
.FallbackTo("groq:llama-4-maverick")
.FallbackTo("anthropic:claude-sonnet-5");
If the primary fails, BYOK tries fallbacks in order.
Aliases
options.Routing.ForAlias("fast").Try("anthropic:claude-sonnet-5");
options.Routing.ForAlias("cheap").Try("groq:deepseek-v4-flash");
Use anywhere a route is expected: ModelId = "fast".
Custom providers
options.UseOpenAICompatible(
providerName: "myprovider"
apiKey: openAiKey,
configure: config =>
{
config.BaseUrl = "https://my-custom-endpoint.com/v1";
config.AddHeader("X-Custom", "value");
config.NativeOptions.ClientLoggingOptions.LogLevel = OpenAI.Diagnostics.ClientLogLevel.Informational;
});
options.UseAnthropicCompatible(
providerName: "myanthropic"
apiKey: anthropicKey,
configure: config =>
{
config.BaseUrl = "https://my-custom-anthropic.com";
});
Then use ModelId = "myprovider:some-model" or ModelId = "myanthropic:some-model".
Or register any custom IChatClient with a factory:
options.UseProvider("my-custom", () => new MyChatClient(apiKey));
Streaming
await foreach (var update in byok.GetStreamingResponseAsync(messages, chatOptions))
{
Console.Write(update.Text);
}
Function calling
var fcMessages = new List<ChatMessage>
{
new(ChatRole.System, "You are a helpful assistant that can use tools."),
new(ChatRole.User, "What time is it?")
};
var fcOptions = new ChatOptions
{
ModelId = "groq:llama-4-maverick",
Tools = [AIFunctionFactory.Create(GetCurrentTime)]
};
var response = await byok.GetResponseAsync(fcMessages, fcOptions);
Console.WriteLine($"Result: {response.Text}");
Define your function tool:
[Description("Returns the current time")]
static string GetCurrentTime() => DateTime.Now.ToString("HH:mm:ss");
Architecture
┌──────────────────────────────────────────┐
│ BYOKClient │
│ Routing → Provider Factory → IChatClient │
└──────────────────────────────────────────┘
│ │
▼ ▼
BYOK.OpenAI BYOK.Anthropic
OpenAICompatibleClient AnthropicChatClient
(IChatClient) (IChatClient)
Each provider client caches the underlying SDK client and only rebuilds when the API key changes.
License
MIT © BracoZS
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Extensions.AI (>= 10.7.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on BYOK.Core:
| Package | Downloads |
|---|---|
|
BYOK.OpenAI
BYOK (Bring Your Own Key) — OpenAI / OpenAI-compatible provider with routing & fallback support |
|
|
BYOK.Anthropic
BYOK (Bring Your Own Key) — Anthropic provider (Claude) with routing & fallback support |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 100 | 7/3/2026 |