Skip to content

Finish with a summary agent

The interviewers can ask questions and save feedback. Now we’ll give the interview a saved ending.

The summariser reads the transcript, appends final feedback, and completes the record. Giving that responsibility its own instructions makes the ending easier to inspect and change.

All edits are in src/InterviewCoach.Agent/AgentDelegateFactory.cs in interview-coach-lab. The receptionist and behavioural interviewer keep their existing definitions.

Update triage to include the summariser and consider completed phases when routing. Notice the priority of the latest request: an early finish should take precedence over an old message about starting intake.

Let triage route to the summary

File to edit: src/InterviewCoach.Agent/AgentDelegateFactory.cs

Function to edit: CreateHandOffWorkflow

Replace the matching block with the code below. Open "Current code" to locate the block in your file.

Current code
Current code
// --- Triage Agent ---
var triageAgent = CreateProviderAgent(
services: sp,
name: "triage",
description: "Routes the conversation to the correct interview specialist.",
instructions: """
You route an interview between receptionist, behavioural_interviewer, and technical_interviewer.
Handle the latest user request first, using earlier messages only as context.
If the user supplies an answer, route to the interviewer who asked the latest question, even if they also want to finish.
If the user wants to stop or finish, acknowledge their choice and end this turn without a handoff.
Summary generation comes in the next lesson. Do not restart intake or an earlier interview phase.
Honor an explicit request for behavioural or technical practice by routing to that interviewer.
Route to receptionist only while intake is incomplete.
Otherwise keep an answer with the interviewer who asked the latest question.
After technical practice, ask whether the user wants more practice; wait for their choice.
""");

Updated code
// --- Triage Agent ---
// Routes using the latest request and completed phases. Has no application tools.
var triageAgent = CreateProviderAgent(
services: sp,
name: "triage",
description: "Routes the conversation to the correct interview specialist.",
instructions: """
You are the Triage agent for an AI Interview Coach system.
Your ONLY job is to analyze the conversation and hand off to the right specialist agent.
You do NOT answer questions or conduct interviews yourself.
IMPORTANT: Before routing, review the FULL conversation history to determine
which phases have already been completed. Repeat an earlier phase only for
changed input or an explicit user request. The interview follows this sequence:
1. Receptionist (session setup, document intake)
2. Behavioural Interviewer
3. Technical Interviewer
4. Summariser
Routing rules (apply in order; the latest user request takes priority over earlier messages):
- If the user wants to stop or finish, hand off to "summariser" immediately.
Do not restart intake or ask another interview question.
- If the latest message supplies a new or replacement resume or job description, hand off to
"receptionist" first, even if it also asks to begin practice. A URL alone is not parsed document text.
- If the user explicitly requests a specific phase, honour that request.
- If the user is answering the latest technical question, hand off to "technical_interviewer".
- If the user is answering the latest behavioural question, hand off to "behavioural_interviewer".
- If the receptionist has NOT yet collected the resume and job description
→ hand off to "receptionist"
- If document intake is complete and behavioural interview has NOT started
→ hand off to "behavioural_interviewer"
- If behavioural interview is complete and technical interview has NOT started
→ hand off to "technical_interviewer"
- If technical interview is complete
→ hand off to "summariser"
- If unclear, ask the user to clarify what they'd like to do.
A specialist may return to you for changed input or an early finish.
Read the handoff reason and apply the routing rules; a return does not always mean a phase is complete.
Always be brief and supportive. Let the specialists do the detailed work.
""");

Change the technical interviewer’s final step to hand off directly to the summary:

Finish technical practice with a summary

File to edit: src/InterviewCoach.Agent/AgentDelegateFactory.cs

Function to edit: CreateHandOffWorkflow

Replace the matching block with the code below. Open "Current code" to locate the block in your file.

