Skip to content
Introducing AI Conversations: Natural Language Interaction for Your Apps! Learn More

Chat Client Provider

The IChatClientProvider interface is the bridge between the AI conversation service and your AI backend.

By default, a built-in InjectedChatClientProvider is registered that resolves IChatClient from your DI container. For most apps, simply register an IChatClient and you’re done:

builder.Services.AddChatClient(new OpenAIClient("your-api-key").GetChatClient("gpt-4o").AsIChatClient());
builder.Services.AddShinyAiConversation(opts =>
{
// No need to call SetChatClientProvider — the default resolves IChatClient from DI
});

If no IChatClient is registered and no custom provider is set, an InvalidOperationException is thrown at runtime.

Two ready-made providers are available as separate NuGet packages so you don’t have to implement IChatClientProvider yourself.

A static provider for any OpenAI-compatible endpoint (OpenAI, Azure OpenAI, Ollama, etc.). Creates the client once at startup with logging and function invocation middleware.

Terminal window
dotnet add package Shiny.AiConversation.OpenAi
builder.Services.AddShinyAiConversation(opts =>
{
opts.AddStaticOpenAIChatClient(
apiToken: "your-api-key",
endpointUri: "https://api.openai.com/v1",
modelName: "gpt-4o"
);
});

Works great for Blazor WASM, server apps, or any MAUI app where you have an API key up front.

A MAUI-specific provider that authenticates via the GitHub OAuth device code flow and uses the Copilot API for chat completions. The entire authentication experience is self-contained:

  1. When authentication is needed, a popup appears with the device code
  2. The code is automatically copied to the clipboard
  3. The user presses OK and a browser opens to GitHub’s verification page
  4. The provider polls in the background until the user authorizes
  5. The OAuth token is exchanged for a Copilot API token and cached
  6. Tokens are persisted in SecureStorage across app restarts
Terminal window
dotnet add package Shiny.AiConversation.Maui.GithubCopilot
builder.Services.AddShinyAiConversation(opts =>
{
opts.AddGithubCopilotChatClient();
});

No login page, token storage, or event wiring needed — one line of registration handles everything.

Additional API on GitHubCopilotChatClientProvider:

MemberDescription
IsAuthenticatedWhether a stored token exists
StartAuthentication(ct)Manually trigger the device code flow
CancelAuthentication()Cancel an in-progress auth flow
SignOut()Clear stored tokens
AccessTokenChangedEvent fired when auth state changes (token or null)

For scenarios not covered by the built-in providers, implement IChatClientProvider:

public interface IChatClientProvider
{
Task<IChatClient> GetChatClient(CancellationToken cancelToken = default);
}

The service calls GetChatClient() before each chat request, so your implementation can handle token refresh, re-authentication, or client rotation.

builder.Services.AddShinyAiConversation(opts =>
{
opts.SetChatClientProvider<MyChatClientProvider>();
});
using Microsoft.Extensions.AI;
using Shiny.AiConversation;
public class OllamaChatClientProvider : IChatClientProvider
{
public Task<IChatClient> GetChatClient(CancellationToken cancelToken = default)
{
var client = new OllamaChatClient(
new Uri("http://localhost:11434"),
"llama3.1"
);
return Task.FromResult<IChatClient>(client);
}
}
PatternProvider
API key from configAddStaticOpenAIChatClient() or register IChatClient in DI
GitHub Copilot (device code flow)AddGithubCopilotChatClient()
Managed identity / customImplement IChatClientProvider
Token refresh with cachingImplement IChatClientProvider