# AI Agents in .NET: Let's Build Something Smart

> Introducing the Knowledge repository - a hands-on companion for learning how to build AI agents with the Microsoft Agent Framework in C#.

- Published: 2025-12-21
- Author: Sven Scharmentke
- Canonical: https://svnscha.de/posts/ai-agents-dotnet-intro/
- Tags: ai, agents, dotnet, csharp, microsoft-agent-framework, llm, tutorial

---

Welcome to a new blog series about building AI agents in .NET.

Yes, you read that right - I just said `.NET`. Not Python. C#. Curly braces. Strong typing. With drums and trumpets.

Over the coming posts, we'll explore the [Microsoft Agent Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview), build actual agentic systems, and - most importantly - have some fun doing it. This first post sets the stage: why I'm doing this, what we're building, and how to get started with the companion repository.

Here is how to get started.

## Why, You Ask?

Honestly? I got a little restless. Every AI agent tutorial out there follows the same well-worn path:

- *"Build a weather agent!"*  -  Revolutionary stuff. Though I hear windows also exist.
- *"Spam detection with AI!"*  -  Gmail's been doing this since 2004.
- *"Customer service chatbot!"*  -  Oh good, we definitely need more of those.

These examples are useful for learning the basics, but I wanted to build something closer to a real application.

This series is about building agents that are genuinely smart, genuinely fun, or ideally both. No boring examples. No wrapping API calls in agent clothing and calling it intelligent.

As for the language choice - I've always been a C-family person. Python is lovely for what it does, but give me curly braces and strong typing any day. When Microsoft released the Agent Framework for .NET? Yeah, that got me genuinely excited. First-class AI agents in C#. Native support, proper tooling, the whole package.

## The Microsoft Agent Framework

