Build a Frontend for your Microsoft Agent Framework Agents with AG-UI

AI Summary13 min read

TL;DR

Learn to build a frontend for Microsoft Agent Framework agents using AG-UI and CopilotKit. This guide covers setup, backend integration, and frontend development for AI agents.

Key Takeaways

  • Microsoft Agent Framework is an open-source SDK for building and orchestrating AI agents with features like modular agents, workflows, and tool integrations.
  • AG-UI protocol bridges the backend (Microsoft Agent Framework) and frontend (CopilotKit) for seamless communication.
  • Setup involves CLI commands, dependency installation, GitHub token configuration, and running a development server for a full-stack agent.

Tags

webdevaiprogrammingopensource

In this guide, you will learn how to build a frontend for your Microsoft Agent Framework Agents using AG-UI Protocol and CopilotKit. Microsoft Agent Framework will power the AI agents backend while CopilotKit powers the frontend and then AG-UI creates a bridge that enables the frontend to communicate with the backend.

Before we jump in, here is what we will cover:

  • What is the Microsoft Agent Framework?

  • Setting up a Microsoft Agent Framework + AG-UI + CopilotKit agent using CLI

  • Integrating your Microsoft Agent Framework agent with AG-UI protocol in the backend

  • Building a frontend for your Microsoft Agent Framework + AG-UI agent using CopilotKit

Here is a preview of what you can build using Microsoft Agent Framework + AG-UI + CopilotKit.

Check out AG-UI's GitHub ⭐️

What is the Microsoft Agent Framework?

The Microsoft Agent Framework is an open-source software development kit (SDK) and runtime designed for building, orchestrating, and deploying AI agents and multi-agent workflows.

It supports both Python and .NET languages, allowing developers to create everything from simple chat-based agents to complex systems where multiple agents collaborate on tasks

Microsoft Agent Framework key features include:

  • Agents: Modular AI entities powered by large language models (LLMs) like Azure OpenAI, OpenAI, or others. Agents can reason, use tools, and maintain conversation history via built-in threading.

  • **Workflows: **Graph-based orchestration for explicit control over multi-agent execution (e.g., sequential, parallel, nested, or human-in-the-loop). Supports checkpointing, type-based routing, and debugging.

  • **Tools and Integrations: **OpenAPI-first design for calling APIs; Model Context Protocol (MCP) for dynamic tools; Agent2Agent (A2A) protocol for cross-runtime collaboration.

If you want to dive deeper into how Microsoft Agent Framework works and its setup, check out the docs here: Microsoft Agent Framework docs.

Image from Notion

Prerequisites

Before you begin, you'll need the following:

Setting up a Microsoft Agent Framework + AG-UI + CopilotKit agent using CLI

In this section, you will learn how to set up a full-stack Microsoft Agent Framework agent using a CLI command that setups the backend using AG-UI protocol and the frontend using CopilotKit.

Let’s get started.

Step 1: Run CLI command

If you don’t already have a Microsoft Agent Framework agent, you can set up one quickly by running the CLI command below in your terminal.

npx copilotkit@latest init -m microsoft-agent-framework
Enter fullscreen mode Exit fullscreen mode

Then give your project a name as shown below.

Step 2: Install dependencies

Once your project has been created successfully, install dependencies using your preferred package manager:

# Using pnpm (recommended)
pnpm install

# Using npm
npm install

# Using yarn
yarn install

# Using bun
bun install
Enter fullscreen mode Exit fullscreen mode

Step 3: Set up your GitHub token for GitHub Models

After installing the dependencies, first, get your GitHub token:

gh auth token
Enter fullscreen mode Exit fullscreen mode

Then, navigate to the agent directory and set it as a user secret:

cd agent
dotnet user-secrets set GitHubToken "<your-token>"
cd ..
Enter fullscreen mode Exit fullscreen mode

Step 4: Run development server

Then start the development server using your preferred package manager:

# Using pnpm
pnpm dev

