If you’re a .NET developer looking to break into AI engineering, agents are the single best place to start. They’re the point where “calling an LLM API” turns into “building a system that reasons, uses tools, and takes action” — and Azure AI Foundry Agent Service, paired with .NET, makes this surprisingly approachable.
In this post, I’ll walk through exactly how to stand up your first agent end-to-end — from the Azure side setup to the actual C# code — and share the full walkthrough in video form as well.
🎥 Watch the full hands-on video here: https://youtu.be/mrsEsculrNg
Why Agents, and Why Now
Most of us started our AI journey with a simple chat completion call — send a prompt, get text back. That’s fine for Q&A, but it falls apart the moment you need the model to do something: run code, search documents, call an API, or hold a multi-turn conversation with real state.
That’s exactly the gap Foundry Agent Service closes. An agent in Foundry is:
- Durable — it lives as a resource in your Foundry project, not in your app’s memory
- Tool-aware — it can invoke built-in tools (like a code interpreter) or your own custom functions
- Stateful — conversations persist and carry context across turns
And the best part for us .NET folks: the entire thing is callable from clean, typed C# — no wrestling with raw REST payloads.
What You’ll Need
Before writing any code, set up the Azure side:
-
An Azure AI Foundry project with a chat model deployed (e.g.,
gpt-4o-mini) - The Foundry User RBAC role assigned to your account at the resource/resource-group scope — this is the single most common blocker people hit (a silent 403 when calling the SDK), so don’t skip it
-
az loginrun locally, so your code can authenticate without hardcoding any keys
If you’ve worked with Cognitive Services roles before, note that agent management needs this separate Foundry-specific role — that trips up a lot of people coming from plain Azure OpenAI usage.
Setting Up the .NET Project
dotnet new console -n FoundryAgentLab -f net10.0
cd FoundryAgentLab
dotnet add package Azure.AI.Projects
dotnet add package Azure.Identity
Enter fullscreen mode Exit fullscreen mode
Set your environment variables:
export PROJECT_ENDPOINT="https://<your-resource>.services.ai.azure.com/api/projects/<your-project>"
export MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
export AGENT_NAME="my-dotnet-agent"
Enter fullscreen mode Exit fullscreen mode
Creating the Agent
using Azure.AI.Projects;
using Azure.AI.Projects.OpenAI;
using Azure.Identity;
string projectEndpoint = Environment.GetEnvironmentVariable("PROJECT_ENDPOINT")
?? throw new InvalidOperationException("Missing environment variable 'PROJECT_ENDPOINT'");
string modelDeploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME")
?? throw new InvalidOperationException("Missing environment variable 'MODEL_DEPLOYMENT_NAME'");
string agentName = Environment.GetEnvironmentVariable("AGENT_NAME")
?? throw new InvalidOperationException("Missing environment variable 'AGENT_NAME'");
AIProjectClient projectClient = new(new Uri(projectEndpoint), new AzureCliCredential());
AgentDefinition agentDefinition = new PromptAgentDefinition(modelDeploymentName)
{
Instructions = "You are a helpful .NET/Azure tutor that answers general questions",
};
AgentVersion newAgentVersion = projectClient.Agents.CreateAgentVersion(
agentName,
options: new(agentDefinition));
Console.WriteLine($"Agent created — Id: {newAgentVersion.Id}, Version: {newAgentVersion.Version}");
Enter fullscreen mode Exit fullscreen mode
A few things worth calling out here:
-
AIProjectClientis your single entry point into the project — agents, conversations, and responses all hang off it. -
PromptAgentDefinitionis a declarative agent — you describe its model and instructions, and Foundry handles the execution plumbing. - Notice the agent has a version. Every time you update it, Foundry keeps a version history — helpful when you’re iterating on prompts and want to roll back.
Talking to the Agent
Creating the agent is half the story — now let’s have an actual conversation with it, with context retained across turns:
using OpenAI.Responses;
// Create a conversation to maintain context across turns
ProjectConversation conversation = projectClient.OpenAI.Conversations.CreateProjectConversation();
// A responses client pre-bound to this agent and this conversation
ProjectResponsesClient responsesClient = projectClient.OpenAI.GetProjectResponsesClientForAgent(
defaultAgent: agentName,
defaultConversationId: conversation.Id);
ResponseResult response = responsesClient.CreateResponse("What is the size of France in square miles?");
Console.WriteLine(response.GetOutputText());
// Follow-up — same conversation, so context carries over
response = responsesClient.CreateResponse("And what is the capital city?");
Console.WriteLine(response.GetOutputText());
Enter fullscreen mode Exit fullscreen mode
Run it, and you’ll see the second answer correctly reference “it” back to France — no manual history management, no prompt-stuffing. That’s the conversation object doing its job.
What Makes This “Agentic” Rather Than Just “A Chat Call”
It’s a fair question — at this scale, it looks a lot like calling any chat API. The distinction shows up once you scale this pattern up:
- Attach built-in tools (code interpreter, file search, Bing grounding) and the model decides on its own when to invoke them
- Attach your own function tools, and the agent calls into your application code mid-conversation
- The agent persists as a named, versioned resource your whole team can reference — not a prompt buried in someone’s script
This lab is deliberately the smallest possible slice of that — enough to get something real running today, with room to grow into tool-calling and multi-agent patterns next.
Wrapping Up
If you’re a .NET developer eyeing a move toward AI engineering, this is a genuinely good on-ramp — the SDK is clean, the concepts map well onto things you already know (clients, DI-friendly patterns, typed models), and Foundry handles the infrastructure you’d otherwise have to hand-roll.
I go through this entire setup — including the Azure Portal steps, the RBAC gotcha, and debugging a couple of real errors — in the video below. If you’re following along in Hindi/Hinglish, this one’s for you:
🎥 https://youtu.be/mrsEsculrNg
If you found this useful, a like/subscribe on the channel genuinely helps — and drop a comment if you get stuck anywhere, I read all of them.
Happy coding! 🚀
답글 남기기