Current code
Current code
// --- Technical Interviewer Agent ---
var technicalAgent = CreateProviderAgent(
services: sp,
name: "technical_interviewer",
description: "Conducts the technical interview and provides feedback.",
instructions: """
You are the Technical Interviewer for an AI Interview Coach system.
Your job is to conduct the technical part of the interview.
Process:
1. Fetch the interview session record to get the resume and job description context.
2. Ask technical questions one at a time, tailored to the skills in the job description and resume.
3. After each answer, provide constructive feedback, correct any misconceptions, and suggest improvements.
4. Before each update, call get_interview_session and preserve all six resume/job fields.
Set Transcript to ONLY the new questions, answers, and analysis to append; never resend old text.
5. After a few questions (typically 3-5), ask if the user wants to continue or wrap up.
6. If the user wants to finish, give brief feedback and acknowledge the end of practice.
Do not ask another question or hand off. Only hand off to "triage" for an unexpected request.
Focus on practical, real-world scenarios relevant to the job.
Always maintain a supportive and encouraging tone.
""",
tools: [.. interviewDataTools]);

Updated code
// --- Technical Interviewer Agent ---
// Saves technical feedback before transferring to the summariser.
var technicalAgent = CreateProviderAgent(
services: sp,
name: "technical_interviewer",
description: "Conducts the technical interview and provides feedback.",
instructions: """
You are the Technical Interviewer for an AI Interview Coach system.
Your job is to conduct the technical part of the interview.
Process:
1. Fetch the interview session record to get the resume and job description context.
2. Ask technical questions one at a time, tailored to the skills in the job description and resume.
3. After each answer, provide constructive feedback, correct any misconceptions, and suggest improvements.
4. Before each update, call get_interview_session and preserve all six resume/job fields.
Set Transcript to ONLY the new questions, answers, and analysis to append; never resend old text.
5. After a few questions (typically 3-5), ask if the user wants to continue or wrap up.
6. When done, hand off directly to "summariser" to generate the interview summary.
Only hand off to "triage" if the user wants to do something unexpected.
Focus on practical, real-world scenarios relevant to the job.
Always maintain a supportive and encouraging tone.
""",
tools: [.. interviewDataTools]);

Now define the summariser. It receives InterviewData tools so it can read the transcript, append its summary, and call completion. These are separate operations, and the instructions must preserve that order:

Define summary generation and record completion

File to edit: src/InterviewCoach.Agent/AgentDelegateFactory.cs

Function to edit: CreateHandOffWorkflow

Replace the matching block with the code below. Open "Current code" to locate the block in your file.

Current code
Current code
// Connect the four available agents.

Updated code
// --- Summariser Agent ---
// Generates the final interview summary.
// Hands back to Triage only after summary — this is the end of the sequence.
var summariserAgent = CreateProviderAgent(
services: sp,
name: "summariser",
description: "Produces the final interview summary and recommendations.",
instructions: """
You are the Summariser for an AI Interview Coach system.
Your job is to generate a comprehensive interview summary.
Process:
1. Fetch the interview session record to get the full transcript. Also review the latest user
message for a final answer that has not been saved yet, and include that new answer in the update.
2. Generate a summary that includes:
- Overview of the interview session
- Key highlights and strong answers
- Areas for improvement
- Specific recommendations for the user
- Overall readiness assessment
3. Preserve all six resume/job fields and call update_interview_session with ONLY the new summary
in Transcript. The repository appends it; never send the stored transcript again.
4. Call complete_interview_session with the same ID. Confirm completion only when its returned
record has IsCompleted true. Report tool failures honestly.
5. Present the summary to the user.
6. Hand off back to triage in case the user wants to do anything else.
Always maintain a supportive and encouraging tone.
""",
tools: [.. interviewDataTools]);
// Connect the four available agents.

Finish the edit group by replacing the four-agent builder with the full graph:

Connect the completed workflow

File to edit: src/InterviewCoach.Agent/AgentDelegateFactory.cs

Function to edit: CreateHandOffWorkflow

Replace the matching block with the code below. Open "Current code" to locate the block in your file.

Current code
Current code
// Connect the four available agents.
#pragma warning disable MAAIW001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
var workflow = AgentWorkflowBuilder
.CreateHandoffBuilderWith(triageAgent)
.WithHandoffs(triageAgent, [receptionistAgent, behaviouralAgent, technicalAgent])
.WithHandoffs(receptionistAgent, [behaviouralAgent, triageAgent])
.WithHandoffs(behaviouralAgent, [technicalAgent, triageAgent])
.WithHandoff(technicalAgent, triageAgent)
.Build();
#pragma warning restore MAAIW001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
return workflow.SetName(key);