# Using npm
npm run dev

# Using yarn
yarn dev

# Using bun
bun run dev
Enter fullscreen mode Exit fullscreen mode

Once the development server is running, navigate to http://localhost:3000/ and you should see your Microsoft Agent Framework + AG-UI + CopilotKit agent up and running.

Image from Notion

Congrats! You've successfully integrated a ADK Agent chatbot to your application. To start, try the provided tools to set the web page theme, write proverbs or get the weather, as shown below.

Integrating your Microsoft Agent Framework agent with AG-UI protocol in the backend

In this section, you will learn how to integrate your Microsoft Agent Framework agent with AG-UI protocol, in order to expose it to the frontend.

Let’s jump in.

Step 1: Install Microsoft Agent Framework + AG-UI packages

To get started, install the Microsoft Agent Framework + AG-UI packages together with other necessary dependencies using the commands below.

dotnet new web -n AGUIServer
cd AGUIServer
dotnet add package Microsoft.Agents.AI.Hosting.AGUI.AspNetCore
dotnet add package Microsoft.Extensions.AI.OpenAI
dotnet add package OpenAI
Enter fullscreen mode Exit fullscreen mode

Step 2: Import required packages

Once you have installed the required packages, import them as shown below in a Program.cs file.

using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting.AGUI.AspNetCore;
using Microsoft.AspNetCore.Http.Json;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Options;
using OpenAI;
using System.ComponentModel;
using System.Text.Json.Serialization;
Enter fullscreen mode Exit fullscreen mode

Step 3: Create and Configure Web Application Builder

After importing the required packages, create a new WebApplicationBuilder instance with command-line arguments, configure JSON Serialization Options and register AG-UI Services, as shown below.

// ...

// Create a new WebApplicationBuilder instance with command-line arguments
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

// Configure JSON Serialization Options
builder.Services.ConfigureHttpJsonOptions(options => options.SerializerOptions.TypeInfoResolverChain.Add(ProverbsAgentSerializerContext.Default));

// Register AG-UI Services
builder.Services.AddAGUI();

// Build the WebApplication instance from the builder
// This compiles all registered services and configurations
WebApplication app = builder.Build();

// ...
Enter fullscreen mode Exit fullscreen mode

Step 4: Set Up Agent Factory and Map Endpoints

Once you have configured the web application builder, set up the agent factory and map endpoints, as shown below.

// ...

// Get Required Services from Dependency Injection Container
// Retrieve the logger factory for creating loggers
var loggerFactory = app.Services.GetRequiredService<ILoggerFactory>();
// Retrieve JSON options for serialization configuration
var jsonOptions = app.Services.GetRequiredService<IOptions<JsonOptions>>();

// Create Agent Factory Instance
// Instantiate the ProverbsAgentFactory with:
// - Application configuration (for accessing appsettings, environment variables, etc.)
// - Logger factory (for creating loggers within the factory)
// - JSON serializer options (for serializing agent data)
var agentFactory = new ProverbsAgentFactory(builder.Configuration, loggerFactory, jsonOptions.Value.SerializerOptions);

// Map AG-UI Endpoint
// Map the root path ("/") to the AG-UI agent endpoint
// The CreateProverbsAgent() method returns a configured AI agent instance
// This allows the agent to handle requests at the root URL
app.MapAGUI("/", agentFactory.CreateProverbsAgent());

// Start the web application and begin listening for HTTP requests
// This is an async operation that will run until the application is stopped
await app.RunAsync();

// ...
Enter fullscreen mode Exit fullscreen mode

Step 5: Define your agent state

After setting up the agent factory and mapping endpoints, define your agent state class that maintains the application's state. The agent state class is registered as a singleton in the dependency injection container, meaning there's one instance shared across the entire application lifetime.

// ...

public class ProverbsState
{
    // Initialize the Proverbs list as an empty list to avoid null reference issues
    public List<string> Proverbs { get; set; } = new List<string>();
}

