Wednesday, April 8, 2026

Getting Started with Microsoft Agent Framework 1.0.0 in .NET

Microsoft Agent Framework 1.0.0 was released few days ago with support for both .NET and Python. Agent Framework is the direct successor to both Semantic Kernel and AutoGen and includes many features such as Persistence, Monitoring, Humans in the Loop etc.

In this post, let's see how we can create a simple agent with multiple tools in .NET.

I have created a Console App and the first step is adding the new Microsoft.Agents.AI.Foundry package.
dotnet add package Microsoft.Agents.AI.Foundry --version 1.0.0
An AI Agent uses an LLM to run tools in a loop to achieve it's goal. So first let's define some tools that our agent can use. In Agent Framework, tools are plain C# methods decorated with [Description] attributes. The framework automatically generates the tool schema for the LLM from the attribute.
[Description("Returns weather data for a given city, including temperature (in Celsius) and description.")]
static WeatherResult GetWeather(
    [Description("The city to get the weather for.")] string city)
{
    Console.WriteLine($"[Tool] Getting weather for '{city}'.");

    return new WeatherResult(18, "Rainy");
}

[Description("Returns a list of leisure activities for a given city and date, each with a name and location.")]
static List<LeisureActivity> GetActivities(
    [Description("The city to get activities for.")] string city,
    [Description("The date to get activities for in format YYYY-MM-DD.")] string date)
{
    Console.WriteLine($"[Tool] Getting activities for '{city}' on '{date}'.");

    return
    [
        new("Hiking", city),
        new("Beach", city),
        new("Museum", city)
    ];
}

[Description("Gets the current date from the system and returns as a string in format YYYY-MM-DD.")]
static string GetCurrentDate()
{
    Console.WriteLine("[Tool] Getting current date.");

    return DateTime.Now.ToString("yyyy-MM-dd");
}

record WeatherResult(int Temperature, string Description);

record LeisureActivity(string Name, string Location);
Note: these are mock implementations returning hardcoded data, but in a real application, these tools would call actual APIs. Here we are using typed records (WeatherResultLeisureActivity) instead of raw JSON strings. The framework serializes these to JSON automatically. The [Description] attributes on the methods should describe the return shape since the framework only generates input parameter schemas, the LLM won't see the return type otherwise (.NET [Feature]: Consider including return type schema in generated tool definitions)

Now let's create an agent that uses these tools.
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using System.ComponentModel;

string endpoint = "https://<FOUNDRY_RESOURCE>.services.ai.azure.com/";
string deploymentName = "<DEPLOYMENT_NAME>";

// For local development, using AzureCliCredential
var credential = new AzureCliCredential();

AIAgent agent = new AIProjectClient(new Uri(endpoint), credential)
    .AsAIAgent(
        model: deploymentName,
        name: "weekend-planner",
        instructions: """
            You help users plan their weekends and choose the best activities for the given weather.
            If an activity would be unpleasant in weather, don't suggest it.
            Include date of the weekend in response.
            """,
        tools: [
            AIFunctionFactory.Create(GetWeather),
            AIFunctionFactory.Create(GetActivities),
            AIFunctionFactory.Create(GetCurrentDate)
        ]);

string userInput = "What should I do this weekend in Auckland?";
Console.WriteLine(await agent.RunAsync(userInput));
The key things to note here:
  • AsAIAgent() is an extension method on AIProjectClient provided by the Microsoft.Agents.AI.Foundry package.
  • AIFunctionFactory.Create() inspects the method's [Description] attributes and parameter types to automatically generate the tool schema that gets sent to the LLM. The LLM then decides which tools to call and with what arguments.
  • RunAsync() handles the entire tool calling loop for you. It sends the prompt, processes tool call requests from the LLM, invokes the matching local functions, sends results back, and returns the final response.
Now when I run this, I can see something like this.
Output
Isn't it nice.

Hope this helps.

More read:

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment