DEV Community

Cover image for Build a Frontend for your Microsoft Agent Framework (Python) Agents with AG-UI
Bonnie for CopilotKit

Posted on

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

TL;DR

In this guide, you will learn how to build a frontend for your Microsoft Agent Framework (Python) Agents using AG-UI Protocol and CopilotKit. Microsoft Agent Framework (Python) 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.

Check out AG-UI's GitHub ⭐️

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

  • Understanding 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 (Python) + AG-UI + CopilotKit.

What is the Microsoft Agent Framework?

The Microsoft Agent Framework (MAF) is an open-source development kit (SDK) and runtime for building and deploying AI agents and multi-agent workflows in both Python and NET.

MAF is considered the next generation of Microsoft's previous agent-related projects, unifying the strengths of AutoGen (for innovative multi-agent orchestration) and Semantic Kernel (for enterprise-grade features and production readiness).

The core purpose of the framework is to allow developers to create sophisticated AI applications that involve:

  • Individual AI agents that use Large Language Models (LLMs) to reason, make decisions, and use tools.

  • Complex multi-agent systems where multiple agents collaborate to solve complex, multi-step tasks.

The Python implementation offers a developer-friendly experience that is highly suitable for building and testing agentic systems quickly.

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:

  • OpenAI or Azure OpenAI credentials (for the Microsoft Agent Framework agent)

  • Python 3.12+

  • uv

  • Node.js 20+

  • Any of the following package managers:

    • pnpm (recommended)
    • npm
    • yarn
    • bun

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 (Python) agent using a CLI command that sets up 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-py
Enter fullscreen mode Exit fullscreen mode

Then give your project a name as shown below.

Image from Notion

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 agent credentials

After installing the dependencies, set up your agent credentials. The backend automatically uses Azure when the Azure env vars below are present; otherwise, it falls back to OpenAI.

To set up your agent credentials, create a .env file inside the agent folder with one of the following configurations:

OpenAI:

OPENAI_API_KEY=sk-...your-openai-key-here...
OPENAI_CHAT_MODEL_ID=gpt-4o-mini
Enter fullscreen mode Exit fullscreen mode

Azure OpenAI:

AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com/
AZURE_OPENAI_CHAT_DEPLOYMENT_NAME=gpt-4o-mini
# If you are not relying on az login:
# AZURE_OPENAI_API_KEY=...
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 (Python) + AG-UI + CopilotKit agent up and running.

Image from Notion

Congrats! You've successfully set up a full-stack Microsoft Agent Framework agent. Your AI agent is now ready to use! Try playing around with the suggestions in the chat to test the integration.

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 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.

uv pip install agent-framework, agent-framework-ag-ui, azure-identity
Enter fullscreen mode Exit fullscreen mode

Step 2: Define your agent state

Once you have installed the required packages, use a JSON schema to define the structure of the agent state that will be synchronised between the backend and the frontend UI, as shown below.

from __future__ import annotations

from textwrap import dedent
from typing import Annotated

# Import core agent framework components for building conversational AI agents
from agent_framework import ChatAgent, ChatClientProtocol, ai_function
# Import CopilotKit integration layer that bridges Agent Framework with the frontend
from agent_framework_ag_ui import AgentFrameworkAgent
from pydantic import Field

# STATE_SCHEMA: Defines the structure of agent state 
STATE_SCHEMA: dict[str, object] = {
    "proverbs": {
        "type": "array",  # Proverbs is a list/array of items
        "items": {"type": "string"},  # Each item in the array is a string
        "description": "Ordered list of the user's saved proverbs.",  # Human-readable description
    }
}

// ...
Enter fullscreen mode Exit fullscreen mode

After that, use a state config JSON schema to tell the agent which tool function to call when it needs to update state, as shown below.

from __future__ import annotations

from textwrap import dedent
from typing import Annotated

# Import core agent framework components for building conversational AI agents
from agent_framework import ChatAgent, ChatClientProtocol, ai_function
# Import CopilotKit integration layer that bridges Agent Framework with the frontend
from agent_framework_ag_ui import AgentFrameworkAgent
from pydantic import Field

// ...