// ...
Enter fullscreen mode Exit fullscreen mode

Step 6: Configure your Agent factory

Once you have defined your agent state, configure your agent factory class responsible for creating and configuring AI agents.

// ...

public class ProverbsAgentFactory
{
    // Store configuration for accessing settings (like API tokens)
    private readonly IConfiguration _configuration;
    // Reference to the shared state instance
    private readonly ProverbsState _state;
    // OpenAI client instance for making API calls
    private readonly OpenAIClient _openAiClient;
    // Logger instance for logging agent activities
    private readonly ILogger _logger;
    // JSON serializer options for serializing/deserializing agent data
    private readonly System.Text.Json.JsonSerializerOptions _jsonSerializerOptions;

    // ...
 }

 // ...
Enter fullscreen mode Exit fullscreen mode

Step 7: Initialize the Agent factory

Inside the agent factory class, define a constructor that initializes the agent factory by using a GitHub token to authenticate with the Azure OpenAI endpoint and configure the OpenAI client.

// ...

public class ProverbsAgentFactory
{
    // Store configuration for accessing settings (like API tokens)
    private readonly IConfiguration _configuration;
    // Reference to the shared state instance
    private readonly ProverbsState _state;
    // OpenAI client instance for making API calls
    private readonly OpenAIClient _openAiClient;
    // Logger instance for logging agent activities
    private readonly ILogger _logger;
    // JSON serializer options for serializing/deserializing agent data
    private readonly System.Text.Json.JsonSerializerOptions _jsonSerializerOptions;

    // Step 3.1: Constructor - Initialize the factory with dependencies
    // This constructor is called by the dependency injection container
    public ProverbsAgentFactory(IConfiguration configuration, ProverbsState state)
    {
        // Store injected dependencies
        _configuration = configuration;
        _state = new();

        // Step 3.2: Retrieve the GitHub token from configuration
        // The token is used to authenticate with the Azure OpenAI endpoint
        // If the token is not found, throw an exception with helpful instructions
        var githubToken = _configuration["GitHubToken"]
            ?? throw new InvalidOperationException(
                "GitHubToken not found in configuration. " +
                "Please set it using: dotnet user-secrets set GitHubToken \"<your-token>\" " +
                "or get it using: gh auth token");

        // Step 3.3: Create and configure the OpenAI client
        // - Use the GitHub token as the API key credential
        // - Set the endpoint to Azure's inference API endpoint
        _openAiClient = new OpenAIClient(
            new System.ClientModel.ApiKeyCredential(githubToken),
            new OpenAIClientOptions
            {
                Endpoint = new Uri("https://models.inference.ai.azure.com")
            });
    }

    // ...

 }
Enter fullscreen mode Exit fullscreen mode

Step 8: Create and configure your AI agent

Once you have initialized the agent factory, define a method inside the agent factory class that sets up the chat client, defines the agent's behavior, and registers the available tools

// ...

public class ProverbsAgentFactory
{
    // Store configuration for accessing settings (like API tokens)
    private readonly IConfiguration _configuration;
    // Reference to the shared state instance
    private readonly ProverbsState _state;
    // OpenAI client instance for making API calls
    private readonly OpenAIClient _openAiClient;
    // Logger instance for logging agent activities
    private readonly ILogger _logger;
    // JSON serializer options for serializing/deserializing agent data
    private readonly System.Text.Json.JsonSerializerOptions _jsonSerializerOptions;

    // ...

