Skip to main content

Microsoft Agent Framework–Building a multi-agent workflow with DevUI in .NET

Yesterday, I created a minimal .NET project with DevUI and registered a couple of standalone agents. That gets you surprisingly far for interactive testing. But real business scenarios quickly outgrow a single agent: you need data flowing through multiple specialized steps, decisions being made along the way, and a clear picture of the whole pipeline.

That's what workflows are for. In this post, we'll build a content review pipeline as a concrete example — a Writer agent drafts a response, a Reviewer agent critiques it, and a deterministic formatting step finalizes the output. All of it visualized in DevUI.

Agents vs Workflows — the key distinction

The Agent Framework docs put it cleanly: an agent is LLM-driven and dynamic — it decides which tools to call and in what order, based on the conversation. A workflow is a predefined graph of operations, some of which may be AI agents, but the topology is explicit and deterministic. You decide exactly what runs after what.

When should you choose a workflow over a single agent with tools? A few signals:

  • You need multiple agents with different system prompts to collaborate in a fixed order
  • You have deterministic steps (validation, formatting, API calls) interleaved with LLM steps
  • You need checkpointing, fault tolerance, or human-in-the-loop approval between steps
  • You want type-safe message contracts between pipeline stages

Remark: The key message is to remain pragmatic: if you can write a regular function to handle the task, do that. Use an agent when you need LLM reasoning. Use a workflow when you need explicit control over a multi-step process.

Core Workflow concepts

Three concepts make up the mental model:

Executors are the processing nodes. Each executor receives typed messages, does work (LLM call, API call, data transform), and emits typed output messages. The recommended way to define one is a partial class that inherits from Executor, with handler methods marked [MessageHandler]. The partial keyword enables compile-time source generation for handler registration.

Edges define the connections between executors — which executor's output feeds which other executor's input. They can be simple direct connections, or conditional branches that route based on message content.

WorkflowBuilder ties executors and edges into a directed graph. Once built, you execute it with InProcessExecution.RunStreamingAsync() or RunAsync().

What we're building

A content review pipeline with three stages:

1. Writer executor (AI agent) — takes a topic prompt and drafts a short paragraph

2. Reviewer executor (AI agent) — receives the draft and returns concise actionable feedback

3. Formatter executor (deterministic) — wraps the final output in a structured response envelope

The data flow looks like this:


Step 1: Install extra packages

On top of the packages from the previous post, you need the workflows package:


        dotnet add package Microsoft.Agents.AI.Hosting --prerelease
	dotnet add package Microsoft.Agents.AI.DevUI --prerelease
        dotnet add package Microsoft.Agents.AI.Workflows --prerelease
        dotnet add package OllamaSharp

Step 2: Define the Executors

WriterExecutor.cs

The Writer executor is a thin wrapper around a ChatClientAgent. It receives a string (the user's topic), runs the agent, and returns the draft as a string that gets forwarded to the next executor automatically.

ReviewerExecutor.cs

The Reviewer receives the draft string and returns a string containing its feedback. Same pattern, different agent instructions.

FormatterExecutor.cs

The Formatter is a purely deterministic executor — no AI, just C# code. It calls context.YieldOutputAsync() to emit the final result back to the workflow caller.

Step 3: Wire it up in Program.cs

Now the workflow is assembled in Program.cs alongside the DevUI registration. The key difference from the single-agent setup is that instead of calling builder.AddAIAgent(), we construct agents manually so we can pass them into executor instances, then hand the workflow to the hosting layer.

Step 3 — Run and Explore in DevUI

dotnet run

In the DevUI sidebar you'll now see ContentReviewPipeline listed as a workflow entry rather than an agent. Click on Configure and run, type a topic — "the benefits of electric vehicles" works well — and hit Run workflow.

Unfortunately, that didn't work and resulted in an error. It turns out that using mixed workflows in C# doesn't work yet in DevUI. 

However, an agent only workflow does work. So, let's update our example and change it into an agent only workflow:

Restart the application, click on Configure and run again, type a topic — "the benefits of electric vehicles" — and hit Run workflow.

You'll see each executor fire in sequence. Because agents are wrapped as executors in the workflow, the reasoning trail shows the Writer's output, then the Reviewer's feedback, the full chain of thought, step by step.

Tip: DevUI's workflow visualization is one of its strongest features. Unlike the single-agent view, you can see the executor graph on the left and watch messages propagate through it in real time, which makes it easy to spot where in the pipeline things are going wrong.

Calling the workflow programmatically

If you want to call the workflow directly from code (outside of DevUI), you can use the RunAsync method:


Conclusion

Switching from a single agent to a workflow in the Agent Framework is mostly additive. You keep the same setup from part one and add executor classes plus a WorkflowBuilder call. 

Unfortunately, the DevUI backend part for ASP.NET Core can’t handle all type of workflows yet, so we’ll have to wait for an update. When that happens, I’ll write a follow-up post. Pinky promise!

Meanwhile, you can explore my working end-to-end example here: wullemsb/DevUIExample at workflows

More information

Microsoft Agent Framework Workflows | Microsoft Learn

Microsoft Agent Framework Workflows - Executors | Microsoft Learn

wullemsb/DevUIExample at workflows


Popular posts from this blog

Podman– Command execution failed with exit code 125

After updating WSL on one of the developer machines, Podman failed to work. When we took a look through Podman Desktop, we noticed that Podman had stopped running and returned the following error message: Error: Command execution failed with exit code 125 Here are the steps we tried to fix the issue: We started by running podman info to get some extra details on what could be wrong: >podman info OS: windows/amd64 provider: wsl version: 5.3.1 Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM Error: unable to connect to Podman socket: failed to connect: dial tcp 127.0.0.1:2655: connectex: No connection could be made because the target machine actively refused it. That makes sense as the podman VM was not running. Let’s check the VM: >podman machine list NAME         ...

Azure DevOps/ GitHub emoji

I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.

VS Code Planning mode

After the introduction of Plan mode in Visual Studio , it now also found its way into VS Code. Planning mode, or as I like to call it 'Hannibal mode', extends GitHub Copilot's Agent Mode capabilities to handle larger, multi-step coding tasks with a structured approach. Instead of jumping straight into code generation, Planning mode creates a detailed execution plan. If you want more details, have a look at my previous post . Putting plan mode into action VS Code takes a different approach compared to Visual Studio when using plan mode. Instead of a configuration setting that you can activate but have limited control over, planning is available as a separate chat mode/agent: I like this approach better than how Visual Studio does it as you have explicit control when plan mode is activated. Instead of immediately diving into execution, the plan agent creates a plan and asks some follow up questions: You can further edit the plan by clicking on ‘Open in Editor’: ...