# PREDICT_STATE_CONFIG: Maps state fields to the tools that modify them.
# This tells your agent which tool function to call when the agent needs to update
# a particular piece of state, and which argument of that tool contains the new state value.
PREDICT_STATE_CONFIG: dict[str, dict[str, str]] = {
    "proverbs": {
        "tool": "update_proverbs",  # The name of the tool function that updates proverbs
        "tool_argument": "proverbs",  # The parameter name in that tool that receives the new proverb list
    }
}

// ...
Enter fullscreen mode Exit fullscreen mode

Step 3: Define your agent tools

After defining your agent state, configure your agent tools using the @ai_function decorator to mark them as tools that your AI agent can call, as shown below. The name and description help the agent to understand when and how to use these tools.

from __future__ import annotations

from textwrap import dedent
from typing import Annotated

# Import core agent framework components for building conversational AI agents
from agent_framework import ChatAgent, ChatClientProtocol, ai_function
# Import CopilotKit integration layer that bridges Agent Framework with the frontend
from agent_framework_ag_ui import AgentFrameworkAgent
from pydantic import Field

// ...

# @ai_function decorator: Marks this as a tool that the AI agent can call.
# The name and description help the LLM understand when and how to use this tool.
@ai_function(
    name="update_proverbs",
    description=(
        "Replace the entire list of proverbs with the provided values. "
        "Always include every proverb you want to keep."
    ),
)
def update_proverbs(
    proverbs: Annotated[
        list[str],  # The function accepts a list of strings
        Field(
            description=(
                # This description guides the LLM on how to use this parameter correctly.
                # Emphasises that this should be the COMPLETE list, not a partial update.
                "The complete source of truth for the user's proverbs. "
                "Maintain ordering and include the full list on each call."
            )
        ),
    ],
) -> str:
    """
    Persist the provided set of proverbs.

    Returns:
        A confirmation message indicating how many proverbs are now tracked.
    """
    return f"Proverbs updated. Tracking {len(proverbs)} item(s)."

# Weather tool: Demonstrates frontend UI integration through tool calls.
# When the agent calls this function, CopilotKit can render a weather card in the UI.
@ai_function(
    name="get_weather",
    description="Share a quick weather update for a location. Use this to render the frontend weather card.",
)
def get_weather(
    location: Annotated[str, Field(description="The city or region to describe. Use fully spelled out names.")],
) -> str:
    """
    Return a short natural language weather summary.

    Args:
        location: The city or region name to get the weather for.

    Returns:
        A friendly weather description string that can be displayed to the user.
    """
    # Normalise the location string: remove whitespace, capitalise words
    normalized = location.strip().title() or "the requested location"

    # Return a mock weather response (in production, this would query a real API)
    return (
        f"The weather in {normalised} is mild with a light breeze. "
        "Skies are mostly clear—perfect for planning something fun."
    )

# Human-in-the-loop tool: Demonstrates requiring explicit user approval before executing.
# The approval_mode="always_require" parameter ensures this function will pause execution
# and wait for the user to explicitly approve or reject the action via the UI.
@ai_function(
    name="go_to_moon",
    description="Request a playful human-in-the-loop confirmation before launching a mission to the moon.",
    approval_mode="always_require",  # CRITICAL: Forces user approval before this tool executes
)
def go_to_moon() -> str:
    """
    Request human approval before continuing.


    Returns:
        A message confirming the approval request has been initiated.
    """
    return "Mission control requested. Awaiting human approval for the lunar launch."
Enter fullscreen mode Exit fullscreen mode

Step 4: Create, configure and integrate your agent with AG-UI protocol

Once you have defined your agent tools, create your agent with Microsoft Agent Framework. Then configure the agent with instructions, chat client, and tools, as shown below.

from __future__ import annotations

from textwrap import dedent
from typing import Annotated

# Import core agent framework components for building conversational AI agents
from agent_framework import ChatAgent, ChatClientProtocol, ai_function
# Import CopilotKit integration layer that bridges Agent Framework with the frontend
from agent_framework_ag_ui import AgentFrameworkAgent
from pydantic import Field

// ...