So what exactly are we working with? The framework comes with everything you need to build proper agentic systems:
- Native C# support (obviously)
- A beautiful [DevUI](https://learn.microsoft.com/en-us/agent-framework/user-guide/devui/?pivots=programming-language-csharp) for testing and debugging your agents - still in preview and missing some Python-side features, but it gets the job done
- Built-in patterns for common agentic scenarios (the fun stuff)
- Integration with the broader .NET ecosystem (finally!)

And that's what this blog series is all about.

### About DevUI

Speaking of DevUI - if you head over to Microsoft's documentation and switch to the C# tab, you're greeted with this gem:

> *"DevUI documentation for C# is coming soon. Please check back later or refer to the Python documentation for conceptual guidance."*

Ah yes, the classic "refer to Python" move. You know, the language we *specifically* chose not to use for this series? The irony isn't lost on me. But hey, I'm not bitter - I'm just impressed they managed to ship a working DevUI before the documentation. That's actually kind of bold.

The DevUI is a useful web interface for chatting with agents and inspecting their behavior during development. It does not replace proper tracing with tools such as OpenTelemetry and Jaeger, but it works well for quick iteration and debugging. I will cover observability separately in a later post.

## The Knowledge Repository

To support this series, I've created a companion repository called [Knowledge](https://github.com/svnscha/knowledge). I briefly considered *"AI-Stuff-I-Throw-Together-At-2AM"* but that didn't seem like a good fit. So I thought about it - I'm deepening my own knowledge about AI as I create this series, and hopefully you'll gain some knowledge along the way too. Yeah, let's face it: *Knowledge* is simple. Sometimes simple works.

The repository is structured as a progressive learning path. Each branch builds on the previous one, taking you from zero to building sophisticated agentic systems. Here's what we're working with:

| Branch | Topic | What You'll Learn | Codespace
|--------|-------|-------------------|---|
| `main` | Repository & Hello World Agent | Project setup, DevUI, your first conversational agent | [![Open in Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/svnscha/knowledge/tree/main) |

More branches will be added as the series progresses. And honestly? That Codespaces button is kind of magical - click it, grab a coffee, and come back to a fully configured dev environment. No setup, no dependencies, just ready to go. I still find that ridiculously cool.

Star the repo if you want to follow along!

## Development Environment

You've got two options here - pick whichever fits your workflow.

### Dev Container Setup

First things first: reproducible development environments. The repository includes a `.devcontainer` configuration with:
- .NET 10
- PostgreSQL with pgvector for when we get into embeddings and semantic search
- All the tooling pre-configured

Just open the repo in VS Code, click "Reopen in Container," and you're ready to go. The classic "works on my machine" problem? Solved.

You can also [open it in a Codespace](https://codespaces.new/svnscha/knowledge/tree/main) and work entirely in the browser without a local setup.

### Classic

And for those of you rolling your eyes at all this container and cloud stuff - fair enough. Install the [.NET 10 SDK](https://dotnet.microsoft.com/download), fire up VS Code or Visual Studio, clone the repo, and just go. Sometimes the old ways are the best ways. That said, you'll want to get PostgreSQL with pgvector set up sooner rather than later - we'll need it for embeddings and semantic search in upcoming posts.

## What's on the Main Branch?

![The DevUI in action](/screenshots/2025-12-15-devui-empty.png)

Let me walk you through what you'll find when you clone the repo. The `main` branch sets up everything you need to hit the ground running with AI agent development.


### Project Structure

The solution is organized into two projects:

- **Knowledge** - The main web application that hosts our agents and the DevUI
- **Knowledge.Shared** - Shared configuration, extensions, and utilities

This separation keeps things clean as we add more complexity in future posts.

### Configuration Done Right

One thing I'm particular about is handling configuration properly. In `Knowledge.Shared`, we have a `KnowledgeSettings` class that gives us strongly-typed access to our config values.

The important bits are these two properties:

```cs
public string ApiKey { get; set; } = string.Empty;

public string ApiEndpoint { get; set; } = string.Empty;
```

`ApiKey` is where your OpenAI (or compatible) API key goes. `ApiEndpoint` is optional - leave it empty and we'll hit OpenAI's default endpoint, or set it to point at Azure OpenAI, a local model, whatever you need.

Now, you definitely don't want to hardcode API keys in your source code. That's how keys end up on GitHub and suddenly you're funding a stranger's LLM experiments. Instead, we use [.NET User Secrets](https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets):

```bash
cd src/Knowledge
dotnet user-secrets set "Knowledge:ApiKey" "your-api-key-here"
```

Your key stays on your machine, outside of source control. Sleep well at night.

### Wiring Up the Agent

The following sections walk through `Program.cs` piece by piece.

First, the imports - nothing too surprising here:

```cs
using System.ClientModel;
using Knowledge.Shared.Extensions;
using Microsoft.Agents.AI.DevUI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;
using OpenAI;
```

We're pulling in the Agent Framework (`Microsoft.Agents.AI.*`), Microsoft's AI abstractions (`Microsoft.Extensions.AI`), and the official OpenAI client. Standard .NET web app stuff otherwise.

Next, we create our builder and call into our configuration extension:

```cs
var builder = WebApplication.CreateBuilder(args);

builder.ConfigureKnowledgeDefaults((settings, logger) =>
{
    // ...
});
```

`ConfigureKnowledgeDefaults` is a helper method in our shared project. It handles loading `appsettings.json`, binding it to our `KnowledgeSettings` type, and then gives us a callback where we can access both the settings and a logger. This keeps `Program.cs` clean while still giving us full control.

Inside that callback, we set up OpenAI. First, a sanity check:

```cs
if (string.IsNullOrWhiteSpace(settings.ApiKey))
{
    logger.LogWarning("No API key configured. Set Knowledge:ApiKey in user secrets.");
}
```

Better to warn loudly than fail silently.

Then we create the OpenAI client options. If a custom endpoint is configured, we use it:

```cs
var options = new OpenAIClientOptions();

if (!string.IsNullOrEmpty(settings.ApiEndpoint))
{
    options.Endpoint = new Uri(settings.ApiEndpoint);
}
```

This is what lets you swap between OpenAI, Azure OpenAI, or even a local model running through something like Ollama with an OpenAI-compatible API.

Now we create the actual client and register it with dependency injection:

```cs
var client = new OpenAIClient(new ApiKeyCredential(settings.ApiKey), options);

builder.Services.AddChatClient(client.GetChatClient("gpt-4.1").AsIChatClient());
```

`GetChatClient("gpt-4.1")` gets us a chat client for that specific model. `.AsIChatClient()` wraps it in Microsoft's `IChatClient` abstraction, which is what the Agent Framework expects. Using this abstraction means we could swap out OpenAI for any other provider without changing our agent code.

And finally - the actual agent registration:

```cs
builder.AddAIAgent("Knowledge", "You are a helpful agent named Knowledge.");
```

That's it. One line. We give it a name and a system prompt, and the framework handles the rest. We'll make this more sophisticated in future posts, but for a "hello world" agent, this is all you need.

### Finishing the Pipeline

After our configuration callback, we register a few more services:

```cs
builder.Services.AddOpenAIResponses();
builder.Services.AddOpenAIConversations();
```

These set up the Agent Framework's handlers for OpenAI's responses and conversations API patterns.

Then we build the app and configure the HTTP pipeline:

```cs
var app = builder.Build();

app.ConfigureKnowledgePipeline();
```

`ConfigureKnowledgePipeline` is another shared helper - it sets up logging, error handling, and other middleware that we'll want across all our experiments.

Finally, we map our endpoints:

```cs
app.MapOpenAIResponses();
app.MapOpenAIConversations();
app.MapDevUI();

app.MapGet("/", () => Results.Redirect("/devui/"));

app.Run();
```

`MapOpenAIResponses()` and `MapOpenAIConversations()` expose endpoints that follow OpenAI's API patterns. `MapDevUI()` enables the Agent Framework's built-in developer interface.

That last `MapGet` just redirects the root URL to the DevUI. Because when you're developing agents, that's where you want to be.

### Running the Application

Once configured, getting started is simple:

```bash
dotnet run --project src/Knowledge
```

Navigate to `http://localhost:5000/devui` and you'll see the DevUI - a beautiful interface for interacting with your agents, inspecting their reasoning, and debugging when things inevitably go sideways.

## Summary

We've covered a lot of ground in this introductory post. You now have:
- A companion repository with a reproducible dev container setup
- A working "hello world" agent using the Microsoft Agent Framework
- Proper configuration with user secrets (no API keys in source control!)
- The DevUI for testing and debugging your agents

The foundation is solid. Now comes the fun part.

## Next Steps

We've got the foundation in place - a working agent, DevUI, proper configuration. But let's be real: a "hello world" agent isn't going to impress anyone, least of all ourselves.

Next, I will add tools so the agent can perform actions, explore multi-agent scenarios, and use PostgreSQL with pgvector for embeddings and semantic search. A later post will also add proper observability.

But first things first. Step by step.

If you're a .NET developer who's been watching the AI agent space from the sidelines, wondering when C# would get some love - welcome. If you're just someone who's bored of the same old tutorials and wants to see something different - also welcome.

Clone the repo, star it if you're feeling generous, and let's build something that's actually worth building.

See you in the next post. 🚀
