Skip to content

Commit 1963da5

Browse files
authored
.NET: Hosting libraries documentation (#765)
* init docs * briefly about implementation * a2a doc + sample * cleanup * nit * openai integration * language fixes * adjust * tags * another fix * build report * feedback 1 * add different sections for setting vars in tab * fix tab * correct * wip * fix tabs? * link with anchor * finish of tabs * fix tabs ??? * address PR comments 1 * reformat installation of packages * fix links * nits * simplify * nit * fixes
1 parent 89cfba0 commit 1963da5

5 files changed

Lines changed: 900 additions & 0 deletions

File tree

agent-framework/TOC.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ items:
1616
href: user-guide/model-context-protocol/TOC.yml
1717
- name: Workflows
1818
href: user-guide/workflows/TOC.yml
19+
- name: Hosting
20+
href: user-guide/hosting/TOC.yml
1921
- name: Integrations
2022
items:
2123
- name: AG-UI
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
- name: Overview
2+
href: index.md
3+
- name: A2A Integration
4+
href: agent-to-agent-integration.md
5+
- name: OpenAI Integration
6+
href: openai-integration.md
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
---
2+
title: A2A Integration
3+
description: Learn how to expose Microsoft Agent Framework agents using the Agent-to-Agent (A2A) protocol for inter-agent communication.
4+
author: dmkorolev
5+
ms.service: agent-framework
6+
ms.topic: tutorial
7+
ms.date: 11/11/2025
8+
ms.author: dmkorolev
9+
---
10+
11+
# A2A Integration
12+
13+
> [!NOTE]
14+
> This tutorial describes A2A integration in .NET apps; Python integration is in the works...
15+
16+
The Agent-to-Agent (A2A) protocol enables standardized communication between agents, allowing agents built with different frameworks and technologies to communicate seamlessly. The `Microsoft.Agents.AI.Hosting.A2A.AspNetCore` library provides ASP.NET Core integration for exposing your agents via the A2A protocol.
17+
18+
**NuGet Packages:**
19+
- [Microsoft.Agents.AI.Hosting.A2A](https://www.nuget.org/packages/Microsoft.Agents.AI.Hosting.A2A)
20+
- [Microsoft.Agents.AI.Hosting.A2A.AspNetCore](https://www.nuget.org/packages/Microsoft.Agents.AI.Hosting.A2A.AspNetCore)
21+
22+
## What is A2A?
23+
24+
A2A is a standardized protocol that supports:
25+
26+
- **Agent discovery** through agent cards
27+
- **Message-based communication** between agents
28+
- **Long-running agentic processes** via tasks
29+
- **Cross-platform interoperability** between different agent frameworks
30+
31+
For more information, see the [A2A protocol specification](https://a2a-protocol.org/latest/).
32+
33+
## Example
34+
35+
This minimal example shows how to expose an agent via A2A. The sample includes OpenAPI and Swagger dependencies to simplify testing.
36+
37+
#### 1. Create an ASP.NET Core Web API project
38+
39+
Create a new ASP.NET Core Web API project or use an existing one.
40+
41+
#### 2. Install required dependencies
42+
43+
Install the following packages:
44+
45+
## [.NET CLI](#tab/dotnet-cli)
46+
47+
Run the following commands in your project directory to install the required NuGet packages:
48+
49+
```bash
50+
# Hosting.A2A.AspNetCore for A2A protocol integration
51+
dotnet add package Microsoft.Agents.AI.Hosting.A2A.AspNetCore --prerelease
52+
53+
# Libraries to connect to Azure OpenAI
54+
dotnet add package Azure.AI.OpenAI --prerelease
55+
dotnet add package Azure.Identity
56+
dotnet add package Microsoft.Extensions.AI
57+
dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease
58+
59+
# Swagger to test app
60+
dotnet add package Microsoft.AspNetCore.OpenApi
61+
dotnet add package Swashbuckle.AspNetCore
62+
```
63+
## [Package Reference](#tab/package-reference)
64+
65+
Add the following `<PackageReference>` elements to your `.csproj` file within an `<ItemGroup>`:
66+
67+
```xml
68+
<ItemGroup>
69+
<!-- Hosting.A2A.AspNetCore for A2A protocol integration -->
70+
<PackageReference Include="Microsoft.Agents.AI.Hosting.A2A.AspNetCore" Version="1.0.0-preview.251110.2" />
71+
72+
<!-- Libraries to connect to Azure OpenAI -->
73+
<PackageReference Include="Azure.AI.OpenAI" Version="2.5.0-beta.1" />
74+
<PackageReference Include="Azure.Identity" Version="1.17.0" />
75+
<PackageReference Include="Microsoft.Extensions.AI" Version="9.10.2" />
76+
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.10.2-preview.1.25552.1" />
77+
78+
<!-- Swagger to test app -->
79+
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
80+
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.1" />
81+
</ItemGroup>
82+
```
83+
84+
---
85+
86+
87+
#### 3. Configure Azure OpenAI connection
88+
89+
The application requires an Azure OpenAI connection. Configure the endpoint and deployment name using `dotnet user-secrets` or environment variables.
90+
You can also simply edit the `appsettings.json`, but that's not recommended for the apps deployed in production since some of the data can be considered to be secret.
91+
92+
## [User-Secrets](#tab/user-secrets)
93+
```bash
94+
dotnet user-secrets set "AZURE_OPENAI_ENDPOINT" "https://<your-openai-resource>.openai.azure.com/"
95+
dotnet user-secrets set "AZURE_OPENAI_DEPLOYMENT_NAME" "gpt-4o-mini"
96+
```
97+
## [ENV Windows](#tab/env-windows)
98+
```powershell
99+
$env:AZURE_OPENAI_ENDPOINT = "https://<your-openai-resource>.openai.azure.com/"
100+
$env:AZURE_OPENAI_DEPLOYMENT_NAME = "gpt-4o-mini"
101+
```
102+
## [ENV unix](#tab/env-unix)
103+
```bash
104+
export AZURE_OPENAI_ENDPOINT="https://<your-openai-resource>.openai.azure.com/"
105+
export AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini"
106+
```
107+
## [appsettings](#tab/appsettings)
108+
```json
109+
"AZURE_OPENAI_ENDPOINT": "https://<your-openai-resource>.openai.azure.com/",
110+
"AZURE_OPENAI_DEPLOYMENT_NAME": "gpt-4o-mini"
111+
```
112+
113+
---
114+
115+
116+
#### 4. Add the code to Program.cs
117+
118+
Replace the contents of `Program.cs` with the following code and run the application:
119+
```csharp
120+
using A2A.AspNetCore;
121+
using Azure.AI.OpenAI;
122+
using Azure.Identity;
123+
using Microsoft.Agents.AI.Hosting;
124+
using Microsoft.Extensions.AI;
125+
126+
var builder = WebApplication.CreateBuilder(args);
127+
128+
builder.Services.AddOpenApi();
129+
builder.Services.AddSwaggerGen();
130+
131+
string endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"]
132+
?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
133+
string deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"]
134+
?? throw new InvalidOperationException("AZURE_OPENAI_DEPLOYMENT_NAME is not set.");
135+
136+
// Register the chat client
137+
IChatClient chatClient = new AzureOpenAIClient(
138+
new Uri(endpoint),
139+
new DefaultAzureCredential())
140+
.GetChatClient(deploymentName)
141+
.AsIChatClient();
142+
builder.Services.AddSingleton(chatClient);
143+
144+
// Register an agent
145+
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate.");
146+
147+
var app = builder.Build();
148+
149+
app.MapOpenApi();
150+
app.UseSwagger();
151+
app.UseSwaggerUI();
152+
153+
// Expose the agent via A2A protocol. You can also customize the agentCard
154+
app.MapA2A(pirateAgent, path: "/a2a/pirate", agentCard: new()
155+
{
156+
Name = "Pirate Agent",
157+
Description = "An agent that speaks like a pirate.",
158+
Version = "1.0"
159+
});
160+
161+
app.Run();
162+
```
163+
164+
### Testing the Agent
165+
166+
Once the application is running, you can test the A2A agent using the following `.http` file or through Swagger UI.
167+
168+
The input format complies with the A2A specification. You can provide values for:
169+
- `messageId` - A unique identifier for this specific message. You can create your own ID (e.g., a GUID) or set it to `null` to let the agent generate one automatically.
170+
- `contextId` - The conversation identifier. Provide your own ID to start a new conversation or continue an existing one by reusing a previous `contextId`. The agent will maintain conversation history for the same `contextId`. Agent will generate one for you as well, if none is provided.
171+
172+
```http
173+
# Send A2A request to the pirate agent
174+
POST {{baseAddress}}/a2a/pirate/v1/message:stream
175+
Content-Type: application/json
176+
{
177+
"message": {
178+
"kind": "message",
179+
"role": "user",
180+
"parts": [
181+
{
182+
"kind": "text",
183+
"text": "Hey pirate! Tell me where have you been",
184+
"metadata": {}
185+
}
186+
],
187+
"messageId": null,
188+
"contextId": "foo"
189+
}
190+
}
191+
```
192+
_Note: Replace `{{baseAddress}}` with your server endpoint._
193+
194+
This request returns the following JSON response:
195+
```json
196+
{
197+
"kind": "message",
198+
"role": "agent",
199+
"parts": [
200+
{
201+
"kind": "text",
202+
"text": "Arrr, ye scallywag! Ye’ll have to tell me what yer after, or be I walkin’ the plank? 🏴‍☠️"
203+
}
204+
],
205+
"messageId": "chatcmpl-CXtJbisgIJCg36Z44U16etngjAKRk",
206+
"contextId": "foo"
207+
}
208+
```
209+
210+
The response includes the `contextId` (conversation identifier), `messageId` (message identifier), and the actual content from the pirate agent.
211+
212+
## AgentCard Configuration
213+
214+
The `AgentCard` provides metadata about your agent for discovery and integration:
215+
```csharp
216+
app.MapA2A(agent, "/a2a/my-agent", agentCard: new()
217+
{
218+
Name = "My Agent",
219+
Description = "A helpful agent that assists with tasks.",
220+
Version = "1.0",
221+
});
222+
```
223+
224+
You can access the agent card by sending this request:
225+
```http
226+
# Send A2A request to the pirate agent
227+
GET {{baseAddress}}/a2a/pirate/v1/card
228+
```
229+
_Note: Replace `{{baseAddress}}` with your server endpoint._
230+
231+
### AgentCard Properties
232+
233+
- **Name**: Display name of the agent
234+
- **Description**: Brief description of the agent
235+
- **Version**: Version string for the agent
236+
- **Url**: Endpoint URL (automatically assigned if not specified)
237+
- **Capabilities**: Optional metadata about streaming, push notifications, and other features
238+
239+
## Exposing Multiple Agents
240+
241+
You can expose multiple agents in a single application, as long as their endpoints don't collide. Here's an example:
242+
243+
```csharp
244+
var mathAgent = builder.AddAIAgent("math", instructions: "You are a math expert.");
245+
var scienceAgent = builder.AddAIAgent("science", instructions: "You are a science expert.");
246+
247+
app.MapA2A(mathAgent, "/a2a/math");
248+
app.MapA2A(scienceAgent, "/a2a/science");
249+
```
250+
251+
## See Also
252+
253+
- [Hosting Overview](index.md)
254+
- [OpenAI Integration](openai-integration.md)
255+
- [A2A Protocol Specification](https://a2a-protocol.org/latest/)
256+
- [Agent Discovery](https://github.com/a2aproject/A2A/blob/main/docs/topics/agent-discovery.md)
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
---
2+
title: Hosting Overview
3+
description: Learn how to host AI agents in ASP.NET Core applications using the Agent Framework hosting libraries.
4+
author: dmkorolev
5+
ms.service: agent-framework
6+
ms.topic: overview
7+
ms.date: 11/11/2025
8+
ms.author: dmkorolev
9+
---
10+
11+
# Hosting AI Agents in ASP.NET Core
12+
13+
The Agent Framework provides a comprehensive set of hosting libraries that enable you to seamlessly integrate AI agents into ASP.NET Core applications. These libraries simplify the process of registering, configuring, and exposing agents through various protocols and interfaces.
14+
15+
## Overview
16+
As you may already know from the [AI Agents Overview](../../overview/agent-framework-overview.md#ai-agents), `AIAgent` is the fundamental concept of the Agent Framework. It defines an "LLM wrapper" that processes user inputs, makes decisions, calls tools, and performs additional work to execute actions and generate responses.
17+
18+
However, exposing AI agents from your ASP.NET Core application is not trivial. The Agent Framework hosting libraries solve this by registering AI agents in a dependency injection container, allowing you to resolve and use them in your application services. Additionally, the hosting libraries enable you to manage agent dependencies, such as tools and thread storage, from the same dependency injection container.
19+
20+
Agents can be hosted alongside your application infrastructure, independent of the protocols they use. Similarly, workflows can be hosted and leverage your application's common infrastructure.
21+
22+
## Core Hosting Library
23+
24+
The `Microsoft.Agents.AI.Hosting` library is the foundation for hosting AI agents in ASP.NET Core. It provides the primary APIs for agent registration and configuration.
25+
26+
In the context of ASP.NET Core applications, `IHostApplicationBuilder` is the fundamental type that represents the builder for hosted applications and services. It manages configuration, logging, lifetime, and more. The Agent Framework hosting libraries provide extensions for `IHostApplicationBuilder` to register and configure AI agents and workflows.
27+
28+
### Key APIs
29+
30+
Before configuring agents or workflows, developer needs the `IChatClient` registered in the dependency injection container.
31+
In the examples below, it is registered as keyed singleton under name `chat-model`. This is an example of `IChatClient` registration:
32+
```csharp
33+
// endpoint is of 'https://<your-own-foundry-endpoint>.openai.azure.com/' format
34+
// deploymentName is `gpt-4o-mini` for example
35+
36+
IChatClient chatClient = new AzureOpenAIClient(
37+
new Uri(endpoint),
38+
new DefaultAzureCredential())
39+
.GetChatClient(deploymentName)
40+
.AsIChatClient();
41+
builder.Services.AddSingleton(chatClient);
42+
```
43+
44+
#### AddAIAgent
45+
46+
Register an AI agent with dependency injection:
47+
48+
```csharp
49+
var pirateAgent = builder.AddAIAgent(
50+
"pirate",
51+
instructions: "You are a pirate. Speak like a pirate",
52+
description: "An agent that speaks like a pirate.",
53+
chatClientServiceKey: "chat-model");
54+
```
55+
56+
The `AddAIAgent()` method returns an `IHostedAgentBuilder`, which provides a set of extension methods for configuring the `AIAgent`.
57+
For example, you can add tools to the agent:
58+
```csharp
59+
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate")
60+
.WithAITool(new MyTool()); // MyTool is a custom type derived from `AITool`
61+
```
62+
63+
You can also configure the thread store (storage for conversation data):
64+
```csharp
65+
var pirateAgent = builder.AddAIAgent("pirate", instructions: "You are a pirate. Speak like a pirate")
66+
.WithInMemoryThreadStore();
67+
```
68+
69+
#### AddWorkflow
70+
71+
Register workflows that coordinate multiple agents. A workflow is essentially a "graph" where each node is an `AIAgent`, and the agents communicate with each other.
72+
73+
In this example, we register two agents that work sequentially. The user input is first sent to `agent-1`, which produces a response and sends it to `agent-2`. The workflow then outputs the final response. There is also a `BuildConcurrent` method that creates a concurrent agent workflow.
74+
75+
```csharp
76+
builder.AddAIAgent("agent-1", instructions: "you are agent 1!");
77+
builder.AddAIAgent("agent-2", instructions: "you are agent 2!");
78+
79+
var workflow = builder.AddWorkflow("my-workflow", (sp, key) =>
80+
{
81+
var agent1 = sp.GetRequiredKeyedService<AIAgent>("agent-1");
82+
var agent2 = sp.GetRequiredKeyedService<AIAgent>("agent-2");
83+
return AgentWorkflowBuilder.BuildSequential(key, [agent1, agent2]);
84+
});
85+
```
86+
87+
#### Expose Workflow as AIAgent
88+
89+
`AIAgent`s benefit from integration APIs that expose them via well-known protocols (such as A2A, OpenAI, and others):
90+
- [OpenAI Integration](openai-integration.md) - Expose agents via OpenAI-compatible APIs
91+
- [A2A Integration](agent-to-agent-integration.md) - Enable agent-to-agent communication
92+
93+
Currently, workflows do not provide similar integration capabilities. To use these integrations with a workflow, you can convert the workflow into a standalone agent that can be used like any other agent:
94+
95+
```csharp
96+
var workflowAsAgent = builder
97+
.AddWorkflow("science-workflow", (sp, key) => { ... })
98+
.AddAsAIAgent(); // Now the workflow can be used as an agent
99+
```
100+
101+
## Implementation Details
102+
103+
The hosting libraries act as protocol adapters that bridge the gap between external communication protocols and the Agent Framework's internal `AIAgent` implementation. When you use a hosting integration library (such as OpenAI Responses or A2A), the library retrieves the registered `AIAgent` from dependency injection and wraps it with protocol-specific middleware. This middleware handles the translation of incoming requests from the external protocol format into Agent Framework models, invokes the `AIAgent` to process the request, and then translates the agent's response back into the protocol's expected output format. This architecture allows you to use public communication protocols seamlessly with `AIAgent` while keeping your agent implementation protocol-agnostic and focused on business logic.
104+
105+
## Hosting Integration Libraries
106+
107+
The Agent Framework includes specialized hosting libraries for different integration scenarios:
108+
109+
- [OpenAI Integration](openai-integration.md) - Expose agents via OpenAI-compatible APIs
110+
- [A2A Integration](agent-to-agent-integration.md) - Enable agent-to-agent communication
111+
112+
## See Also
113+
114+
- [AI Agents Overview](../../overview/agent-framework-overview.md)
115+
- [Workflows](../../user-guide/workflows/overview.md)
116+
- [Tools and Capabilities](../../tutorials/agents/function-tools.md)

0 commit comments

Comments
 (0)