# 3 · Hand off to a specialist agent

> Tutorial step 3: add a specialist agent that owns case questions, and let the coordinator hand requests over to it.

- URL: https://docs.mentoragent.net/get-started/tutorial/specialist-agent
- Verified with: MentorAgent 1.0.0
- Last updated: 2026-10-13
- Duration: 10 min
- Packages: Novior.MentorAgent

So far the coordinator, the main agent that answers you, holds every action. As an app grows, one agent with the tools of every area has more tools to choose from on every request. A specialist agent owns one area, with its own tools and its own instructions. The coordinator passes it the requests that belong to that area: this is called a *handoff*. In this step the case actions move into a specialist.

**Before you start:** finish [2 · Require roles and confirmation](https://docs.mentoragent.net/get-started/tutorial/roles-and-confirmation).

## Create the specialist

Create `CaseSpecialist.cs`. It has the same four methods as `CaseService`, and the `[MentorAgent]` attribute on the class. The attribute has the same name as the library: it makes the class a specialist agent.

```csharp title="CaseSpecialist.cs"
using System.ComponentModel;
using Novior.MentorAgent.Attributes;

[MentorAgent(
    Name = "CaseSpecialist",
    Description = "Handles support cases: finds and lists them, adds notes and closes them")]
public class CaseSpecialist(CaseStore store)
{
    [MentorAction(
        Description = "Gets a support case by its number, with its status, priority and notes",
        ReadOnly = true)]
    public SupportCase? GetCase(
        [Description("The case number, for example C-1")] string caseNumber)
        => store.Find(caseNumber);

    [MentorAction(
        Description = "Lists support cases, optionally only those with a given status",
        ReadOnly = true)]
    public IReadOnlyList<SupportCase> ListCases(
        [Description("Open, Waiting for customer or Closed. Leave empty for every case")] string? status = null)
        => store.List(status);

    [MentorAction(
        Description = "Adds a note to a support case",
        RequiresConfirmation = true,
        RequiredRoles = ["Agents", "Supervisors"])]
    public string AddNote(string caseNumber, string text)
    {
        store.AddNote(caseNumber, text);
        return $"Note added to case {caseNumber}.";
    }

    [MentorAction(
        Description = "Closes a support case with a resolution",
        RequiresConfirmation = true,
        RequiredRoles = ["Supervisors"])]
    public string CloseCase(string caseNumber, string resolution)
    {
        store.Close(caseNumber, resolution);
        return $"Case {caseNumber} closed.";
    }
}
```

- `Name` identifies the specialist. The coordinator's instructions list it, and the handoff uses it.
- `Description` tells the coordinator which requests belong here. Write it as you write the description of an action.
- Without `Instructions`, MentorAgent writes the specialist's instructions from `Name` and `Description`. They include the grounding rule: state only facts that its tools returned. If you write your own `Instructions`, they replace all of this, including the grounding rule.
- The methods keep their attributes, so `RequiredRoles` and `RequiresConfirmation` move with them.

Then delete `CaseService.cs`: the specialist replaces it. Do not keep both, or the same tool names would exist twice. MentorAgent finds the roles and the confirmation of a tool by the tool's name, so keep each tool name unique across your actions, specialists and teams.

## Register the specialist

In `Program.cs`, replace the `AddScoped<CaseService>()` line with `AddScoped<CaseSpecialist>()`. The registrations now read:

```csharp title="Program.cs"
builder.Services.AddSingleton<CaseStore>();
builder.Services.AddScoped<CaseSpecialist>();   // replaces AddScoped<CaseService>()
```

MentorAgent finds the specialist through `ScanAssemblies`, like your actions, and gets its instance from dependency injection. Without the registration, the specialist has no tools, and a warning in the log names the class.

The coordinator does not call the specialist directly. It calls `route_to_specialist`, a tool that MentorAgent adds, and a small router agent then picks the specialist. That is one more model call, as [What the handoff costs](https://docs.mentoragent.net/get-started/tutorial/specialist-agent#what-the-handoff-costs) shows.

Handoff needs `options.ChatClient`, which the Cases app sets. It is not available when you pass a prebuilt `options.Agent` instead.

## Try it

Run the app and sign in as Sam: `/dev/sign-in?name=Sam&role=Supervisors`.

1. Type "Which cases are open?". The coordinator has no case tools any more, so it calls `route_to_specialist`. A router passes the request to CaseSpecialist, which calls `list_cases`. The specialist's answer goes back to the coordinator, which writes the reply you see.
2. Type "Close case C-1: the customer can sign in again". The confirmation box appears as before, although the action now runs inside the specialist. Click **Confirm**.
3. Sign in as Alex with `/dev/sign-in?name=Alex&role=Agents`, and ask to close case C-2. The specialist's `close_case` is refused because Alex is not a supervisor, as in step 2.

If no specialist takes a request, the coordinator is told so. It then answers with its own tools, or says that it could not handle the request.

If you click **Cancel** on the confirmation of an action inside the specialist, the coordinator is told that you declined, and to say in one sentence that it did not proceed.

## What the handoff costs

Every agent that works on a request makes its own model calls. In step 2, closing a case took two calls: the coordinator called `close_case`, then wrote the reply. Now it takes five:

1. the coordinator calls `route_to_specialist`;
2. the router picks CaseSpecialist;
3. the specialist calls `close_case`;
4. the specialist answers;
5. the coordinator writes the reply.

All of them run on your `ChatClient` and count in the token usage. A specialist pays off when an area has many actions, or needs instructions of its own. With four actions, as here, one agent answers faster and costs less: the tutorial moves them to show how a handoff works.

## Next step

In [4 · Put agents in a team](https://docs.mentoragent.net/get-started/tutorial/team), two agents review a case together before the specialist closes it.

[Level 2: specialists](https://docs.mentoragent.net/concepts/agent-levels#level-2-specialists) explains how a handoff works in Agent Framework, and [Specialists and teams are gated too](https://docs.mentoragent.net/concepts/governance#specialists-and-teams-are-gated-too) explains why the checks travel with the method.

---

- Previous: [2 · Require roles and confirmation](https://docs.mentoragent.net/get-started/tutorial/roles-and-confirmation.md)
- Next: [4 · Put agents in a team](https://docs.mentoragent.net/get-started/tutorial/team.md)
