| name | foundry-hosted-agent-maf |
| description | Author a Microsoft Agent Framework (.NET) agent that is hosted as a Foundry Hosted Agent and speaks AG-UI over the invocations protocol. Use when building, refactoring, or reviewing a .NET agent that must run as a Foundry Hosted Agent and drive a CopilotKit / AG-UI frontend. WHEN: "build a Foundry hosted agent", "Microsoft Agent Framework AG-UI", "host MAF agent on Foundry", "AddAGUI MapAGUI", "AsAIAgent", "agent over invocations protocol", "generative UI agent backend". |
Skill: Author a MAF agent for Foundry Hosted Agents (AG-UI)
This skill captures the validated best-practice pattern for building a
Microsoft Agent Framework (.NET) agent that runs as a Foundry Hosted Agent and
serves the AG-UI protocol over the platform's invocations endpoint.
When to use
- Creating a new .NET agent to host on Foundry that must drive a CopilotKit /
AG-UI frontend (generative UI, shared state, human-in-the-loop).
- Refactoring an agent off the community
AGUI.Server / raw IChatClient /
custom invocation handler onto the official MAF AG-UI hosting stack.
- Reviewing such an agent for correctness before registering a hosted version.
The pattern (do exactly this)
1. Packages (.csproj, Microsoft.NET.Sdk.Web, net10.0)
<PackageReference Include="Microsoft.Agents.AI.OpenAI" Version="1.13.0" />
<PackageReference Include="Microsoft.Agents.AI.Hosting.AGUI.AspNetCore" Version="1.13.0-preview.260703.1" />
<PackageReference Include="Microsoft.Agents.AI.Hosting.AspNetCore" Version="1.13.0-preview.260703.1" />
<PackageReference Include="Azure.AI.OpenAI" Version="2.9.0-beta.1" />
<PackageReference Include="Azure.Identity" Version="1.13.1" />
Do not include AGUI.Server, AGUI.Abstractions,
Azure.AI.AgentServer.Invocations, or a standalone Microsoft.Extensions.AI
pin — the hosting packages bring what you need.
2. Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient();
builder.Services.AddAGUI();
var endpoint = new Uri(builder.Configuration["AZURE_OPENAI_ENDPOINT"]!);
var deployment = builder.Configuration["MODEL_DEPLOYMENT_NAME"] ?? "model-router";
AITool[] tools =
[
AIFunctionFactory.Create(dataTools.QueryData, "query_data"),
AIFunctionFactory.Create(dataTools.ManageTodos, "manage_todos"),
];
AIAgent agent = new AzureOpenAIClient(endpoint, new DefaultAzureCredential())
.GetChatClient(deployment)
.AsIChatClient()
.AsAIAgent(instructions: SystemPrompt, name: "analytics-agent", tools: tools);
var app = builder.Build();
app.MapAGUI("/invocations", agent);
app.MapAGUI("/", agent);
app.MapGet("/readiness", () => Results.Ok(new { status = "ready" }));
app.Run();
3. Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS base
WORKDIR /app
EXPOSE 8088
ENV ASPNETCORE_URLS=http://+:8088 # no library sets the port — you must
Rules & rationale
- Server tools →
AIFunctionFactory.Create(method, "name"). Client tools
(browser-rendered generative UI, HITL) are declared by the frontend, arrive in
the RunAgentInput, and are routed back to the browser automatically by
MapAGUI. Don't implement client tools server-side.
AddAGUI() auto-enables function-invoking behavior — no manual tool loop.
- AG-UI over
invocations is valid because Foundry passes the body through
and streams the response; POST /invocations → text/event-stream satisfies
the contract.
- Model auth is keyless.
DefaultAzureCredential → the hosted agent's Entra
instance identity. The account typically has disableLocalAuth: true, so grant
that identity Cognitive Services OpenAI User + Cognitive Services User.
Verify locally before registering
cd agent
$env:AZURE_OPENAI_ENDPOINT="https://<account>.openai.azure.com/"; $env:MODEL_DEPLOYMENT_NAME="model-router"
az login; dotnet run # listens on :8088
# readiness
curl.exe -sS http://localhost:8088/readiness
# AG-UI run (expect RUN_STARTED / TOOL_CALL_* / TEXT_MESSAGE_* SSE)
'{"threadId":"t1","runId":"r1","messages":[{"id":"m1","role":"user","content":"List the todos"}],"tools":[],"context":[],"state":{},"forwardedProps":{}}' `
| Out-File $env:TEMP\run.json -Encoding ascii -NoNewline
curl.exe -sS -N -X POST http://localhost:8088/invocations -H "Content-Type: application/json" --data-binary "@$env:TEMP\run.json"
Common failures
| Symptom | Cause / fix |
|---|
AsAIAgent not found | Called on ChatClient; add .AsIChatClient() first. |
| Container never becomes ready on Foundry | Port not 8088 / /readiness missing. Set ASPNETCORE_URLS in Dockerfile. |
| Client tool executed on the server | Don't register renderPieChart/scheduleMeeting server-side; leave them to the frontend. |
| 401 calling the model | Agent instance identity lacks Cognitive Services OpenAI User on the account. |
After it works locally, hand off to the foundry-agent-deploy skill to build,
register, and wire the runtime.
See references/checklist.md for a copy-paste review checklist.