Questa pagina non è ancora tradotta in italiano: qui la trovi in inglese.
Blazor Server app
Configure MentorAgent in a Blazor Web App with Server interactivity: services, the options that matter, the widget and authentication.
On this page
Use this page to add MentorAgent and its chat widget to a Blazor Web App with Server interactivity. The widget and the agent run in the same server process and talk through in-process events. So you install one package and map no endpoint.
When to choose it
Section titled “When to choose it”- Your app is a Blazor Web App with Server interactivity, or you can make the layout that hosts the widget interactive on the server.
- You want the simplest setup. The model key stays on the server, and the browser only receives the rendered UI.
For the other hosts see Blazor WebAssembly and Auto, .NET MAUI and Any front end, for React, Angular, Vue or a native mobile app. Channels compares them all.
Install the packages
Section titled “Install the packages”.NET CLI
dotnet add package Novior.MentorAgentPackageReference
<ItemGroup>
<PackageReference Include="Novior.MentorAgent" Version="1.2.0" />
</ItemGroup>Central Package Management
<ItemGroup>
<PackageVersion Include="Novior.MentorAgent" Version="1.2.0" />
</ItemGroup><ItemGroup>
<PackageReference Include="Novior.MentorAgent" />
</ItemGroup>File-based app
#:package Novior.MentorAgent@1.2.0Novior.MentorAgent brings the widget's components with it, but it does not include a model provider package. The code on this page uses OpenAI, so add its package too:
dotnet add package Microsoft.Extensions.AI.OpenAI --version 10.6.0For another provider, see Model providers. You do not need Novior.MentorAgent.Server to run the widget on this host. Add it only if the same app serves the Model Context Protocol (MCP) or the Agent-to-Agent (A2A) protocol: see MCP server and A2A server.
Minimal configuration
Section titled “Minimal configuration”Keep the model key out of the source code:
dotnet user-secrets init dotnet user-secrets set OpenAI:Key <your-key>Register MentorAgent in
Program.cs, next to the template'sAddRazorComponents:// MentorLanguage, MentorTheme, ChatPosition, MentorshipLevel using Novior.MentorAgent.Abstractions.Models; using Novior.MentorAgent.Extensions; // AddMentorAgent using Microsoft.Extensions.AI; // AsIChatClient using OpenAI; // OpenAIClientbuilder.Services.AddMentorAgent(options => { options.AppName = "Case management"; options.ChatClient = new OpenAIClient( builder.Configuration["OpenAI:Key"] ?? throw new InvalidOperationException( "Set OpenAI:Key with dotnet user-secrets.")) .GetChatClient("gpt-4o-mini") .AsIChatClient(); options.ScanAssemblies = [typeof(Program).Assembly]; });AppName, a model andScanAssembliesare required. TheChatClientline connects OpenAI: for Azure OpenAI, Ollama or Foundry, take the line from Model providers.ScanAssembliesis where MentorAgent looks for your actions, agents and pages. Register the services that hold your actions as usual, for example withAddScoped.Make the whole app interactive. If you created the app with Interactivity location: Global (
dotnet new blazor --interactivity Server --all-interactive),Components/App.razoralready has these two lines. Otherwise, add them:<HeadOutlet @rendermode="InteractiveServer" /> <Routes @rendermode="InteractiveServer" />Add the widget to the layout:
@using Novior.MentorAgent.Abstractions.Components <ChatWidget />The widget injects its own stylesheet and script. You do not change
App.razorfor them.
Run the app: the widget button appears in the bottom-right corner of every page that uses the layout.
Each circuit, the connection that Blazor Server keeps with each browser tab, gets its own coordinator, conversation and page context. Memory stores and the rate limiter are shared by the whole process.
Complete configuration
Section titled “Complete configuration”A configuration for an application with real users, still in Program.cs:
builder.Services.AddMentorAgent(options =>
{
// Required
options.AppName = "Case management";
options.ChatClient = new OpenAIClient(
builder.Configuration["OpenAI:Key"]
?? throw new InvalidOperationException(
"Set OpenAI:Key with dotnet user-secrets."))
.GetChatClient("gpt-4o-mini")
.AsIChatClient();
options.ScanAssemblies = [typeof(Program).Assembly];
// What the assistant knows about the application
options.AppDescription =
"Support case management: case status, notes and closure";
options.Language = MentorLanguage.English;
options.MentorshipLevel = MentorshipLevel.Standard;
// The widget
options.BotName = "Case assistant";
options.WelcomeMessage = "Ask me about your support cases.";
options.Theme = MentorTheme.Minimal; // the light theme
options.PrimaryColor = "#2563eb";
options.Position = ChatPosition.BottomRight;
// Limits and safety
options.MaxMessageLength = 2000;
options.RateLimitPerUser = 20; // messages per window, per user
options.EnableSafetyCheck = true;
// Exception details in replies: never in production
options.IncludeWorkflowExceptionDetails = builder.Environment.IsDevelopment();
});Options for Blazor Server
Section titled “Options for Blazor Server”| Option | Why it matters on Blazor Server |
|---|---|
AppDescription | A real sentence about your application. The prompt and the safety check use it to tell ordinary questions from attempts to extract the prompt or secrets |
Language | The language of the answers and of the widget's own texts |
BotName, WelcomeMessage, Position | The widget reads them from MentorOptions on this host |
Theme, PrimaryColor | The widget reads them from MentorOptions too. Theme = Minimal is the light theme. PrimaryColor takes one six-digit hex color and derives the other shades from it: pressed, glow, accent border and button shadow. Both work under a strict Content Security Policy: see Content Security Policy |
MentorshipLevel | How much the agent explains and suggests: Minimal, Standard or Proactive. Proactive closes its answers with suggested next steps only with ProactiveNextSteps |
MaxMessageLength | Longer messages are refused before the model is called, so they cost nothing |
RateLimitPerUser | Counted per signed-in user. Without sign-in it is counted per circuit, so a reload starts a new count |
EnableSafetyCheck | One extra model call checks each message before the answer, for prompt injection, jailbreaks and attempts to extract the system prompt or credentials. Point ClassifierChatClient at a small model to keep it fast |
IncludeWorkflowExceptionDetails | Puts specialist and team errors in the reply the user reads: development only |
Every option, with its type and default, is in Configuration options; the widget's own are under Widget.
Colors, sizes and fonts. Beyond Theme and PrimaryColor, the widget reads CSS variables that start with --bm-. Override them in a stylesheet loaded after the widget's:
:root {
--bm-panel-w: 480px;
--bm-font: 'Inter', system-ui, sans-serif;
}The widget requests nothing from another origin. The package ships its two fonts, Sora and JetBrains Mono, under the SIL Open Font License 1.1. To use your own fonts, override --bm-font and --bm-font-mono: the browser then never downloads the packaged files. The policy that the widget needs is in Content Security Policy.
Security and roles
Section titled “Security and roles”- Roles. MentorAgent reads the circuit's signed-in user through
AuthenticationStateProviderand checksRequiredRolesagainst the user's role claims. Set up authentication as in any Blazor Web App. Without it every user is anonymous, and every action withRequiredRolesis refused. The order of the checks is in Two checks, in this order. - Confirmation. The widget shows the confirmation box before an action that asks for confirmation runs. A
[MentorAction]that is not read-only asks for confirmation by default: see Confirmation by default. If the circuit closes while the box is open, the turn ends with it.RequireConfirmation = falseturns off these boxes, but never the role checks: see The global switch. - Anonymous users. With
AnonymousIdentityat its default,PerSession, each circuit has its own memory and its own rate-limit count. UseSharedonly for an application with a single user. - Other channels. If the same app also serves MCP or A2A, with
Novior.MentorAgent.Server, actions that ask for confirmation are withheld there. That includes a[MentorAction]that declares nothing: see Every declaration, on every channel. An A2A task runs as the user of its request. That user is signed in only if the endpoint requires authentication: see Where nobody can answer.
Common errors
Section titled “Common errors”- The widget button appears, but nothing happens when you click it. The layout is rendered statically, so the widget has no circuit. Make the app interactive (step 3 above), or give the widget its own render mode as in option A of WebAssembly and Auto. A static page also cannot hand the agent its page context or UI actions.
- The app stops at startup with
InvalidOperationException. The message says what is missing: "Configure ChatClient or Agent", "AppName is required" or "ScanAssemblies cannot be empty". MentorAgent checks the options when the host starts, before the first request. - The key is not found outside your machine. User secrets are loaded only in the
Developmentenvironment. Elsewhere, read the key from an environment variable or a secret store. - Every action with
RequiredRolesis refused. Nobody is signed in, or the user's roles are not role claims. Check whatAuthenticationStateProviderreturns for that user.
Vedi anche
Sezione “Vedi anche”- Canali: come i client arrivano all'agente — Scegli come i client raggiungono il tuo agente: il widget della chat, SignalR o HTTP dal tuo front end, o un protocollo per altri agenti e strumenti AI.
- Add MentorAgent to an existing app — Add an AI agent to a .NET Blazor Web App you already have: install the package, register the services, mark the methods it may call and place the chat widget.
- Model providers — Connect your .NET AI agent to OpenAI, Azure OpenAI, Ollama and other local models, or to your own Agent Framework AIAgent, and choose models with tool calling.
- 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.