def create_agent(chat_client: ChatClientProtocol) -> AgentFrameworkAgent:
    """
    Instantiate the Microsoft Agent Framework with AG-UI.

    This is the main entry point for creating the agent. It configures the base ChatAgent
    with instructions and tools, then wraps it in an AgentFrameworkAgent for AG-UI integration.

    Args:
        chat_client: The chat client protocol implementation that handles LLM communication.

    Returns:
        A fully configured AgentFrameworkAgent ready to handle user interactions.
    """
    # Step 1: Create the base ChatAgent with Microsoft Agent Framework
    # This agent handles the core conversational logic and tool execution
    base_agent = ChatAgent(
        name="proverbs_agent",  # Internal identifier for this agent

        # System instructions: These guide the agent's behaviour throughout the conversation.
        # The instructions are carefully crafted to ensure proper state management,
        # tool usage, and user experience.
        instructions=dedent(
            """
            You help users brainstorm, organize, and refine proverbs while coordinating UI updates.

            // ...

            """.strip()
        ),

        # The chat client handles actual LLM API calls (e.g., to OpenAI, Azure OpenAI, etc.)
        chat_client=chat_client,

        # Tools: These are the functions the agent can call to perform actions
        tools=[update_proverbs, get_weather, go_to_moon],
    )

    // ...
Enter fullscreen mode Exit fullscreen mode

After that, wrap your agent with AgentFrameworkAgent middleware for frontend communication using AG-UI, as shown below.

from __future__ import annotations

from textwrap import dedent
from typing import Annotated

# Import core agent framework components for building conversational AI agents
from agent_framework import ChatAgent, ChatClientProtocol, ai_function
# Import CopilotKit integration layer that bridges Agent Framework with the frontend
from agent_framework_ag_ui import AgentFrameworkAgent
from pydantic import Field

// ...

def create_agent(chat_client: ChatClientProtocol) -> AgentFrameworkAgent:
    """
    Instantiate the Microsoft Agent Framework with AG-UI.

    This is the main entry point for creating the agent. It configures the base ChatAgent
    with instructions and tools, then wraps it in an AgentFrameworkAgent for CopilotKit integration.

    Args:
        chat_client: The chat client protocol implementation that handles LLM communication.

    Returns:
        A fully configured AgentFrameworkAgent ready to handle user interactions.
    """
    # Step 1: Create the base ChatAgent with Microsoft Agent Framework
    # This agent handles the core conversational logic and tool execution

    // ...

    # Step 2: Wrap the base agent in an AgentFrameworkAgent for AG-UI integration
    # This wrapper adds CopilotKit-specific features like state sync and frontend coordination
    return AgentFrameworkAgent(
        agent=base_agent,  # The underlying ChatAgent we just configured

        name="CopilotKitMicrosoftAgentFrameworkAgent",  # Display name for the agent
        description="Manages proverbs, weather snippets, and human-in-the-loop moon launches.",

        # STATE_SCHEMA tells CopilotKit what state this agent manages
        state_schema=STATE_SCHEMA,

        # PREDICT_STATE_CONFIG maps state fields to the tools that update them
        predict_state_config=PREDICT_STATE_CONFIG,

        # require_confirmation=False means the agent can update the state and continue
        # without waiting for explicit user confirmation after each state change.
        # This allows for smoother conversational flow.
        require_confirmation=False,
    )
Enter fullscreen mode Exit fullscreen mode

Step 5: Build and configure chat client

Once you have wrapped your agent with AgentFrameworkAgent middleware, build and configure a chat client with Azure OpenAI or OpenAI credentials using their respective clients, as shown below in the ./main.py file.

from __future__ import annotations

import os

# Uvicorn: ASGI server for running FastAPI applications
import uvicorn
# ChatClientProtocol: Interface that all chat clients must implement
from agent_framework._clients import ChatClientProtocol

// ...

# Load environment variables from .env file (must be done before accessing os.getenv)
# This allows developers to configure API keys and endpoints without hardcoding them
load_dotenv()

