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.
In this tutorial, you'll:
- Turn the case service into a specialist agent with
[MentorAgent] - Register the specialist so the coordinator can hand requests to it
- Check that roles and confirmation still apply inside the specialist
- Count what a handoff costs in model calls
On this page
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.
Create the specialist
Section titled “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.
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.";
}
}Nameidentifies the specialist. The coordinator's instructions list it, and the handoff uses it.Descriptiontells the coordinator which requests belong here. Write it as you write the description of an action.- Without
Instructions, MentorAgent writes the specialist's instructions fromNameandDescription. They include the grounding rule: state only facts that its tools returned. If you write your ownInstructions, they replace all of this, including the grounding rule. - The methods keep their attributes, so
RequiredRolesandRequiresConfirmationmove 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
Section titled “Register the specialist”In Program.cs, replace the AddScoped<CaseService>() line with AddScoped<CaseSpecialist>(). The registrations now read:
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 shows.
Handoff needs options.ChatClient, which the Cases app sets. It is not available when you pass a prebuilt options.Agent instead.
Try it
Section titled “Try it”Run the app and sign in as Sam: /dev/sign-in?name=Sam&role=Supervisors.
- 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 callslist_cases. The specialist's answer goes back to the coordinator, which writes the reply you see. - 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.
- Sign in as Alex with
/dev/sign-in?name=Alex&role=Agents, and ask to close case C-2. The specialist'sclose_caseis 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
Section titled “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:
- the coordinator calls
route_to_specialist; - the router picks CaseSpecialist;
- the specialist calls
close_case; - the specialist answers;
- 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
Section titled “Next step”In 4 · Put agents in a team, two agents review a case together before the specialist closes it.
Level 2: specialists explains how a handoff works in Agent Framework, and Specialists and teams are gated too explains why the checks travel with the method.
What you learned
Section titled “What you learned”- Turn the case service into a specialist agent with
[MentorAgent] - Register the specialist so the coordinator can hand requests to it
- Check that roles and confirmation still apply inside the specialist
- Count what a handoff costs in model calls
See also
Section titled “See also”- Attributes — The parameters of MentorAction, MentorAgent, MentorTeam, TeamMember, MentorPage and MentorSkill, with their defaults and rules.
- The three agent levels — Actions, specialists and teams: how the three levels of MentorAgent map to Agent Framework, and when to use each one.
