The approval step actually blocks.
Multi-agent workflow
A triage agent that hands the customer to a warranty specialist or a refund specialist, built on Microsoft Agent Framework, where the refund tool cannot run until a supervisor says yes, even if the process restarts while it waits.
- build time
- 6 to 8 hours
- cost
- Under $8 if torn down the same day3
- services
- Microsoft Agent Framework, Foundry Agent Service, Azure Functions, Cosmos DB, Entra ID, Application Insights
- assumes
- Project 01. The warranty specialist is that agent, unchanged.
- exams
- Overlaps AI-103, AI-200
- vocabulary
- Orchestration, handoff, specialist, tool approval, request info, checkpoint, human-in-the-loop
The problem
The Warranty Desk now gets asked for refunds. One agent doing warranty lookups, policy quotes and refunds is one agent with too many instructions and too much power.
The head of support wants three things that are, at first, hard to have together. Customers should talk to one thing, not pick a department. Refunds over fifty dollars need a supervisor to approve them, and "approve" has to mean the money cannot move without the click. And the approval has to survive lunch: if the supervisor comes back in an hour and the service restarted in between, the pending refund is still pending, not lost and not silently paid.
- definition
- Handoff. One agent passing the conversation to another, with context, and control coming back to the customer when the receiving agent has nothing more to hand off. In Agent Framework this is an orchestration you build, not a prompt you hope works.
The architecture
Three agents, one conversation, and a tool that waits for a person.
- Ask. The customer asks for a refund in plain words.
- Triage. The triage agent decides refund, not warranty, and hands off a summary.
- Or warranty. A coverage question would have gone to the warranty specialist, Project 01's agent.
- Compute. The refund specialist reads the order and computes the eligible amount.
- Gate. The refund tool requires approval; it emits a request instead of running.
- Approve. A supervisor, in a separate role, sees the request and approves or declines.
- Act. Only now does the Azure Function issue the refund, once, keyed on the request ID.
- Survive. The pending request lived in Cosmos DB checkpoints; a restart re-emits it.
| Job | AWS version | This build | Same idea? |
|---|---|---|---|
| Orchestration | Bedrock multi-agent collaboration | Agent Framework handoff orchestration1 | Yes. Here the handoff is explicit code |
| Specialists | Collaborator agents | Foundry agents, one per job | Yes |
| Approval gate | Step Functions wait for callback | Tool approval, approval_mode="always_require" | Yes. Here it is a property of the tool |
| Durable wait | Step Functions state | Workflow checkpoints in Cosmos DB | Yes |
| Refund action | Lambda | Azure Functions, managed identity | Yes |
The build
In this order. Step 6 is the one that makes "human in the loop" mean something; test it by pulling the plug.
-
Three agents
Triage: decides warranty or refund, nothing else. Warranty specialist: the Project 01 agent, untouched. Refund specialist: reads the order, computes the eligible amount, and has one tool,
Each agent answers in the playground on its own, with its own instructions file in the repo.issue_refund(orderId, amount). -
Handoff orchestration
With Agent Framework, build a handoff workflow: triage can hand to either specialist; specialists can hand back to triage. When an agent replies without handing off, control returns to the customer.
"My dishwasher broke and I want my money back" reaches the refund specialist; "is it still covered" reaches the warranty specialist; both come back to the customer without a second prompt from you. -
The refund tool, gated
Mark
Ask for a $120 refund. The tool does not run; the response carries a pending function-approval request with the order ID and amount, and your side-effect log stays empty. Verified: in our run the gated tool was never executed. Keep that log; it is the evidence.4issue_refundwithapproval_mode="always_require". When the refund specialist calls it, the workflow emits a function approval request instead of running the tool. -
The supervisor screen
A small page that lists pending approval requests and has Approve and Decline. Approving sends the approval response back into the workflow; the tool runs; the Function issues the refund.
Approve from the screen; the refund Function logs one call with the right amount. Decline; it logs nothing and the customer is told. -
The threshold
Refunds under $50 do not need approval. Implement that as code around the tool, not as a sentence in the prompt: the tool decides whether to require approval based on the amount.
$40 refunds run straight through; $60 refunds wait. Tell the model the threshold is $500 in the prompt and confirm it still waits at $60. -
Checkpoints, then pull the plug
Add checkpoint storage backed by Cosmos DB. Ask for a $120 refund, see the pending request, then kill the process. Start it again and restore from the last checkpoint.
The pending request is re-emitted after restart. Approve it now; exactly one refund is issued, not zero and not two. -
Identity
The refund Function accepts only the workflow's managed identity. The supervisor screen requires the supervisor role in Entra ID; a support agent role can see requests but not approve.
Signed in as a support agent, the Approve control is not there and the API says 403. -
Trace the handoffs
Turn on tracing. Run a conversation that goes triage to refund to approval to Function and read it in Application Insights as one trace.
One trace shows three agents, one approval wait, and one tool call, in order, with timings. -
Tear it down
azd down
Then delete the Cosmos account by hand if you created it outside the template.
The resource group is empty. Today's cost is under $8.
Where it breaks
Cause each one on purpose. Multi-agent failures are quiet and expensive.
The trade-offs
- Three agents, or one agent with a longer prompt?
- One agent is simpler until it has the power to refund and the instructions to quote policy in the same context. Splitting gives each agent one job and one set of tools, so the refund specialist cannot quote policy wrong and the warranty specialist cannot move money.
- Handoff, or a fixed sequence?
- A sequential workflow is predictable and cannot route on what the customer said. Handoff routes, and needs a hop limit. Customer conversations route.
- Approval in code, or in the prompt?
- In the prompt, the model decides whether to ask. In code, the tool refuses to run. Money moves on the second kind only.
- Checkpoints, or accept the loss?
- Checkpoints add a store and an idempotency rule. Without them, a restart can drop or duplicate a pending refund. For refunds, that is not a trade-off.
In the interview
"Tell me about a multi-agent system you built."
- decisionTriage plus two specialists with Agent Framework handoff, each agent with one job and one tool set.
- reasonSplitting power: the agent that quotes policy cannot move money.
- watchedHandoff loops; I added a hop limit after seeing one.
"How does the human approval work?"
- decisionThe refund tool requires approval as a property; the workflow emits a request and waits.
- reasonA prompt instruction can be talked out of; a tool gate cannot.
- watchedRestarting the process with a request pending and confirming exactly one refund after approval.
"What if the service restarts while waiting?"
- decisionCheckpoints in Cosmos DB; pending requests are re-emitted on restore.
- reasonA lost approval is a broken promise; a duplicated one is a lost refund.
- watchedThe request ID as the idempotency key on the Function.
Evidence
- One trace
- Triage to refund specialist to approval wait to Function, with timings.
- The plug-pull
- A short recording or three screenshots: pending request, process killed, request re-emitted, one refund.
- The repo
- Three instructions files, the orchestration code, the gated tool, and the supervisor page.
- One sentence for the résumé
- "Built a multi-agent support workflow with Microsoft Agent Framework: triage and specialist handoffs, a tool-level human approval gate for refunds, and durable checkpoints so pending approvals survive restarts without duplicate payments."
Next
Notes
- Checked against Microsoft Learn on 2 September 2026. Agent Framework's handoff orchestration returns control to the user when an agent replies without handing off; tools marked
approval_mode="always_require"emit a function approval request; checkpoints persist pending requests, which are re-emitted on restore. Names may move; the Learn pages win. - Foundry's own workflow agents exist too and are worth knowing; at the time of writing they did not support outbound network isolation, which matters for Project 05. This project builds the orchestration in Agent Framework code so every step is visible.
- "Under $8" assumes serverless Cosmos DB for checkpoints, a Consumption Function, small models, and teardown the same day.
- The approval gate was tested in a real subscription on 3 September 2026 with
agent-framework1.17.0 for Python andgpt-5-mini. With@tool(approval_mode="always_require")the tool never executed and the run surfaced a pending function-approval request; the same tool with only a prompt instruction executed on a claimed supervisor identity in five runs out of five. One thing moved between the docs and the package: the agent class isAgent, notChatAgent, and a conversation isagent.create_session(), notget_new_thread(). Expect that kind of drift and read the package, not just the page.