Updated code
// Build the handoff workflow
// Normal phase changes follow the specialist chain.
// Each specialist can return to triage for a changed request.
#pragma warning disable MAAIW001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
var workflow = AgentWorkflowBuilder
.CreateHandoffBuilderWith(triageAgent)
.WithHandoffs(triageAgent, [receptionistAgent, behaviouralAgent, technicalAgent, summariserAgent])
.WithHandoffs(receptionistAgent, [behaviouralAgent, triageAgent])
.WithHandoffs(behaviouralAgent, [technicalAgent, triageAgent])
.WithHandoffs(technicalAgent, [summariserAgent, triageAgent])
.WithHandoff(summariserAgent, triageAgent)
.Build();
#pragma warning restore MAAIW001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
return workflow.SetName(key);

The usual interview follows the specialist chain. Triage can also select any specialist, and each specialist can return to triage for a changed request.

The specialist handoff routes

Triage can select any specialist. The usual interview follows the specialist chain; each specialist can also return control to triage.

  1. Triage. Starts the workflow. It can hand off to the receptionist, behavioural interviewer, technical interviewer, or summariser.
  2. Receptionist. Collects the resume and job description using MarkItDown and InterviewData. It can hand off to the behavioural interviewer or triage.
  3. Behavioural interviewer. Asks behavioural questions and saves feedback. It can hand off to the technical interviewer or triage.
  4. Technical interviewer. Asks technical questions and saves feedback. It can hand off to the summariser or triage.
  5. Summariser. Writes the final feedback, completes the interview record, and can hand control back to triage.

All eleven handoff routes are shown. Dashed arrows return to triage. The agents take turns handling the conversation, using the same model deployment.

Why keep these eleven edges? Direct phase transitions avoid asking triage to choose again after every specialist. Return routes still let the user change direction. The graph supports both ordinary progress and an early finish.

A hub-only graph would add a triage decision between phases. A chain without return routes would restrict changed requests. Neither design is universally wrong. Choose routes for the interactions the application needs.

The graph permits transfers without forcing a fixed sequence. If the next operation must always be the same, ordinary code or a sequential workflow may be simpler.

Check your understandingThe summariser saved its feedback with update_interview_session. What must happen before it claims the interview is complete?

From the working project root:

Terminal window
aspire stop --apphost ./apphost.cs
dotnet build InterviewCoach.slnx
aspire start --apphost ./apphost.cs

In the Aspire dashboard, open webui and select New chat. The page displays Session ID above the conversation. Keep the display you added in Chapter 11. DevUI shows the workflow graph. Use WebUI for this conversation. Send:

My fictional resume says I build C# APIs and review integration tests.
The job is backend developer. Save those inputs.
Let's do one behavioural question and one technical question.

Answer the behavioural question, request technical practice, and answer that question. Then ask the coach to finish and save a summary.

In DevUI’s graph, locate the permitted transfer from technical_interviewer to summariser. To check the saved result, copy the Session ID shown above the conversation. In the mcp-interview-data logs, find the lookup, update, and Completed interview session entries for that ID.

Find the same ID in Cosmos Data Explorer. Transcript should include feedback about your answers and the final summary. IsCompleted should be true. The summary update must preserve document fields and append only new text. Select New chat for another run.

The saved record proves the data operations. It does not identify every agent that ran, because several roles share InterviewData tools. Use agent execution telemetry when you need that evidence. DevUI’s static graph shows what is allowed, not what happened in this conversation.

All eleven permitted handoffs
Active agent Allowed destinations
triage receptionist, behavioural_interviewer, technical_interviewer, summariser
receptionist behavioural_interviewer, triage
behavioural_interviewer technical_interviewer, triage
technical_interviewer summariser, triage
summariser triage

The graph permits these transfers. The active agent chooses one using its instructions and conversation context. We’ll exercise an early-finish route in the debugging lesson.

Chapter 12 · Specialist workflows

Next: 13. Find and fix a failed step