A full-stack sample that builds interactive generative UI for an AI agent on the Microsoft stack, adapting the AG-UI pattern to Foundry Hosted Agents.
- Microsoft Agent Framework — authors the agent (C# / .NET 10). Hosted with the official AG-UI ASP.NET stack (
Microsoft.Agents.AI.Hosting.AGUI.AspNetCore:AddAGUI()+MapAGUI()). - AG-UI protocol — the open, event-based standard connecting the agent to the frontend, served over the Foundry
invocationsendpoint. - Foundry Hosted Agents — runs the agent container with managed identity, scaling, and observability.
- CopilotKit — React library adding generative UI, shared state, and human-in-the-loop, plus a Node runtime bridge.
- Azure Static Web Apps (frontend) and Azure App Service (CopilotKit runtime bridge).
Swapping the C# Agent Framework backend for LangGraph or Semantic Kernel would leave the AG-UI endpoint and the entire frontend unchanged — that is the point of AG-UI.
The agent reasons over a sample sales dataset and drives the UI over AG-UI: it renders charts inline (generative UI), keeps a shared todo canvas in sync (bi-directional state), and pauses for the user before acting (human-in-the-loop).
Generative UI — pie chart. The agent calls the server query_data tool, then
the client renderPieChart tool to render the result inline.
Generative UI + shared state — bar chart and todo canvas. A bar chart renders
inline while the Todo Canvas on the right stays in sync via AG-UI STATE_SNAPSHOT
events bound to CopilotKit's useCoAgent.
Human-in-the-loop — meeting scheduler. The run pauses and hands control to the UI; the agent waits for the user to pick a time before continuing.
Browser (React + CopilotKit) Azure Static Web Apps
│ POST /api/copilotkit (CopilotKit v2 method envelope)
▼
CopilotKit runtime (Node/Express) Azure App Service ← holds endpoint + token
│ AG-UI RunAgentInput (SSE back)
▼
Foundry Hosted Agent POST /invocations?api-version=v1 ← Microsoft Agent Framework
│ reason + call server tools, stream AG-UI events ← container :8088, /readiness
▼
Azure OpenAI model deployment (Model Router)
Full write-up: docs/architecture.md.
| Path | What it is |
|---|---|
agent/ |
.NET 10 Microsoft Agent Framework agent, hosted over AG-UI with AddAGUI()/MapAGUI(), containerized for Foundry Hosted Agents (listens on :8088, /readiness). |
runtime/ |
Node/TypeScript CopilotKit runtime bridge (@copilotkit/runtime + @ag-ui/client). Deploys to App Service. |
frontend/ |
Vite + React + CopilotKit app: pie-chart generative UI, shared todo canvas, meeting-scheduler HITL. Deploys to Static Web Apps. |
infra/ |
azd + Bicep: identity, Log Analytics, App Insights, ACR, Foundry account + Model Router model, App Service, Static Web App. |
scripts/ |
register_agent.py (register a Hosted Agent version) and deploy-agent.* (build/push + print the register/wire commands). |
docs/ |
Architecture, deployment, and best-practices playbooks. |
AGENTS.md |
Full reference for AI agents/humans working in the repo. |
- Azure subscription with access to Microsoft Foundry; quota for a B1 App
Service plan and a Model Router deployment (version
2025-11-18, available in East US 2 and Sweden Central). - azd and Azure CLI.
- .NET 10 SDK, Node.js 20+,
Python 3.10+ with
azure-ai-projects+azure-identity.
- Agent (terminal 1):
cd agent export AZURE_OPENAI_ENDPOINT="https://<account>.openai.azure.com/" export MODEL_DEPLOYMENT_NAME="model-router" az login # DefaultAzureCredential uses your CLI login dotnet run # AG-UI on http://localhost:8088/invocations, /readiness
- Runtime (terminal 2):
cd runtime cp .env.example .env # FOUNDRY_AGENT_ENDPOINT=http://localhost:8088/invocations npm install && npm run dev # http://localhost:3000
- Frontend (terminal 3):
cd frontend npm install && npm run dev # http://localhost:5173 (proxies /api/copilotkit -> :3000)
Then try: "Show a pie chart of sales by region", "Add three tasks: review the Americas sales figures, follow up on the APAC pipeline, prepare the quarterly sales deck", and "Schedule a 30-minute meeting".
The full, validated flow is in docs/deployment.md. Summary:
azd auth login
azd up # infra + runtime (App Service) + web (SWA)
# Build the agent image and register the Hosted Agent
./scripts/deploy-agent.ps1 # builds/pushes the image, prints register + wire commands
python scripts/register_agent.py # (update IMAGE tag first) registers a hosted-agent version
# Point the runtime at the invocations endpoint (MUST include api-version)
az webapp config appsettings set -g <rg> -n <runtime-app> --settings `
FOUNDRY_AGENT_ENDPOINT="<project-endpoint>/agents/analytics-agent/endpoint/protocols/invocations?api-version=v1"
az webapp restart -g <rg> -n <runtime-app>Verify through the Static Web App hostname (the runtime App Service returns 401 to direct callers by design):
'{"method":"info"}' | Out-File $env:TEMP\i.json -Encoding ascii -NoNewline
curl.exe -sS -X POST https://<swa-hostname>/api/copilotkit -H "Content-Type: application/json" --data-binary "@$env:TEMP\i.json"Notes: the
azure.ai.agentsazdpostdeployhook error (AZURE_AI_PROJECT_ENDPOINT is not set) is cosmetic — the deploy succeeds. Node App Service cold start takes ~100s.
- No keys in code: the agent and runtime use Microsoft Entra ID managed
identity (
DefaultAzureCredential) with least-privilege roles. - The Foundry account uses
disableLocalAuth: true; the agent's instance identity needsCognitive Services OpenAI User+Cognitive Services User. - The CopilotKit runtime is the only component that holds the agent endpoint and token; the browser never does. The runtime App Service is a locked SWA linked backend.
- Treat agent-supplied component props as untrusted — validate before rendering.
- Layer Azure AI Content Safety and system-prompt guardrails on the model.
See docs/best-practices.md, AGENTS.md,
and the reusable Copilot skills under
.copilot/skills/ (foundry-hosted-agent-maf,
foundry-agent-deploy).
The Microsoft Agent Framework AG-UI hosting packages
(Microsoft.Agents.AI.Hosting.AGUI.AspNetCore etc.) are in preview; the versions
pinned in agent/Agent.csproj are the ones validated here. Check the official
docs for the latest before bumping.


