
Learn how to build AI agents in C# using Semantic Kernel. Step-by-step tutorial with runnable code, best practices, and pitfalls. Start building today!
Building AI agents in C# is no longer the exclusive territory of Python developers. With Microsoft's Semantic Kernel, .NET engineers can now create autonomous, task-solving agents that reason, call tools, and complete multi-step workflows—all in the language and ecosystem they already know. In this tutorial, you'll learn exactly how to build AI agents in C# using Semantic Kernel, from your first "hello world" agent to production-grade patterns used in real applications.
Whether you're a beginner searching for "how to build an AI agent," an intermediate developer looking for Semantic Kernel best practices, or a senior engineer exploring advanced autonomous agent design in C#, this guide walks through the concepts, the code, and the pitfalls to avoid.
What Are AI Agents in C#?
An AI agent is a program that uses a large language model (LLM) as its reasoning engine to decide what to do next. Unlike a simple chatbot that answers a single question, an agent can plan, invoke external tools (functions, APIs, databases), observe the results, and loop until a goal is achieved. This "reason → act → observe" cycle is what makes an agent autonomous.
Semantic Kernel is Microsoft's open-source SDK for orchestrating LLMs with your own code. It sits between your C# application and models like Azure OpenAI, OpenAI, or local models, and gives you three core building blocks:
- Kernel — the central dependency-injection container that wires up models, plugins, and services.
- Plugins (functions) — native C# methods the agent can call to take real-world actions.
- Agents & planners — the layer that lets the model choose which functions to invoke, in what order, to solve a task.
The reason C# is a strong choice for building AI agents is type safety and enterprise integration. Your agent's tools are strongly typed methods, so the whole pipeline—from LLM output to database call—benefits from compile-time checks, dependency injection, and the mature .NET hosting ecosystem.
Setting Up Semantic Kernel in .NET
Start by creating a console project and adding the Semantic Kernel NuGet package. Everything below targets .NET 8 and the current 1.x line of Semantic Kernel.
// Terminal commands
// dotnet new console -n AgentDemo
// cd AgentDemo
// dotnet add package Microsoft.SemanticKernel
Next, build a Kernel and connect it to a chat completion model. Never hard-code API keys—read them from environment variables or user secrets. This is one of the most common security pitfalls when building AI agents in C#.
using Microsoft.SemanticKernel;
var builder = Kernel.CreateBuilder();
// Option A: OpenAI
builder.AddOpenAIChatCompletion(
modelId: "gpt-4o",
apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY")!);
// Option B: Azure OpenAI
// builder.AddAzureOpenAIChatCompletion(
// deploymentName: "gpt-4o",
// endpoint: Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!,
// apiKey: Environment.GetEnvironmentVariable("AZURE_OPENAI_KEY")!);
Kernel kernel = builder.Build();
At this point you have a working kernel. The magic of an autonomous agent comes from giving the model tools and letting it decide when to use them.
Building Your First Autonomous Agent
Step 1: Create a Plugin (the Agent's Tools)
A plugin is just a C# class with methods decorated with [KernelFunction]. The [Description] attributes are critical—they are the only way the LLM understands what each tool does and when to call it. Treat these descriptions as the agent's instruction manual.
using System.ComponentModel;
using Microsoft.SemanticKernel;
public class WeatherPlugin
{
[KernelFunction]
[Description("Gets the current temperature in Celsius for a given city.")]
public string GetTemperature(
[Description("The city name, e.g. London")] string city)
{
// In production, call a real weather API here.
return city.ToLower() switch
{
"london" => "14",
"sydney" => "23",
"toronto" => "19",
_ => "20"
};
}
[KernelFunction]
[Description("Recommends clothing based on a temperature in Celsius.")]
public string RecommendClothing(
[Description("Temperature in Celsius")] int celsius)
=> celsius < 15 ? "Wear a warm jacket." : "A t-shirt is fine.";
}
Step 2: Enable Automatic Function Calling
This is the heart of an autonomous agent. By setting FunctionChoiceBehavior.Auto(), you tell Semantic Kernel to let the model call your functions on its own, feed the results back into the conversation, and continue reasoning until it produces a final answer.
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
kernel.Plugins.AddFromType<WeatherPlugin>();
var chat = kernel.GetRequiredService<IChatCompletionService>();
var settings = new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
var history = new ChatHistory();
history.AddUserMessage(
"I'm in London today. What should I wear?");
var result = await chat.GetChatMessageContentAsync(
history, settings, kernel);
Console.WriteLine(result.Content);
// The agent autonomously calls GetTemperature("London"),
// then RecommendClothing(14), then answers:
// "It's 14°C in London, so wear a warm jacket."
Notice what happened: you never told the code to call GetTemperature then RecommendClothing. The model planned that sequence itself. That is the difference between a scripted workflow and a genuine AI agent.
Using the Agent Framework for Persistent Agents
For more structured scenarios, Semantic Kernel offers a dedicated Agent Framework via the ChatCompletionAgent class. It lets you give an agent a persistent name, instructions (its "system prompt"), and a reusable identity—ideal when you're building multiple specialized agents that collaborate.
using Microsoft.SemanticKernel.Agents;
using Microsoft.SemanticKernel.ChatCompletion;
using Microsoft.SemanticKernel.Connectors.OpenAI;
ChatCompletionAgent travelAgent = new()
{
Name = "TravelAssistant",
Instructions =
"You are a concise travel assistant. Use the available " +
"tools to check weather and give clothing advice. " +
"Always state the temperature you found.",
Kernel = kernel,
Arguments = new(new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
})
};
var thread = new ChatHistoryAgentThread();
await foreach (var response in travelAgent.InvokeAsync(
"Packing for Sydney tomorrow — what do I wear?", thread))
{
Console.WriteLine(response.Message.Content);
}
The Agent Framework shines when you build multi-agent systems: for example, a "researcher" agent that gathers data and a "writer" agent that formats it, coordinated by an orchestration layer. Each agent has its own instructions and tool set but shares the same kernel infrastructure.
AI Agent Best Practices in C#
Once you move beyond demos, the following best practices separate reliable production agents from fragile prototypes.
- Write descriptions for the model, not for humans. The
[Description]text is the agent's decision-making input. Ambiguous descriptions cause the model to call the wrong tool. Be explicit about inputs, outputs, and units. - Keep functions small and single-purpose. One tool = one clear action. Fine-grained functions give the model more precise control and produce more predictable plans.
- Set a maximum iteration limit. An autonomous loop can spiral. Guard against runaway tool-calling by capping turns and adding timeouts.
- Validate all LLM-supplied arguments. Treat parameters the model passes to your functions as untrusted input—validate ranges, sanitize strings, and never pass them straight into SQL or shell commands.
- Use dependency injection. Register the kernel and plugins in your
IServiceCollectionso agents integrate cleanly with ASP.NET Core apps, logging, and configuration. - Add telemetry. Semantic Kernel emits OpenTelemetry traces. Log which functions were called and with what arguments to debug agent behavior.
Common Pitfalls to Avoid
- Leaking API keys by hard-coding them—always use environment variables, user secrets, or Azure Key Vault.
- Uncontrolled cost. Auto function calling can trigger many model round-trips. Monitor token usage and prefer smaller models for simple routing tasks.
- Overloading a single agent with 30 tools. Models degrade when given too many choices; split responsibilities across specialized agents.
- Ignoring prompt injection. If your agent reads external web content or user files, that content can contain instructions. Isolate untrusted data and constrain what tools it can influence.
Advanced: Adding Memory and RAG to Your C# Agent
Real autonomous agents need context beyond a single conversation. Semantic Kernel supports vector-store connectors (Azure AI Search, Qdrant, Redis, and more) so your agent can retrieve relevant documents—a pattern known as Retrieval-Augmented Generation (RAG). You expose retrieval as just another [KernelFunction], and the agent decides when it needs to look something up.
public class KnowledgePlugin
{
private readonly IVectorSearch _search;
public KnowledgePlugin(IVectorSearch search) => _search = search;
[KernelFunction]
[Description("Searches the company knowledge base for relevant info.")]
public async Task<string> SearchDocsAsync(
[Description("The search query")] string query)
{
var results = await _search.QueryAsync(query, top: 3);
return string.Join("\n---\n", results);
}
}
Because retrieval is exposed as a tool, the agent grounds its answers in your data instead of hallucinating—dramatically improving accuracy for enterprise use cases like support bots and internal assistants.
Conclusion: Key Takeaways
You now have a complete mental model for building AI agents in C# with Semantic Kernel. Instead of writing rigid, hard-coded workflows, you give an LLM a set of well-described tools and let it reason its way to the goal autonomously.
- Semantic Kernel gives .NET developers a first-class way to build autonomous AI agents with full type safety and DI support.
- Plugins with clear
[Description]attributes are the agent's tools—descriptions drive behavior. - FunctionChoiceBehavior.Auto() turns a chat model into a task-solving agent that plans and calls functions on its own.
- The Agent Framework (
ChatCompletionAgent) enables persistent, named, and multi-agent systems. - Follow best practices—validate inputs, cap iterations, secure keys, and add telemetry—to move from demo to production.
The best way to master building AI agents in C# is to start small: create one plugin, enable auto function calling, and watch your agent reason. From there, add memory, RAG, and multiple collaborating agents. Semantic Kernel gives you everything you need to build powerful, autonomous AI agents in the .NET ecosystem—so open your IDE and start building today.
Your go-to resource for C#, .NET, and modern software development. Follow along for daily tutorials, tips, and real-world examples.
Comments
Post a Comment