--- title: Getting Started with AG-UI description: Step-by-step tutorial to build your first AG-UI server and client with Agent Framework zone_pivot_groups: programming-languages author: moonbox3 ms.topic: tutorial ms.author: evmattso ms.date: 04/01/2026 ms.service: agent-framework --- # Getting Started with AG-UI This tutorial demonstrates how to build both server and client applications using the AG-UI protocol with .NET or Python and Agent Framework. You'll learn how to create an AG-UI server that hosts an AI agent and a client that connects to it for interactive conversations. ## What You'll Build By the end of this tutorial, you'll have: - An AG-UI server hosting an AI agent accessible via HTTP - A client application that connects to the server and streams responses - Understanding of how the AG-UI protocol works with Agent Framework ::: zone pivot="programming-language-csharp" ## Prerequisites Before you begin, ensure you have the following: - .NET 8.0 or later - [Azure OpenAI service endpoint and deployment configured](/azure/ai-foundry/openai/how-to/create-resource) - [Azure CLI installed](/cli/azure/install-azure-cli) and [authenticated](/cli/azure/authenticate-azure-cli) - User has the `Cognitive Services OpenAI Contributor` role for the Azure OpenAI resource > [!NOTE] > These samples use Azure OpenAI models. For more information, see [how to deploy Azure OpenAI models with Microsoft Foundry](/azure/ai-foundry/how-to/deploy-models-openai). > [!NOTE] > These samples use `DefaultAzureCredential` for authentication. Make sure you're authenticated with Azure (e.g., via `az login`). For more information, see the [Azure Identity documentation](/dotnet/api/overview/azure/identity-readme). > [!WARNING] > The AG-UI protocol is still under development and subject to change. We will keep these samples updated as the protocol evolves. ## Step 1: Creating an AG-UI Server The AG-UI server hosts your AI agent and exposes it via HTTP endpoints using ASP.NET Core. > [!NOTE] > The server project requires the `Microsoft.NET.Sdk.Web` SDK. If you're creating a new project from scratch, use `dotnet new web` or ensure your `.csproj` file uses `` instead of `Microsoft.NET.Sdk`. ### Install Required Packages Install the necessary packages for the server: ```bash dotnet add package Microsoft.Agents.AI.Hosting.AGUI.AspNetCore --prerelease dotnet add package Azure.AI.Projects --prerelease dotnet add package Azure.Identity dotnet add package Microsoft.Agents.AI.Foundry --prerelease ``` > [!NOTE] > The `Microsoft.Agents.AI.Foundry` package is required for the `AsAIAgent()` extension method that creates an Agent Framework agent from an `AIProjectClient`. ### Server Code Create a file named `Program.cs`: ```csharp // Copyright (c) Microsoft. All rights reserved. using Azure.AI.Projects; using Azure.Identity; using Microsoft.Agents.AI; using Microsoft.Agents.AI.Hosting.AGUI.AspNetCore; WebApplicationBuilder builder = WebApplication.CreateBuilder(args); builder.Services.AddHttpClient().AddLogging(); builder.Services.AddAGUI(); WebApplication app = builder.Build(); string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"] ?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set."); // Create the AI agent AIAgent agent = new AIProjectClient( new Uri(endpoint), new DefaultAzureCredential()) .AsAIAgent( model: deploymentName, name: "AGUIAssistant", instructions: "You are a helpful assistant."); // Map the AG-UI agent endpoint app.MapAGUI("/", agent); await app.RunAsync(); ``` > [!WARNING] > `DefaultAzureCredential` is convenient for development but requires careful consideration in production. In production, consider using a specific credential (e.g., `ManagedIdentityCredential`) to avoid latency issues, unintended credential probing, and potential security risks from fallback mechanisms. ### Key Concepts - **`AddAGUI`**: Registers AG-UI services with the dependency injection container - **`MapAGUI`**: Extension method that registers the AG-UI endpoint with automatic request/response handling and SSE streaming - **`AsAIAgent`**: Creates an Agent Framework agent from an `AIProjectClient` with a specified model and instructions - **ASP.NET Core Integration**: Uses ASP.NET Core's native async support for streaming responses - **Instructions**: The agent is created with default instructions, which can be overridden by client messages - **Configuration**: `AIProjectClient` with `DefaultAzureCredential` provides secure authentication ### Configure and Run the Server Set the required environment variables: ```bash export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/" export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini" ``` Run the server: ```bash dotnet run --urls http://localhost:8888 ``` The server will start listening on `http://localhost:8888`. > [!NOTE] > Keep this server running while you set up and run the client in Step 2. Both the server and client need to run simultaneously for the complete system to work. ## Step 2: Creating an AG-UI Client The AG-UI client connects to the remote server and displays streaming responses. > [!IMPORTANT] > Before running the client, ensure the AG-UI server from Step 1 is running at `http://localhost:8888`. ### Install Required Packages Install the AG-UI client library: ```bash dotnet add package Microsoft.Agents.AI.AGUI --prerelease dotnet add package Microsoft.Agents.AI --prerelease ``` > [!NOTE] > The `Microsoft.Agents.AI` package provides the `AsAIAgent()` extension method. ### Client Code Create a file named `Program.cs`: ```csharp // Copyright (c) Microsoft. All rights reserved. using Microsoft.Agents.AI; using Microsoft.Agents.AI.AGUI; using Microsoft.Extensions.AI; string serverUrl = Environment.GetEnvironmentVariable("AGUI_SERVER_URL") ?? "http://localhost:8888"; Console.WriteLine($"Connecting to AG-UI server at: {serverUrl}\n"); // Create the AG-UI client agent using HttpClient httpClient = new() { Timeout = TimeSpan.FromSeconds(60) }; AGUIChatClient chatClient = new(httpClient, serverUrl); AIAgent agent = chatClient.AsAIAgent( name: "agui-client", description: "AG-UI Client Agent"); AgentSession session = await agent.CreateSessionAsync(); List messages = [ new(ChatRole.System, "You are a helpful assistant.") ]; try { while (true) { // Get user input Console.Write("\nUser (:q or quit to exit): "); string? message = Console.ReadLine(); if (string.IsNullOrWhiteSpace(message)) { Console.WriteLine("Request cannot be empty."); continue; } if (message is ":q" or "quit") { break; } messages.Add(new ChatMessage(ChatRole.User, message)); // Stream the response bool isFirstUpdate = true; string? threadId = null; await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, session)) { ChatResponseUpdate chatUpdate = update.AsChatResponseUpdate(); // First update indicates run started if (isFirstUpdate) { threadId = chatUpdate.ConversationId; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"\n[Run Started - Thread: {chatUpdate.ConversationId}, Run: {chatUpdate.ResponseId}]"); Console.ResetColor(); isFirstUpdate = false; } // Display streaming text content foreach (AIContent content in update.Contents) { if (content is TextContent textContent) { Console.ForegroundColor = ConsoleColor.Cyan; Console.Write(textContent.Text); Console.ResetColor(); } else if (content is ErrorContent errorContent) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"\n[Error: {errorContent.Message}]"); Console.ResetColor(); } } } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine($"\n[Run Finished - Thread: {threadId}]"); Console.ResetColor(); } } catch (Exception ex) { Console.WriteLine($"\nAn error occurred: {ex.Message}"); } ``` ### Key Concepts - **Server-Sent Events (SSE)**: The protocol uses SSE for streaming responses - **AGUIChatClient**: Client class that connects to AG-UI servers and implements `IChatClient` - **AsAIAgent**: Extension method on `AGUIChatClient` to create an agent from the client - **RunStreamingAsync**: Streams responses as `AgentResponseUpdate` objects - **AsChatResponseUpdate**: Extension method to access chat-specific properties like `ConversationId` and `ResponseId` - **Session Management**: The `AgentSession` maintains conversation context across requests - **Content Types**: Responses include `TextContent` for messages and `ErrorContent` for errors ### Configure and Run the Client Optionally set a custom server URL: ```bash export AGUI_SERVER_URL="http://localhost:8888" ``` Run the client in a separate terminal (ensure the server from Step 1 is running): ```bash dotnet run ``` ## Step 3: Testing the Complete System With both the server and client running, you can now test the complete system. ### Expected Output ``` $ dotnet run Connecting to AG-UI server at: http://localhost:8888 User (:q or quit to exit): What is 2 + 2? [Run Started - Thread: thread_abc123, Run: run_xyz789] 2 + 2 equals 4. [Run Finished - Thread: thread_abc123] User (:q or quit to exit): Tell me a fun fact about space [Run Started - Thread: thread_abc123, Run: run_def456] Here's a fun fact: A day on Venus is longer than its year! Venus takes about 243 Earth days to rotate once on its axis, but only about 225 Earth days to orbit the Sun. [Run Finished - Thread: thread_abc123] User (:q or quit to exit): :q ``` ### Color-Coded Output The client displays different content types with distinct colors: - **Yellow**: Run started notifications - **Cyan**: Agent text responses (streamed in real-time) - **Green**: Run completion notifications - **Red**: Error messages ## How It Works ### Server-Side Flow 1. Client sends HTTP POST request with messages 2. ASP.NET Core endpoint receives the request via `MapAGUI` 3. Agent processes the messages using Agent Framework 4. Responses are converted to AG-UI events 5. Events are streamed back as Server-Sent Events (SSE) 6. Connection closes when the run completes ### Client-Side Flow 1. `AGUIChatClient` sends HTTP POST request to server endpoint 2. Server responds with SSE stream 3. Client parses incoming events into `AgentResponseUpdate` objects 4. Each update is displayed based on its content type 5. `ConversationId` is captured for conversation continuity 6. Stream completes when run finishes ### Protocol Details The AG-UI protocol uses: - HTTP POST for sending requests - Server-Sent Events (SSE) for streaming responses - JSON for event serialization - Thread IDs (as `ConversationId`) for maintaining conversation context - Run IDs (as `ResponseId`) for tracking individual executions ## Next Steps Now that you understand the basics of AG-UI, you can: - **[Add Backend Tools](backend-tool-rendering.md)**: Create custom function tools for your domain ## Additional Resources - [AG-UI Overview](index.md) - [Agent Framework Documentation](../../overview/index.md) - [AG-UI Protocol Specification](https://docs.ag-ui.com/) ::: zone-end ::: zone pivot="programming-language-python" ## Prerequisites Before you begin, ensure you have the following: - Python 3.10 or later - Node.js 18 or later (for the CopilotKit frontend) - [Azure OpenAI service endpoint and deployment configured](/azure/ai-foundry/openai/how-to/create-resource) - [Azure CLI installed](/cli/azure/install-azure-cli) and [authenticated](/cli/azure/authenticate-azure-cli) - User has the `Cognitive Services OpenAI Contributor` role for the Azure OpenAI resource > [!NOTE] > These samples use Azure OpenAI models. For more information, see [how to deploy Azure OpenAI models with Foundry](/azure/ai-foundry/how-to/deploy-models-openai). > [!NOTE] > These samples use `AzureCliCredential` for authentication. Make sure you're authenticated with Azure (e.g., via `az login`). For more information, see the [Azure Identity documentation](/python/api/azure-identity/azure.identity.defaultazurecredential). > [!WARNING] > The AG-UI protocol is still under development and subject to change. We will keep these samples updated as the protocol evolves. This quickstart takes the shortest path to a running app: install the packages, expose an agent over AG-UI with FastAPI, and point a [CopilotKit](https://copilotkit.ai/) React frontend at it. For a language-agnostic client (a Python `AGUIChatClient` or `curl`), see [Backend Tool Rendering](backend-tool-rendering.md). ## Step 1: Install the Packages Install the AG-UI integration on the agent (server) side: ```bash pip install agent-framework-ag-ui --pre ``` Or using uv: ```bash uv pip install agent-framework-ag-ui --prerelease=allow ``` This installs `agent-framework-core`, `fastapi`, and `uvicorn` as dependencies. Install the CopilotKit packages on the frontend side (from your React or Next.js app): ```bash npm install @copilotkit/react-core @copilotkit/react-ui @copilotkit/runtime @ag-ui/client ``` ## Step 2: Define and Expose an Agent Create a file named `server.py`. Define an Agent Framework agent, wrap it in an `AgentFrameworkAgent`, and register it as an AG-UI endpoint on a FastAPI app. ```python """AG-UI server exposed to a CopilotKit frontend.""" import os from agent_framework import Agent from agent_framework.openai import OpenAIChatCompletionClient from agent_framework_ag_ui import AgentFrameworkAgent, add_agent_framework_fastapi_endpoint from azure.identity import AzureCliCredential from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware endpoint = os.environ["AZURE_OPENAI_ENDPOINT"] deployment_name = os.environ["AZURE_OPENAI_CHAT_COMPLETION_MODEL"] chat_client = OpenAIChatCompletionClient( model=deployment_name, azure_endpoint=endpoint, api_version=os.getenv("AZURE_OPENAI_API_VERSION"), credential=AzureCliCredential(), ) # The base agent handles reasoning and tool calls. base_agent = Agent( name="AGUIAssistant", instructions="You are a helpful assistant.", client=chat_client, ) # AgentFrameworkAgent adapts the agent to the AG-UI protocol and is the # entry point for generative UI features (tools, shared state, and more). agent = AgentFrameworkAgent( agent=base_agent, name="MyAgent", description="A helpful assistant exposed over AG-UI.", ) app = FastAPI(title="AG-UI Server") # Allow the frontend's browser requests during local development. app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) # Register the agent at the root path. add_agent_framework_fastapi_endpoint(app, agent, "/") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="127.0.0.1", port=8000) ``` ### Key Concepts - **`Agent`**: The Agent Framework agent that reasons over messages and calls tools. - **`AgentFrameworkAgent`**: A lightweight wrapper that adapts the agent to the AG-UI protocol. It's also where you enable generative UI features such as `state_schema` and `predict_state_config`. - **`add_agent_framework_fastapi_endpoint`**: Registers the agent as a FastAPI endpoint with automatic request handling and SSE streaming. Set the required environment variables and run the server: ```bash export AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/" export AZURE_OPENAI_CHAT_COMPLETION_MODEL="gpt-4o-mini" python server.py ``` The server listens on `http://127.0.0.1:8000`. Keep it running while you set up the frontend. ## Step 3: Point a CopilotKit Frontend at the Agent CopilotKit connects to your AG-UI endpoint through a runtime route, then renders a chat UI with a provider and a chat component. First, add a runtime route that proxies to your agent. In a Next.js App Router project, create `app/api/copilotkit/route.ts`: ```ts import { CopilotRuntime, copilotRuntimeNextJSAppRouterEndpoint, ExperimentalEmptyAdapter } from "@copilotkit/runtime"; import { HttpAgent } from "@ag-ui/client"; import { NextRequest } from "next/server"; // Point the runtime at the FastAPI endpoint from Step 2. const runtime = new CopilotRuntime({ agents: { my_agent: new HttpAgent({ url: "http://127.0.0.1:8000/" }), }, }); export const POST = async (req: NextRequest) => { const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({ runtime, serviceAdapter: new ExperimentalEmptyAdapter(), endpoint: "/api/copilotkit", }); return handleRequest(req); }; ``` Then render the chat UI. In `app/page.tsx`: ```tsx "use client"; import { CopilotKit, CopilotChat } from "@copilotkit/react-core/v2"; export default function Page() { return ( ); } ``` The `agent` prop, the `agents` key in the runtime, and each hook's `agentId` all use the same identifier (`my_agent` here). > [!TIP] > Frontend tools and UI renderers you register in the browser are forwarded to your agent automatically over the AG-UI protocol, so all the generative UI patterns below work without extra server wiring. ## Step 4: Run It With the agent server running from Step 2, start your frontend in a separate terminal: ```bash npm run dev ``` Open the app, ask the assistant a question, and watch the response stream in token by token. You now have a working AG-UI + Agent Framework app with a CopilotKit UI. ## Dive Deeper The quickstart gets you a streaming chat. From here, add capabilities as you need them: - **Want tools your agent runs on the server?** See [Backend Tool Rendering](backend-tool-rendering.md). - **Want the agent to call actions that run in the browser?** See [Frontend Tools](frontend-tools.md). - **Want approval workflows before an action runs?** See [Human-in-the-Loop](human-in-the-loop.md). - **Want to synchronize state between the agent and the UI?** See [State Management](state-management.md). - **Want to render rich, custom UI from tool calls and agent state?** See [Generative UI: A Spectrum of UI Control](#generative-ui-a-spectrum-of-ui-control) below. - **Want the full CopilotKit React setup, hooks reference, and components?** See the [Microsoft Agent Framework integration for CopilotKit](https://docs.copilotkit.ai/microsoft-agent-framework). - **Want to explore features interactively?** See [Testing with the AG-UI Dojo](testing-with-dojo.md). ## Generative UI: A Spectrum of UI Control *Generative UI* is the ability to render agent activity as real interface, not just text. AG-UI and CopilotKit support a spectrum of approaches, from the agent driving everything with zero frontend code to your app composing UI freely. Pick the lowest rung that meets your need; each one gives your app more control at the cost of more frontend code. | Rung | Pattern | Who designs the UI | Frontend code | | --- | --- | --- | --- | | 1 | [Automatic tool rendering](#1-automatic-tool-rendering) | Built-in default renderer | None | | 2 | [Custom tool rendering](#2-custom-tool-rendering) | Your app, per named tool | `useRenderTool` | | 3 | [Catch-all rendering](#3-catch-all-rendering) | Your app, one renderer for all tools | `useDefaultRenderTool` | | 4 | [Frontend tools](#4-frontend-tools) | Your app runs browser actions | `useFrontendTool` | | 5 | [State-driven rendering](#5-state-driven-rendering) | Your app renders live agent state | `useAgent` | | 6 | [Your components](#6-your-components) | Your app's React components | `useComponent` | | 7 | [Open generative UI](#7-open-generative-ui) | The agent composes UI | `openGenerativeUI` | All snippets below build on the `server.py` and frontend from the quickstart. On the agent side you add tools or state; on the frontend you add a hook. This spectrum intentionally omits the fully declarative (A2UI) approach. ### 1. Automatic Tool Rendering Define a tool on your agent and the default chat UI renders each call (arguments, status, and result) with no frontend code. Use this when you want zero-effort feedback about what the agent is doing. Add a backend tool to the agent in `server.py`: ```python from typing import Annotated from agent_framework import Agent, tool from pydantic import Field @tool def get_weather( location: Annotated[str, Field(description="The location to get weather for")], ) -> str: return f"The weather for {location} is 70 degrees." base_agent = Agent( name="AGUIAssistant", instructions="You are a helpful assistant. Use tools when relevant.", client=chat_client, tools=[get_weather], ) ``` No frontend changes are needed; `` renders the tool call with its built-in default renderer. ### 2. Custom Tool Rendering Supply a branded component for a specific tool. The renderer's `name` must match the tool name. Use this when a tool deserves a purpose-built card instead of the generic view. The agent keeps the same `get_weather` tool from rung 1. On the frontend, register a renderer with [`useRenderTool`](https://docs.copilotkit.ai/microsoft-agent-framework/generative-ui/tool-rendering): ```tsx import { useRenderTool } from "@copilotkit/react-core/v2"; import { z } from "zod"; useRenderTool({ name: "get_weather", parameters: z.object({ location: z.string() }), render: ({ status, parameters }) => (
{status !== "complete" ? `Checking weather for ${parameters.location}…` : `Weather for ${parameters.location} is ready.`}
), }); ``` ### 3. Catch-all Rendering Register a single renderer that paints every tool call not claimed by a named renderer. Use this for a consistent look across many tools without writing one component per tool. ```tsx import { useDefaultRenderTool } from "@copilotkit/react-core/v2"; // A convenience wrapper around useRenderTool({ name: "*", ... }). useDefaultRenderTool({ render: ({ name, status, parameters, result }) => (
{name}: {status} {result ?
{JSON.stringify(result, null, 2)}
: null}
), }); ``` ### 4. Frontend Tools Let the agent call an action that runs in the user's browser, such as reading component state, calling a browser API, or triggering an animation. The handler can be async. Register it with [`useFrontendTool`](https://docs.copilotkit.ai/microsoft-agent-framework/frontend-tools); CopilotKit forwards it to the agent over AG-UI, so no backend tool definition is required. ```tsx import { useFrontendTool } from "@copilotkit/react-core/v2"; import { z } from "zod"; useFrontendTool({ name: "change_background", description: "Change the page background to any valid CSS background value.", parameters: z.object({ background: z.string() }), handler: async ({ background }) => { document.body.style.background = background; return { status: "success" }; }, }); ``` ### 5. State-driven Rendering Render the agent's live state (a plan, a progress list, a draft document) as it updates. Declare a `state_schema`, update state from a tool, and subscribe to it on the frontend. On the agent side, use `state_update` to publish state after each transition and pass `state_schema` to the wrapper: ```python from typing import Annotated from agent_framework import Agent, tool from agent_framework_ag_ui import AgentFrameworkAgent, state_update from pydantic import Field STATE_SCHEMA: dict[str, object] = { "steps": { "type": "array", "items": { "type": "object", "properties": { "title": {"type": "string"}, "status": {"type": "string", "enum": ["pending", "in_progress", "completed"]}, }, }, "description": "Ordered plan steps with live status.", } } @tool(name="set_steps", description="Publish the full plan and step statuses. Call on every transition.") def set_steps( steps: Annotated[list[dict], Field(description="The complete list of steps with title and status.")], ): return state_update(text=f"Published {len(steps)} step(s).", state={"steps": steps}) base_agent = Agent( name="Planner", instructions="Plan the work as steps, then walk each step pending → in_progress → completed by calling set_steps.", client=chat_client, tools=[set_steps], ) agent = AgentFrameworkAgent( agent=base_agent, name="PlannerAgent", description="Streams a live plan to the UI.", state_schema=STATE_SCHEMA, ) ``` On the frontend, read the state with [`useAgent`](https://docs.copilotkit.ai/microsoft-agent-framework/generative-ui/state-rendering): ```tsx import { useAgent } from "@copilotkit/react-core/v2"; // For type safety, define a type matching your agent's state snapshot. type AgentState = { steps: { title: string; status: string }[] }; const { agent } = useAgent({ agentId: "my_agent" }); return (
    {agent.state?.steps?.map((step, i) => (
  • {step.status === "completed" ? "✅" : "⏳"} {step.title}
  • ))}
); ``` ### 6. Your Components Register your own React components and let the agent decide when to render them. Start display-only, then make them interactive by letting the component send a value back to the agent. Register components with [`useComponent`](https://docs.copilotkit.ai/microsoft-agent-framework/generative-ui/your-components/display-only); CopilotKit forwards them to the agent as callable tools, so instruct the agent to call them by name. ```python base_agent = Agent( name="ChartAssistant", instructions=( "When the user asks for a chart, call render_bar_chart with a title and a " "data array of {label, value} items." ), client=chat_client, # No backend tools; the components are registered on the frontend and # forwarded to the agent as tools it can call by name. tools=[], ) ``` Display-only: the agent supplies the data, the component renders it: ```tsx import { useComponent } from "@copilotkit/react-core/v2"; import { z } from "zod"; useComponent({ name: "render_bar_chart", description: "Display a bar chart with labeled numeric values.", parameters: z.object({ title: z.string(), data: z.array(z.object({ label: z.string(), value: z.number() })), }), render: BarChart, // your component }); ``` Interactive: the component collects input and calls `respond` to return it to the agent: ```tsx useComponent({ name: "pick_meeting_time", description: "Ask the user to choose a meeting time.", parameters: z.object({ options: z.array(z.string()) }), render: ({ respond, status, args }) => ( ), }); ``` ### 7. Open Generative UI Let the agent compose UI on the fly. CopilotKit auto-registers a `generateSandboxedUi` frontend tool; when the agent calls it, the streamed HTML and CSS is mounted inside a sandboxed iframe. Enable it on both the runtime and the provider, with no per-component code required. In the runtime route, list the agents that may generate UI: ```ts const runtime = new CopilotRuntime({ agents: { my_agent: new HttpAgent({ url: "http://127.0.0.1:8000/" }) }, openGenerativeUI: { agents: ["my_agent"] }, }); ``` In the provider, turn it on: ```tsx ``` On the agent side, instruct it to call the tool: ```python base_agent = Agent( name="UIAssistant", instructions="On each turn, call generateSandboxedUi once to build a self-contained HTML + CSS widget that answers the user.", client=chat_client, tools=[], ) ``` For an advanced variant where the generated UI calls back into host functions you define, pass those functions to the provider with `openGenerativeUI={{ sandboxFunctions }}`. See [Open Generative UI](https://docs.copilotkit.ai/microsoft-agent-framework) in the CopilotKit docs. ## Additional Resources - [AG-UI Overview](index.md) - [Agent Framework Documentation](../../overview/index.md) - [Microsoft Agent Framework integration for CopilotKit](https://docs.copilotkit.ai/microsoft-agent-framework) - [AG-UI Protocol Specification](https://docs.ag-ui.com/) ::: zone-end