def _build_chat_client() -> ChatClientProtocol:
    """
    Build and configure the appropriate chat client based on environment variables.

    Returns:
        ChatClientProtocol: A configured chat client ready to communicate with an LLM.

    Raises:
        RuntimeError: If credentials are missing or invalid.
    """
    try:
        # Option 1: Azure OpenAI Service
        # Check if Azure OpenAI endpoint is configured
        if bool(os.getenv("AZURE_OPENAI_ENDPOINT")):
            # Azure OpenAI uses deployment names instead of model IDs
            # Deployments are custom instances of models you create in Azure
            deployment_name = os.getenv("AZURE_OPENAI_CHAT_DEPLOYMENT_NAME", "gpt-4o-mini")

            return AzureOpenAIChatClient(
                # DefaultAzureCredential tries multiple authentication methods:
                # 1. Environment variables (AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, etc.)
                # 2. Managed Identity (if running on Azure infrastructure)
                # 3. Azure CLI credentials (for local development)
                credential=DefaultAzureCredential(),

                # The name of your deployed model in Azure OpenAI Studio
                deployment_name=deployment_name,

                # Your Azure OpenAI resource endpoint (e.g., https://my-resource.openai.azure.com/)
                endpoint=os.getenv("AZURE_OPENAI_ENDPOINT"),
            )

        # Option 2: OpenAI API (public service)
        # Check if OpenAI API key is configured
        if bool(os.getenv("OPENAI_API_KEY")):
            return OpenAIChatClient(
                # Model identifier from OpenAI's catalogue (e.g., gpt-4o-mini, gpt-4, etc.)
                model_id=os.getenv("OPENAI_CHAT_MODEL_ID", "gpt-4o-mini"),

                # Your OpenAI API key from platform.openai.com
                api_key=os.getenv("OPENAI_API_KEY"),
            )

        # If neither Azure nor OpenAI credentials are found, raise an error
        raise ValueError("Either AZURE_OPENAI_ENDPOINT or OPENAI_API_KEY environment variable is required")

    except Exception as exc:  # pragma: no cover
        # Catch any initialization errors and provide a helpful message
        raise RuntimeError(
            "Unable to initialize the chat client. Double-check your API credentials as documented in README.md."
        ) from exc
Enter fullscreen mode Exit fullscreen mode

Then configure your Microsoft Agent Framework + AG-UI agent with the chat client, as shown below.

from __future__ import annotations

import os

# Uvicorn: ASGI server for running FastAPI applications
import uvicorn
# ChatClientProtocol: Interface that all chat clients must implement
from agent_framework._clients import ChatClientProtocol

// ...

# Step 1: Initialize the chat client
# This creates the connection to either Azure OpenAI or OpenAI API
chat_client = _build_chat_client()

# Step 2: Create the agent with the configured chat client
# This instantiates our MAF + AG-UI agent with all its tools and instructions
my_agent = create_agent(chat_client)

// ...
Enter fullscreen mode Exit fullscreen mode

Step 6: Add a FastAPI server and configure your agent endpoint

Once you have built the chat client with credentials, add a FastAPI server that exposes your Microsoft Agent Framework agent over AG-UI, as shown below.

from __future__ import annotations

import os

# Uvicorn: ASGI server for running FastAPI applications
import uvicorn
# add_agent_framework_fastapi_endpoint: CopilotKit integration that registers agent endpoints
from agent_framework_ag_ui import add_agent_framework_fastapi_endpoint
# dotenv: Loads environment variables from .env file
from dotenv import load_dotenv
# FastAPI: Modern web framework for building APIs
from fastapi import FastAPI
# CORSMiddleware: Handles Cross-Origin Resource Sharing for frontend communication
from fastapi.middleware.cors import CORSMiddleware

// ...

# Step 3: Create the FastAPI application
# FastAPI will handle HTTP requests from the frontend and route them to our agent
app = FastAPI(title="CopilotKit + Microsoft Agent Framework (Python)")

# Step 4: Configure CORS (Cross-Origin Resource Sharing)
# This is essential for allowing the frontend (running on a different port/domain)
# to communicate with this backend API
app.add_middleware(
    CORSMiddleware,
    # allow_origins=["*"] means accept requests from any domain
    # In production, you should restrict this to your specific frontend domain(s)
    # e.g., allow_origins=["https://myapp.com", "https://www.myapp.com"]
    allow_origins=["*"],

    # Allow cookies and authentication headers to be included in requests
    allow_credentials=True,

    # Allow all HTTP methods (GET, POST, PUT, DELETE, etc.)
    allow_methods=["*"],

    # Allow all headers (Content-Type, Authorization, etc.)
    allow_headers=["*"],
)

