Model providers
Connect OpenAI, Azure OpenAI, Ollama and other local models, or your own AIAgent, and choose models that support tool calling.
On this page
This page shows how to connect MentorAgent to a model: OpenAI, Azure OpenAI, Ollama and other local models, or an agent you build with Agent Framework, such as a Foundry agent. MentorAgent calls the model through Microsoft.Extensions.AI. In AddMentorAgent you give it one of two things: an IChatClient, which is Path A, or an Agent Framework AIAgent that you have already built, which is Path B.
Choose a path
Section titled “Choose a path”Use Path A, options.ChatClient, whenever the provider has an IChatClient: OpenAI, Azure OpenAI, Ollama and any server with an OpenAI-compatible API. MentorAgent builds the agent and every feature works.
Use Path B, options.Agent, for a provider you reach only through an AIAgent. Two examples are a Foundry project, with Microsoft.Agents.AI.Foundry, and Anthropic's Claude models, with Microsoft.Agents.AI.Anthropic: you add these Agent Framework packages yourself. On Path B the agent's instructions are yours, and some features need a ChatClient that MentorAgent can call itself:
| Feature | Path A: ChatClient | Path B: Agent |
|---|---|---|
| Actions, MCP client tools, RAG, Agent Skills | Yes | Yes |
| Specialists, teams, remote A2A agents, YAML agents | Yes | No |
| UI actions of the current page | One tool per action | One generic invoke_ui_action tool |
| Safety check | Yes | Only with ClassifierChatClient |
| Model routing, tool filtering, hosted tools, structured outputs | Yes | No |
| Memory capture after each turn | Yes | Only with ClassifierChatClient; the remember tool stays |
| Chat history | Set through MentorOptions | Set on your agent |
Set ChatClient or Agent, never both. Whatever the path, the model must support tool calling: every action is a tool.
Install the packages
Section titled “Install the packages”.NET CLI
dotnet add package Novior.MentorAgentPackageReference
<ItemGroup>
<PackageReference Include="Novior.MentorAgent" Version="1.0.0" />
</ItemGroup>Central Package Management
<ItemGroup>
<PackageVersion Include="Novior.MentorAgent" Version="1.0.0" />
</ItemGroup><ItemGroup>
<PackageReference Include="Novior.MentorAgent" />
</ItemGroup>File-based app
#:package Novior.MentorAgent@1.0.0Novior.MentorAgent brings no model provider package. Add the ones that your provider needs:
| Provider | Packages to add |
|---|---|
| OpenAI, and Ollama through its OpenAI-compatible endpoint | Microsoft.Extensions.AI.OpenAI. It brings the OpenAI SDK and the AsIChatClient() method |
| Azure OpenAI | Azure.AI.OpenAI and Microsoft.Extensions.AI.OpenAI |
| Azure OpenAI with Microsoft Entra ID | Azure.Identity as well, for DefaultAzureCredential |
| A Foundry project (Path B) | Microsoft.Agents.AI.Foundry: see Foundry agents (Path B) |
| Anthropic (Path B) | Microsoft.Agents.AI.Anthropic |
Azure.AI.OpenAI 2.9.0-beta.1 is a prerelease, so dotnet add package needs a version for it. The examples on this page are compiled with these versions:
dotnet add package Microsoft.Extensions.AI.OpenAI --version 10.6.0
dotnet add package Azure.AI.OpenAI --version 2.9.0-beta.1
dotnet add package Azure.Identity --version 1.21.0Novior.MentorAgent brings System.ClientModel, so ApiKeyCredential needs no extra package. How the versions fit together, and the one combination that needs a pin, is in Provider package versions.
Minimal configuration
Section titled “Minimal configuration”Every example on this page is the model line inside AddMentorAgent(options => …). The rest of the configuration stays as on the page of your host, such as Blazor Server app or Any front end. These using directives cover all the examples. Keep Azure.AI.Projects only for a Foundry project: it comes with the Foundry package, not with MentorAgent:
using System.ClientModel; // ApiKeyCredential (Ollama)
using Azure; // AzureKeyCredential
using Azure.AI.OpenAI; // AzureOpenAIClient
using Azure.AI.Projects; // AIProjectClient (Foundry): only with Microsoft.Agents.AI.Foundry
using Azure.Identity; // DefaultAzureCredential
using Microsoft.Extensions.AI; // AsIChatClient, AsIEmbeddingGenerator
using OpenAI; // OpenAIClientWith OpenAI, keep the key in user secrets and set the client:
dotnet user-secrets set OpenAI:Key <your-key>options.ChatClient = new OpenAIClient(builder.Configuration["OpenAI:Key"]
?? throw new InvalidOperationException("Set OpenAI:Key with dotnet user-secrets."))
.GetChatClient("gpt-4o-mini")
.AsIChatClient();Complete configuration
Section titled “Complete configuration”This section connects the other providers: Azure OpenAI, Ollama and other local models, and Foundry agents. It also adds an embedding model and lists the options that matter on this page.
Azure OpenAI
Section titled “Azure OpenAI”With an API key, read the endpoint and the key from configuration. The model name is the name of your deployment:
options.ChatClient = new AzureOpenAIClient(
new Uri(builder.Configuration["AzureOpenAI:Endpoint"]!),
new AzureKeyCredential(builder.Configuration["AzureOpenAI:Key"]!))
.GetChatClient("gpt-4o-mini") // the deployment name
.AsIChatClient();{
"AzureOpenAI": {
"Endpoint": "https://<your-resource>.openai.azure.com/"
}
}Keep the key in user secrets while you develop:
dotnet user-secrets set AzureOpenAI:Key <your-key>Microsoft Entra ID needs no key. DefaultAzureCredential uses the managed identity when the app runs in Azure, and your developer sign-in on your machine. Give that identity access to the Azure OpenAI resource:
options.ChatClient = new AzureOpenAIClient(
new Uri(builder.Configuration["AzureOpenAI:Endpoint"]!),
new DefaultAzureCredential()) // managed identity in Azure, your developer sign-in locally
.GetChatClient("gpt-4o-mini")
.AsIChatClient();The Responses API needs one pin on the packages. Azure.AI.OpenAI 2.9.0-beta.1 calls a ResponsesClient constructor that OpenAI 2.11 removed. With OpenAI 2.11 or later, GetResponsesClient() throws MissingMethodException when your code calls it, although the build succeeds. Keep OpenAI at 2.10 by pinning Microsoft.Extensions.AI.OpenAI to [10.6.0], as in Provider package versions. Chat Completions needs no pin. OpenAI and Ollama need none either.
With the Responses API the service keeps the conversation, so MentorAgent must not keep its own history, and it installs no compaction either:
// The Responses client is experimental in the OpenAI SDK: without the pragma the build fails with OPENAI001
#pragma warning disable OPENAI001
options.ChatClient = new AzureOpenAIClient(
new Uri(builder.Configuration["AzureOpenAI:Endpoint"]!),
new DefaultAzureCredential())
.GetResponsesClient()
.AsIChatClient("gpt-4o-mini"); // the deployment name goes here
#pragma warning restore OPENAI001
// The service keeps the conversation: MentorAgent must not keep its own history
options.UseServiceManagedHistory = true;Ollama and other local models
Section titled “Ollama and other local models”Ollama exposes an OpenAI-compatible endpoint, so the OpenAI client talks to it:
// Ollama's OpenAI-compatible endpoint: same SDK, no extra package
options.ChatClient = new OpenAIClient(
new ApiKeyCredential("ollama"), // Ollama ignores it; the SDK requires one
new OpenAIClientOptions
{
Endpoint = new Uri("http://localhost:11434/v1"),
NetworkTimeout = TimeSpan.FromMinutes(20), // a CPU model can take minutes on a long prompt
})
.GetChatClient("llama3.2")
.AsIChatClient();
// The safety checks share the slow model: give them time, or point ClassifierChatClient at a faster one
options.SafetyCheckTimeout = TimeSpan.FromMinutes(2);Tool calling. Pick a model that supports tools. A model without them answers, but never runs your actions.
Context window. MentorAgent's prompt can be longer than Ollama (external site)'s default context, and Ollama cuts the start of the prompt without an error. Create a variant with a larger context and use its name in
GetChatClient:FROM llama3.2 PARAMETER num_ctx 16384ollama create llama3.2-16k -f ModelfileTime. A model on a CPU can take minutes on a long prompt: that is what
NetworkTimeoutin the snippet is for. It raises the HTTP time limit of the OpenAI client. The safety checks run on the same model, so give them time withSafetyCheckTimeout, or pointClassifierChatClientat a faster model.Other servers. A server with the OpenAI-compatible Chat Completions API is used the same way: change
Endpointand the model name.
Foundry agents (Path B)
Section titled “Foundry agents (Path B)”A Foundry project gives you an AIAgent. Novior.MentorAgent does not bring Agent Framework's Foundry package, so add Microsoft.Agents.AI.Foundry to your project. If the same project uses the Azure OpenAI Responses API, pin the Foundry package to this version: a newer one brings OpenAI 2.11 or later. The example on this page is compiled with this version:
<PackageReference Include="Microsoft.Agents.AI.Foundry" Version="[1.17.0-preview.260804.1]" />Then build the agent and set Agent instead of ChatClient:
// Path B: a pre-built AIAgent instead of a ChatClient
options.Agent = new AIProjectClient(
new Uri(builder.Configuration["Foundry:ProjectEndpoint"]!),
new DefaultAzureCredential())
.AsAIAgent(model: "gpt-4o-mini", instructions: "You are the assistant of a case management application.");On Path B the instructions you pass describe the agent's role and tone. MentorAgent adds the page, the user and your actions around them, but not its own coordinator prompt. The agent must be a ChatClientAgent, or another agent whose chat client invokes functions (FunctionInvokingChatClient), because that is where MentorAgent checks roles and confirmation. MentorAgent refuses any other agent when it builds the coordinator.
Embedding model
Section titled “Embedding model”An embedding model turns a text into a list of numbers that represents its meaning, so MentorAgent can find the texts closest to a message. It makes semantic tool filtering, semantic memory and semantic model routing possible. It uses a separate deployment:
options.EmbeddingGenerator = new AzureOpenAIClient(
new Uri(builder.Configuration["AzureOpenAI:Endpoint"]!),
new DefaultAzureCredential())
.GetEmbeddingClient("text-embedding-3-small") // a separate embedding deployment
.AsIEmbeddingGenerator();Setting it switches nothing on. Each feature has its own option: EnableToolFiltering, MemoryRelevanceFiltering and RoutingStrategy = MentorRoutingStrategy.Semantic. If you turn one on without an embedding model, MentorAgent logs a warning and the feature stays off. RequireLookupForRecordQuestions and RequireActionForChangeRequests need it too, through tool filtering.
Options that matter here
Section titled “Options that matter here”| Option | What it does |
|---|---|
ChatClient | Path A: the model MentorAgent builds its agent on |
Agent | Path B: a pre-built AIAgent. Never together with ChatClient |
EmbeddingGenerator | The embedding model for filtering, memory and routing |
ClassifierChatClient | The model for MentorAgent's own short decisions: safety checks, the off-topic check (RefuseOutOfScope), the facts to remember, and the question behind the two Require… options. It defaults to ChatClient; a small, fast model shortens the wait before each answer |
StrongChatClient, RoutingStrategy | A stronger model for the hard questions: see Cost and model routing |
UseServiceManagedHistory | Path A with a client whose service keeps the conversation, such as the Responses API |
SafetyCheckTimeout, SafetyCheckFailure | How long the safety checks may take, and what happens when they give no answer |
ConfigureChatClientPipeline | Adds your own IChatClient middleware to the Path A pipeline |
Every option is in Configuration options.
Security and roles
Section titled “Security and roles”- Keys stay on the server. Never put a key in the source code or in a client project. Use user secrets while you develop, and environment variables or a secret store in production. On Azure, Entra ID with a managed identity removes the key altogether.
- The provider does not decide what runs. Roles and confirmation are checked by MentorAgent around each action, whatever the model and whatever the path: see Roles, confirmation and governance.
- Data leaves with the prompt. The page context, the user's name and roles, memories, retrieved documents and action results are sent to the provider. A local model keeps them on your machine. Data that leaves your application lists everything that goes out.
Common errors
Section titled “Common errors”- The build does not find
OpenAIClient,AzureOpenAIClientorAsIChatClient. The provider packages are not in your project, becauseNovior.MentorAgentdoes not include a model provider package. Add them, as in Install the packages. GetResponsesClient()throwsMissingMethodExceptionwhen it is called.OpenAIresolved to 2.11 or later. PinMicrosoft.Extensions.AI.OpenAIas in Azure OpenAI.- The build does not find
AIProjectClientor theAzure.AI.Projectsnamespace. The Foundry package is not in your project, becauseNovior.MentorAgentdoes not include it. AddMicrosoft.Agents.AI.Foundrywith the pinned version, as in Foundry agents (Path B). - The build stops with
OPENAI001onGetResponsesClient. The Responses client is experimental in the OpenAI SDK: keep the#pragmaaround it. - Every turn fails with "Only ConversationId or ChatHistoryProvider may be used, but not both". The client keeps the conversation on the service: set
UseServiceManagedHistory = true. - The app stops at startup with "[MentorAgent] Set ChatClient OR Agent, not both." or "[MentorAgent] Configure ChatClient or Agent." Set exactly one of them. MentorAgent checks the options when the host starts. In a .NET MAUI app, which has no host start, the error comes the first time MentorAgent is used.
- The widget or your own client shows "The assistant could not start", and the log says "The pre-built agent in options.Agent … cannot carry MentorAgent's tool gate". The agent does not use a chat client that invokes functions (
FunctionInvokingChatClient). Build it from a chat client, or use Path A. - The model answers but never calls your actions. It does not support tool calling, or, on Ollama, the context window cut the prompt.
- The safety check is skipped with a timeout warning. The model is too slow for the default limit: raise
SafetyCheckTimeoutor set a fasterClassifierChatClient.
See also
Section titled “See also”- Prerequisites — The .NET version, hosts, Agent Framework and provider package versions MentorAgent is tested with, and how to install it.
- Blazor Server app — Configure MentorAgent in a Blazor Web App with Server interactivity: services, the options that matter, the widget and authentication.
- Production checklist — Settings to review before you go to production: governance defaults, safety check, rate limits, cost and routing, history, observability, and outgoing data.
- Configuration options — Every MentorOptions property with its type, default and effect, grouped by area, plus the options of the WebAssembly client and the YAML loader.
