# 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.

- URL: https://docs.mentoragent.net/get-started/existing-app
- Verified with: MentorAgent 1.0.0
- Last updated: 2026-10-14
- Packages: Novior.MentorAgent

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](https://docs.mentoragent.net/get-started/quickstart) instead. If your front end is React, Angular, Vue or a mobile app with an ASP.NET Core backend, follow [Any front end](https://docs.mentoragent.net/configure/any-front-end): the actions you mark are the same.

## 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](https://docs.mentoragent.net/get-started/prerequisites) lists the other versions you need.
- If `<Routes>` uses `InteractiveAuto` or `InteractiveWebAssembly`, do not follow this page. Follow [option B of Blazor WebAssembly and Auto](https://docs.mentoragent.net/configure/blazor-webassembly#option-b-run-the-widget-in-webassembly) 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](https://docs.mentoragent.net/get-started/prerequisites#provider-package-versions) first.

## Install the packages

In the project that hosts the app (the server project, if the solution has a client project too):

**.NET CLI**

```shell
dotnet add package Novior.MentorAgent
```

**PackageReference**

```xml title="YourApp.csproj"
<ItemGroup>
  <PackageReference Include="Novior.MentorAgent" Version="1.0.0" />
</ItemGroup>
```

**Central Package Management**

```xml title="Directory.Packages.props"
<ItemGroup>
  <PackageVersion Include="Novior.MentorAgent" Version="1.0.0" />
</ItemGroup>
```

```xml title="YourApp.csproj"
<ItemGroup>
  <PackageReference Include="Novior.MentorAgent" />
</ItemGroup>
```

**File-based app**

```csharp title="app.cs"
#:package Novior.MentorAgent@1.0.0
```

Then add the package of your model provider. The code below uses OpenAI:

```shell
dotnet add package Microsoft.Extensions.AI.OpenAI --version 10.6.0
```

For another provider, see [Model providers](https://docs.mentoragent.net/configure/model-providers).

## Register MentorAgent

In `Program.cs`, add the `using` directives:

```csharp title="Program.cs"
using Novior.MentorAgent.Extensions;
using Microsoft.Extensions.AI;
using OpenAI;
```

Then, before `builder.Build()`, register your service and MentorAgent:

```csharp title="Program.cs"
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.
- **`ScanAssemblies`** lists 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.
- **`AppDescription`** is 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 init` if the project has no user secrets yet, then `dotnet user-secrets set OpenAI:Key <your-key>`. For other providers, see [Model providers](https://docs.mentoragent.net/configure/model-providers).

## Mark the methods the agent may call

Put `[MentorAction]` on public methods of a service. It comes from `Novior.MentorAgent.Attributes`.

```csharp title="CaseService.cs"
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 = true` states 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`: `GetCaseStatusAsync` becomes `get_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

Add the widget's namespace to `Components/_Imports.razor`:

```razor title="Components/_Imports.razor"
@using Novior.MentorAgent.Abstractions.Components
```

Where 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`:

```razor title="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`:

```razor title="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](https://docs.mentoragent.net/configure/blazor-webassembly#minimal-configuration).

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](https://docs.mentoragent.net/configure/blazor-webassembly#option-b-run-the-widget-in-webassembly) instead.

## 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](https://docs.mentoragent.net/get-started/troubleshooting#the-agent-does-not-call-your-method).

## 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.** `RequiredRoles` restricts an action to users who hold at least one of the roles, checked with `ClaimsPrincipal.IsInRole` (the `ClaimTypes.Role` claims, by default):

  ```csharp title="CaseSupervisorService.cs"
  [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.NameIdentifier` claim. If it is missing, it uses the `sub` claim, then the `oid` claim, 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](https://learn.microsoft.com/aspnet/core/security/authorization/roles).

[Roles, confirmation and governance](https://docs.mentoragent.net/concepts/governance) explains the checks, and [2 · Require roles and confirmation](https://docs.mentoragent.net/get-started/tutorial/roles-and-confirmation) tries them step by step.

## Next steps

Configure MentorAgent for the way you use it:

- [Blazor Server app](https://docs.mentoragent.net/configure/blazor-server): the options that matter, the widget and authentication.
- [Blazor WebAssembly and Auto](https://docs.mentoragent.net/configure/blazor-webassembly), [.NET MAUI (Blazor Hybrid)](https://docs.mentoragent.net/configure/maui) or [any other front end](https://docs.mentoragent.net/configure/any-front-end), such as React, Angular, Vue or a native mobile app.
- [MCP server](https://docs.mentoragent.net/configure/mcp-server) and [A2A server](https://docs.mentoragent.net/configure/a2a-server), to publish your actions to other agents.
- [Production checklist](https://docs.mentoragent.net/configure/production), before you go to production.

---

- Previous: [4 · Put agents in a team](https://docs.mentoragent.net/get-started/tutorial/team.md)
- Next: [Blazor Server app](https://docs.mentoragent.net/configure/blazor-server.md)