# Step 5: Register the CopilotKit endpoint
# This function adds the necessary routes to handle CopilotKit's communication protocol
# It creates endpoints for:
# - Agent chat interactions
# - State synchronization
# - Tool execution
# - Streaming responses
add_agent_framework_fastapi_endpoint(
    app=app,  # The FastAPI application to add routes to
    agent=my_agent,  # Our configured agent instance
    path="/",  # Base path for CopilotKit endpoints (frontend will connect here)
)

# ============================================================================
# Main Entry Point
# ============================================================================

if __name__ == "__main__":
    # This block runs only when executing this file directly (not when imported)
    # It starts the web server that listens for requests from the frontend

    # Read server configuration from environment variables with sensible defaults
    host = os.getenv("AGENT_HOST", "0.0.0.0")  # 0.0.0.0 means listen on all network interfaces
    port = int(os.getenv("AGENT_PORT", "8000"))  # Default to port 8000

    # Start the Uvicorn ASGI server
    # - "main:app" references the 'app' variable in the 'main' module
    # - host and port determine where the server listens
    # - reload=True enables auto-restart when code changes (great for development)
    #   NOTE: In production, set reload=False for better performance and stability
    uvicorn.run("main:app", host=host, port=port, reload=True)
Enter fullscreen mode Exit fullscreen mode

Congrats! You've successfully integrated your Python Microsoft Agent Framework Agent with AG-UI protocol, and it is available at http://localhost:8000 (or specified port) endpoint.

Let’s now see how to add a frontend to your AG-UI wrapped Microsoft Agent Framework agent.

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

In this section, you will learn how to add a frontend to your Microsoft Agent Framework + AG-UI agent using CopilotKit, which runs anywhere that React runs.

Let’s get started.

Step 1: Install CopilotKit packages

To get started, install the latest packages for CopilotKit into your frontend.

npm install @copilotkit/react-ui @copilotkit/react-core @copilotkit/runtime
Enter fullscreen mode Exit fullscreen mode

Step 2: Set up the Copilot Runtime instance

Once you have installed CopilotKit packages, set up the copilot runtime instance with an HttpAgent instance in the /api/copilotkit API route that enables your frontend to make HTTP requests to the backend.

import {
  CopilotRuntime, // Main runtime that manages agent communication
  ExperimentalEmptyAdapter, // Service adapter for single-agent setups
  copilotRuntimeNextJSAppRouterEndpoint, // Next.js App Router endpoint handler
} from "@copilotkit/runtime";

// Import AG-UI client for connecting to Microsoft Agent Framework agents
import { HttpAgent } from "@ag-ui/client";

// Import Next.js types for request handling
import { NextRequest } from "next/server";

// Create a service adapter for the CopilotKit runtime
const serviceAdapter = new ExperimentalEmptyAdapter();

// Create the main CopilotRuntime instance that manages communication between the frontend and backend agents
const runtime = new CopilotRuntime({

  // Define the agents that will be available to the frontend
    agents: {

    // Configure the ADK agent connection
    my_agent: new HttpAgent({

      // Specify the URL where the Microsoft Agent Framework agent is running
      url: "http://localhost:8000/",
    }),
  },
});

// Export the POST handler for the API route
export const POST = async (req: NextRequest) => {

  // Create the request handler using CopilotKit's Next.js helper
  const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
    runtime, // The CopilotRuntime instance we configured
    serviceAdapter, // The service adapter for agent coordination
    endpoint: "/api/copilotkit", // The endpoint path (matches this file's location)
  });


  return handleRequest(req);
};
Enter fullscreen mode Exit fullscreen mode

Step 3: Set up CopilotKit provider

After setting up a Copilot Runtime instance, set up the CopilotKit provider component that manages your ADK agent sessions.

