Skip to main content

Microsoft Agent Framework - Getting started with DevUI in .NET

If you've been exploring the Microsoft Agent Framework, you've probably seen the Python DevUI example showcased prominently in the docs. DevUI is a fantastic inner-loop tool — it lets you visually inspect your agents: their messages, reasoning steps, tool calls, and conversation state, all in a browser dashboard while you develop locally. Think of it as Swagger UI, but for AI agents.

The problem? When I went looking for a .NET / C# equivalent, I couldn't find one. The official Microsoft Learn page for DevUI samples simply said: "DevUI samples for C# are coming soon." — Not great when you're trying to ship.

So I built one. This post walks through a complete, working .NET Core example using Microsoft Agent Framework 1.0, with DevUI wired up and ready to go.

What is DevUI?

DevUI is a lightweight developer dashboard shipped as part of the Microsoft Agent Framework. It is not intended for production — it's a local dev tool, similar in spirit to what Redux DevTools does for React or what Aspire's dashboard does for distributed .NET apps.

When you run your agent app with DevUI enabled, you get a browser UI that shows:

  • The agent profile — name, instructions, registered tools
  • The invocation request — what was sent to the agent
  • The reasoning trail — intermediate steps and internal messages
  • Tool calls — which functions were invoked and with what arguments
  • OpenTelemetry traces — if you have tracing enabled
Remark: The DevUI functionality turns out not be fully functional yet. I encountered a lot of use cases where it refused to work. So feel free to give it a try but there will be dragons...

How DevUI Works in .NET

For .NET, DevUI is exposed through the Microsoft.Agents.AI.DevUI NuGet package. It integrates directly into ASP.NET Core's middleware pipeline via a single method call:

app.MapDevUI()

Internally, it hooks into the same OpenAI-compatible Responses and Conversations APIs that the agent runtime exposes, so every agent message flows through it automatically — no extra instrumentation code required.

Once running, navigate to /devui in your browser, and you'll see all registered agents listed in the left sidebar. Click one, send a message, and watch the chain-of-thought unfold in real time.

Prerequisites

Before writing any code, make sure you have:

  • .NET 10 SDK or later (the example targets net10.0)
irm https://ollama.com/install.ps1 | iex

Project setup

Step 1: Create the project

Create a new minimal ASP.NET Core web application. This is the host that DevUI will attach to.

dotnet new web -n AgentFramework.DevUI.Example
cd AgentFramework.DevUI.Example

Step 2: Install NuGet packages

You need four packages in total: the Agent Framework hosting layer, DevUI itself, the hosting OpenAI connector, and the OpenAI client SDK.


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

Step 3: The code

Here is the complete Program.cs for this example. It registers a chat client backed by Foundry Local, defines two agents with different personas, enables the OpenAI-compatible response endpoints (required by DevUI), and maps the DevUI dashboard.

What each step does:

Step 1 — Chat client: We create an IChatClient backed by GitHub Models using the OpenAI client SDK. The AsIChatClient() extension bridges the OpenAI SDK to Microsoft.Extensions.AI's provider-agnostic interface. Swapping to Azure OpenAI or any other supported provider is a one-line change.

Step 2 — Agents: builder.AddAIAgent() registers a named agent with a system prompt (instructions). You can register as many agents as you like. Each will appear as a separate entry in the DevUI sidebar.

Step 3 & 4 — Responses + Conversations APIs: These are the OpenAI-compatible API endpoints that Agent Framework exposes. DevUI hooks into these to intercept all agent traffic. They must be registered before calling MapDevUI().

Step 5 — DevUI: app.MapDevUI() mounts the dashboard at /devui. The IsDevelopment() guard ensures it is never available in staging or production.

Step 4: Running the app

Launch the app in Development mode (the default when using dotnet run):


dotnet run
# Output:
# Now listening on: https://localhost:5001
# Now listening on: http://localhost:5000

Then open https://localhost:5001/devui in your browser. You should see the Weather bot agent listed in the dropdown at the top:

You can now interact with the agent:

Click WeatherBot, type "What's the weather in Brussels?" in the input box and hit Send. 


The right panel will show the full execution trace: the user message, response parts and the final response:


Extending the example

Adding tools

Tools are where agents get genuinely useful. You register them with AIFunctionFactory and pass them during agent registration. DevUI will show every tool call with its arguments and return value in the reasoning trail.

Exploring tools

Tool call tracing is one of DevUI's most valuable features during development. You can see exactly which tool was called, what arguments were passed, and what was returned — all without adding a single log statement.


Troubleshooting

404 at /devui

Make sure you have called both app.MapOpenAIResponses() and app.MapOpenAIConversations() before app.MapDevUI(). All three are required.

Also verify you are running in Development mode (ASPNETCORE_ENVIRONMENT=Development). In Production, the IsDevelopment() guard prevents DevUI from mounting.

Package not found

The Agent Framework packages are currently prerelease. Make sure you're passing --prerelease to dotnet add package or explicitly specify the version string in your .csproj.

Conclusion

Microsoft Agent Framework 1.0 shipped in April 2026 with stable APIs and first-class .NET support, but the C# DevUI story was underdocumented. This post fills that gap with a working end-to-end example.

The setup comes down to 3 packages, five lines of registration code, and one route mapping. From there, you get a functional local debugging dashboard that dramatically shortens the write-run-fix loop for agent development in .NET. However, it is not yet fully supported in .NET so expect some issues and unsupported scenarios.

The code for this example is straightforward to extend. Have fun!

More information

microsoft/agent-framework: A framework for building, orchestrating and deploying AI agents and multi-agent workflows with support for Python and .NET.

Ollama

Agent Framework documentation | Microsoft Learn

DevUI Overview | Microsoft Learn

wullemsb/DevUIExample: C# example for using DevUI in Agent Framework

Popular posts from this blog

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.

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         ...

Cleaner switch expressions with pattern matching in C#

Ever find yourself mapping multiple string values to the same result? Being a C# developer for a long time, I sometimes forget that the C# has evolved so I still dare to chain case labels or reach for a dictionary. Of course with pattern matching this is no longer necessary. With pattern matching, you can express things inline, declaratively, and with zero repetition. A small example I was working on a small script that should invoke different actions depending on the environment. As our developers were using different variations for the same environment e.g.  "tst" alongside "test" , "prd" alongside "prod" .  We asked to streamline this a long time ago, but as these things happen, we still see variations in the wild. This brought me to the following code that is a perfect example for pattern matching: The or keyword here is a logical pattern combinator , not a boolean operator. It matches if either of the specified pattern...