    // Create Proverbs Agent
    // This method creates and configures the AI agent with its tools and capabilities
    public AIAgent CreateProverbsAgent()
    {
        // Get Chat Client
        // Retrieve a chat client for the "gpt-4o-mini" model
        // Convert it to the IChatClient interface required by the agent framework
        var chatClient = _openAiClient.GetChatClient("gpt-4o-mini").AsIChatClient();

        // Create Chat Client Agent
        // Create a ChatClientAgent that wraps the chat client with agent capabilities
        // - name: Identifier for the agent
        // - description: System prompt that describes the agent's role and behavior
        //   This instructs the agent to always check the current proverbs list before discussing them
        // - tools: Array of functions the agent can call to perform actions
        var chatClientAgent = new ChatClientAgent(
            chatClient,
            name: "ProverbsAgent",
            description: @"A helpful assistant that helps manage and discuss proverbs.
            You have tools available to add, set, or retrieve proverbs from the list.
            When discussing proverbs, ALWAYS use the get_proverbs tool to see the current list before mentioning, updating, or discussing proverbs with the user.",
            tools: [
                // Tool 1: Get the current list of proverbs
                AIFunctionFactory.Create(GetProverbs, options: new() { Name = "get_proverbs", SerializerOptions = _jsonSerializerOptions }),
                // Tool 2: Add new proverbs to the existing list
                AIFunctionFactory.Create(AddProverbs, options: new() { Name = "add_proverbs", SerializerOptions = _jsonSerializerOptions }),
                // Tool 3: Replace the entire list of proverbs
                AIFunctionFactory.Create(SetProverbs, options: new() { Name = "set_proverbs", SerializerOptions = _jsonSerializerOptions }),
                // Tool 4: Get weather information for a location
                AIFunctionFactory.Create(GetWeather, options: new() { Name = "get_weather", SerializerOptions = _jsonSerializerOptions })
            ]);

        // Wrap with Shared State Agent
        // Wrap the chat client agent with SharedStateAgent to enable state persistence
        // This allows the agent to maintain state across multiple interactions
        // The JSON serializer options are used for state serialization
        return new SharedStateAgent(chatClientAgent, _jsonSerializerOptions);
    }    
    // ...

 }
Enter fullscreen mode Exit fullscreen mode

Step 9: Define agent tools

After configuring your agent, define agent tool methods inside the agent factory class that your AI agent can call as tools.

// ...

public class ProverbsAgentFactory
{
    // Store configuration for accessing settings (like API tokens)
    private readonly IConfiguration _configuration;
    // Reference to the shared state instance
    private readonly ProverbsState _state;
    // OpenAI client instance for making API calls
    private readonly OpenAIClient _openAiClient;


    // ...

    // Tool 1: Get Proverbs
    // Retrieves the current list of proverbs from the shared state
    [Description("Get the current list of proverbs.")]
    private List<string> GetProverbs()
    {
        // Log the operation for debugging and monitoring
        _logger.LogInformation("📖 Getting proverbs: {Proverbs}", string.Join(", ", _state.Proverbs));
        // Return the current list of proverbs from the shared state
        return _state.Proverbs;
    }

    // Tool 2: Add Proverbs
    // Adds new proverbs to the existing list without removing existing ones
    [Description("Add new proverbs to the list.")]
    private void AddProverbs([Description("The proverbs to add")] List<string> proverbs)
    {
        // Log the operation with the proverbs being added
        _logger.LogInformation("➕ Adding proverbs: {Proverbs}", string.Join(", ", proverbs));
        // Add the new proverbs to the end of the existing list
        // AddRange appends all items from the input list to the state's Proverbs list
        _state.Proverbs.AddRange(proverbs);
    }

    // Tool 3: Set Proverbs
    // Replaces the entire list of proverbs with a new list
    [Description("Replace the entire list of proverbs.")]
    private void SetProverbs([Description("The new list of proverbs")] List<string> proverbs)
    {
        // Log the operation with the new list of proverbs
        _logger.LogInformation("📝 Setting proverbs: {Proverbs}", string.Join(", ", proverbs));
        // Replace the entire list using collection expression syntax
        // The [.. proverbs] syntax creates a new list with a copy of all items from proverbs
        _state.Proverbs = [.. proverbs];
    }

    // Tool 4: Get Weather
    // Retrieves weather information for a specified location
    // Note: This is a mock implementation that returns ha

Visit Website