To set up the CopilotKit Provider, the [<CopilotKit>](https://docs.copilotkit.ai/reference/components/CopilotKit) component must wrap the Copilot-aware parts of your application.

For most use cases, it's appropriate to wrap the CopilotKit provider around the entire app, e.g., in your layout.tsx file.

// Step 1: Import necessary types and components from Next.js and CopilotKit
import type { Metadata } from "next";

import { CopilotKit } from "@copilotkit/react-core";
import "./globals.css";
import "@copilotkit/react-ui/styles.css";

// Step 2: Define metadata for the application, used by Next.js for SEO and page headers
export const metadata: Metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

// Step 3: Define the RootLayout component, which wraps the entire application
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  // Step 4: Return the JSX structure for the layout
  return (
    <html lang="en">
      <body className={"antialiased"}>
        {/* Step 5: Wrap the children components with CopilotKit provider to enable CopilotKit functionality */}
        <CopilotKit runtimeUrl="/api/copilotkit" agent="my_agent">
          {children}
        </CopilotKit>
      </body>
    </html>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Set up a Copilot UI component

Once you have set up the CopilotKit Provider, set up a Copilot UI component that enables you to interact with your ADK agent. CopilotKit ships with a number of built-in chat components, which include CopilotPopupCopilotSidebar, and CopilotChat.

To set up a Copilot UI component, define it alongside your core page components, e.g. in your page.tsx file.

"use client";

import { CopilotKitCSSProperties, CopilotSidebar } from "@copilotkit/react-ui";
import { useState } from "react";

export default function CopilotKitPage() {
  const [themeColor, setThemeColor] = useState("#6366f1");

  // ...

  return (
    <main style={{ "--copilot-kit-primary-color": themeColor } as CopilotKitCSSProperties}>
      <CopilotSidebar
        disableSystemMessage={true}
        clickOutsideToClose={false}
        labels={{
          title: "Popup Assistant",
          initial: "👋 Hi, there! You're chatting with an agent.",
        }}
        suggestions={[
          {
            title: "Generative UI",
            message: "Get the weather in San Francisco.",
          },
          {
            title: "Frontend Tools",
            message: "Set the theme to green.",
          },
          {
            title: "Human in the Loop",
            message: "Please go to the moon.",
          },
          {
            title: "Write Agent State",
            message: "Add a proverb about AI.",
          },
          {
            title: "Update Agent State",
            message: "Please remove 1 random proverb from the list if there are any.",
          },
          {
            title: "Read Agent State",
            message: "What are the proverbs?",
          },
        ]}
      >
        <YourMainContent themeColor={themeColor} />
      </CopilotSidebar>
    </main>
   );
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Sync your Microsoft Agent Framework agent state with the frontend

After setting up a Copilot UI component, sync your Microsoft Agent Framework agent state with the frontend using CopilotKit hooks.

To sync your Microsoft Agent Framework agent state with the frontend, use the CopilotKit useCoAgent hook that allows you to share state bidirectionally between your application and the agent.

"use client";

import { useCoAgent } from "@copilotkit/react-core";

// State of the agent, make sure this aligns with your agent's state.
type AgentState = {
  proverbs: string[];
}

function YourMainContent({ themeColor }: { themeColor: string }) {

  // 🪁 Shared State: https://docs.copilotkit.ai/coagents/shared-state
  const { state, setState } = useCoAgent<AgentState>({
    name: "my_agent",
    initialState: {
      proverbs: [
        "CopilotKit may be new, but it's the best thing since sliced bread.",
      ],
    },
  })

     // ...
  return (

  // ...
  )
Enter fullscreen mode Exit fullscreen mode

To render your agent's state, progress, outputs, or tool calls with custom UI components in real-time, you can use tool-based Generative UI.

"use client";

import { useCoAgent, useCopilotAction } from "@copilotkit/react-core";

// ...

function YourMainContent({ themeColor }: { themeColor: string }) {
  // ...

  //🪁 Generative UI: https://docs.copilotkit.ai/coagents/generative-ui
  useCopilotAction({
    name: "get_weather",
    description: "Get the weather for a given location.",
    available: "disabled",
    parameters: [
      { name: "location", type: "string", required: true },
    ],
    render: ({ args }) => {
      return <WeatherCard location={args.location} themeColor={themeColor} />
    },
  });

  return ( ... )
Enter fullscreen mode Exit fullscreen mode

Then try asking the agent to get the weather for a location. You should see the custom UI component that we added renders the get weather tool call and displays the arguments that were passed to the tool.

Image from Notion

Step 6: Implementing Human-in-the-Loop (HITL) in the frontend

Human-in-the-loop (HITL) allows agents to request human input or approval during execution, making AI systems more reliable and trustworthy. This pattern is essential when building AI applications that need to handle complex decisions or actions that require human judgment.

You can learn more about Human in the Loop here on CopilotKit docs.

Image from Notion

To implement Human-in-the-Loop (HITL) in the frontend, you need to use the CopilotKit useCopilotKitAction hook with the renderAndWaitForResponse method, which allows returning values asynchronously from the render function, as shown in the src/app/page.tsx file.

import { MoonCard } from "@/components/moon";
import { useCopilotAction } from "@copilotkit/react-core";

// ...

function YourMainContent({ themeColor }: { themeColor: string }) {

  // ...

  // 🪁 Human In the Loop: https://docs.copilotkit.ai/pydantic-ai/human-in-the-loop
  useCopilotAction(
    {
      name: "go_to_moon",
      description: "Go to the moon on request.",
      renderAndWaitForResponse: ({ respond, status }) => {
        return <MoonCard themeColor={themeColor} status={status} respond={respond} />;
      },
    },
    [themeColor],
  );

  return (

    // ...

  );
}
Enter fullscreen mode Exit fullscreen mode

Then try asking the agent to go to the moon. Then the agent will trigger frontend actions by tool/action name to request human input or feedback during execution, and you are prompted with a choice (rendered inside the chat UI). Then you can choose by pressing a button in the chat UI, as shown below.

Image from Notion

Step 7: Stream your Microsoft Agent Framework agent responses in the frontend

Once you have synced your Microsoft Agent Framework agent state with the frontend, stream your MAF agent responses or results in the frontend.

To stream your Microsoft Agent Framework agent responses or results in the frontend, pass the agent’s state field values to the frontend components, as shown below.

"use client";

import { useCoAgent } from "@copilotkit/react-core";
import { ProverbsCard } from "@/components/proverbs";

// State of the agent, make sure this aligns with your agent's state.
type AgentState = {
  proverbs: string[];
}

function YourMainContent({ themeColor }: { themeColor: string }) {
  // 🪁 Shared State: https://docs.copilotkit.ai/coagents/shared-state
  const { state, setState } = useCoAgent<AgentState>({
    name: "my_agent",
    initialState: {
      proverbs: [
        "CopilotKit may be new, but it's the best thing since sliced bread.",
      ],
    },
  })

  // ...

  return (
    <div
      style={{ backgroundColor: themeColor }}
      className="h-screen flex justify-center items-center flex-col transition-colors duration-300"
    >
      <ProverbsCard state={state} setState={setState} />
    </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

If you query your Microsoft Agent Framework agent, you should see the agent’s response or results streaming in the UI, as shown below.

Image from Notion

Conclusion

In this guide, we have walked through the steps of building a frontend for your Microsoft Agent Framework agent using AG-UI protocol and CopilotKit.

While we’ve explored a couple of features, we have barely scratched the surface of the countless use cases for CopilotKit, ranging from building interactive AI chatbots to building agentic solutions—in essence, CopilotKit lets you add a ton of useful AI capabilities to your products in minutes.

Hopefully, this guide makes it easier for you to integrate AI-powered Copilots into your existing application.

Follow CopilotKit on Twitter and say hi, and if you'd like to build something cool, join the Discord community.

Top comments (5)

Collapse
 
hajusef_908 profile image
Hajeem Usef

Looking forward to building this, thanks

Collapse
 
nathan_tarbert profile image
Nathan Tarbert CopilotKit

This is awesome, Bonnie, great tutorial!

Collapse
 
alexhales67 profile image
Alex Hales67

Nice!
There seems to be a lot of frameworks popping up, I didn't hear about Microsoft but it makes sense, there are a lot of people in their ecosystem. When did they release it?

Collapse
 
nathan_tarbert profile image
Nathan Tarbert CopilotKit

Alex, Microsoft announced MAF last week at the .NET 10 conf.

Collapse
 
jal_c_68347 profile image
Jalissia_C

Looks very nice, thanks for posting