Add MentorAgent to an existing app
Add MentorAgent to a Blazor Web App you already have: install the package, register the services, mark your methods and place the widget.
On this page
Use this page when you have a Blazor Web App and want an agent that calls methods your app already has. For a new app, follow the Quickstart instead. If your front end is React, Angular, Vue or a mobile app with an ASP.NET Core backend, follow Any front end: the actions you mark are the same.
Before you start
Section titled “Before you start”- Your app is a Blazor Web App on .NET 10. In
Components/App.razor,<Routes>has@rendermode="InteractiveServer", or it has no render mode and each page or component chooses its own. Prerequisites lists the other versions you need. - If
<Routes>usesInteractiveAutoorInteractiveWebAssembly, do not follow this page. Follow option B of Blazor WebAssembly and Auto instead. - You need the package of your model provider. MentorAgent does not include one. If you use Azure OpenAI with the Responses API, read Provider package versions first.
Install the packages
Section titled “Install the packages”In the project that hosts the app (the server project, if the solution has a client project too):
.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.0Then add the package of your model provider. The code below uses OpenAI:
dotnet add package Microsoft.Extensions.AI.OpenAI --version 10.6.0For another provider, see Model providers.
Register MentorAgent
Section titled “Register MentorAgent”In Program.cs, add the using directives:
using Novior.MentorAgent.Extensions;
using Microsoft.Extensions.AI;
using OpenAI;Then, before builder.Build(), register your service and MentorAgent:
builder.Services.AddScoped<CaseService>();
builder.Services.AddMentorAgent(options =>
{
options.AppName = "Case management";
options.AppDescription = "Tracks customer support cases, their status and their notes";
options.ChatClient = new OpenAIClient(
builder.Configuration["OpenAI:Key"] ?? throw new InvalidOperationException(
"OpenAI:Key is missing: run dotnet user-secrets set OpenAI:Key <your-key>"))
.GetChatClient("gpt-4o-mini")
.AsIChatClient();
// Every assembly that contains actions, agents or pages
options.ScanAssemblies = [typeof(CaseService).Assembly];
});- Register every service whose methods you expose, as you register any service. MentorAgent gets the instance from dependency injection. A method whose service is not registered is left out, with a warning in the log.
ScanAssemblieslists the assemblies to search for actions, agents and pages. If your services live in a class library, list that library, and list the web project too if its pages use[MentorPage]. List each assembly once: a repeated entry is ignored, with a warning.AppDescriptionis optional. It tells the model what your application is for, so give it a real sentence.- The key comes from configuration. In development, keep it in user secrets. Run
dotnet user-secrets initif the project has no user secrets yet, thendotnet user-secrets set OpenAI:Key <your-key>. For other providers, see Model providers.
Mark the methods the agent may call
Section titled “Mark the methods the agent may call”Put [MentorAction] on public methods of a service. It comes from Novior.MentorAgent.Attributes.
public class CaseService(ICaseRepository cases)
{
[MentorAction(
Description = "Gets the status of a support case",
ReadOnly = true)]
public Task<string> GetCaseStatusAsync(string caseNumber)
=> cases.GetStatusAsync(caseNumber);
[MentorAction(
Description = "Adds a note to a support case",
RequiresConfirmation = true)]
public Task AddNoteAsync(string caseNumber, string text)
=> cases.AddNoteAsync(caseNumber, text);
}- A method that only reads declares
ReadOnly = true. The agent calls it without asking. - A method that changes data asks the user to confirm before it runs. A
[MentorAction]that is not read-only asks by default.RequiresConfirmation = truestates the rule in your code. - A method with
[Description]alone has no rules. It never asks, and anyone who reaches the agent can call it. Do not use it for a method that changes data. - The tool name is the method name in snake case, without a trailing
Async:GetCaseStatusAsyncbecomesget_case_status. Options that refer to a tool use this name. - Only public instance methods declared on the class itself count. Static, private and inherited methods are ignored.
The attributes can go on the service your pages already use, or on a small class that calls your existing code, as CaseService does here with ICaseRepository. A separate class lets you choose exactly what the agent sees.
Place the widget
Section titled “Place the widget”Add the widget's namespace to Components/_Imports.razor:
@using Novior.MentorAgent.Abstractions.ComponentsWhere the widget goes depends on the render mode of your app. Open Components/App.razor and look at <Routes>:
Global Server interactivity
<Routes> has @rendermode="InteractiveServer", so every page and the layout are interactive. Put the widget at the end of Components/Layout/MainLayout.razor:
<ChatWidget />Interactivity per page or component
<Routes> has no @rendermode: each page or component chooses its own, and the layout renders statically. Pin the widget to the server. To do this, give it its own render mode, InteractiveServer, at the end of Components/Layout/MainLayout.razor:
<ChatWidget @rendermode="InteractiveServer" />The widget is interactive on every page, including pages that render statically or run in WebAssembly. A page that hands data to the agent through IMentorPageContext must be interactive itself.
If your app was created with WebAssembly interactivity, it has no Server interactivity yet. With the pinned widget, every page then answers HTTP 500. Add Server interactivity in Program.cs, as described in Blazor WebAssembly and Auto.
If <Routes> uses InteractiveAuto or InteractiveWebAssembly, the layout comes from the client project and can run in the browser. MentorAgent cannot run in the browser, so a widget that runs on the server fails in that layout. Follow option B of Blazor WebAssembly and Auto instead.
Check that it works
Section titled “Check that it works”Run the app, open a page and click the widget button. Ask a question that one of your read methods answers, then ask for a change and check that the confirmation box appears before the method runs.
If the agent answers without calling your method, see Troubleshooting.
If your app signs users in
Section titled “If your app signs users in”MentorAgent reads the signed-in user through the AuthenticationStateProvider your app already has: nothing else needs configuring. With a signed-in user:
The prompt includes the user's name and roles, so the model knows who it is talking to.
Roles.
RequiredRolesrestricts an action to users who hold at least one of the roles, checked withClaimsPrincipal.IsInRole(theClaimTypes.Roleclaims, by default):[MentorAction( Description = "Moves a support case to another team", RequiresConfirmation = true, RequiredRoles = ["Supervisors"])] public Task ReassignCaseAsync(string caseNumber, string team) => cases.ReassignAsync(caseNumber, team);A signed-out user, or one without the role, is refused before any confirmation box appears. Register this service too.
Memory and the per-user rate limit, when you turn them on, are kept for each user. MentorAgent identifies the user by the
ClaimTypes.NameIdentifierclaim. If it is missing, it uses thesubclaim, then theoidclaim, then the user name. Without sign-in, memory and the rate limit treat each session as a separate anonymous user.
With ASP.NET Core Identity, roles reach the claims only when role support is registered: the Blazor template's AddIdentityCore<ApplicationUser>() needs .AddRoles<IdentityRole>(). See Role-based authorization (external site).
Roles, confirmation and governance explains the checks, and 2 · Require roles and confirmation tries them step by step.
Next steps
Section titled “Next steps”Configure MentorAgent for the way you use it:
- Blazor Server app: the options that matter, the widget and authentication.
- Blazor WebAssembly and Auto, .NET MAUI (Blazor Hybrid) or any other front end, such as React, Angular, Vue or a native mobile app.
- MCP server and A2A server, to publish your actions to other agents.
- Production checklist, before you go to production.
See also
Section titled “See also”- Blazor Server app — Configure MentorAgent in a Blazor Web App with Server interactivity: services, the options that matter, the widget and authentication.
- Roles, confirmation and governance — How MentorAgent checks roles and asks for confirmation before an action runs, on every channel, and what it leaves to your code.
