Skip to content

Commit 7daee33

Browse files
duplicate hosted agents samples (#385)
1 parent 2cbae5d commit 7daee33

33 files changed

Lines changed: 1315 additions & 0 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
7+
<Nullable>enable</Nullable>
8+
<ImplicitUsings>enable</ImplicitUsings>
9+
10+
<NoWarn>$(NoWarn);MEAI001;OPENAI001</NoWarn>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="Azure.AI.AgentServer.AgentFramework" Version="1.0.0-beta.4" />
15+
<PackageReference Include="Azure.AI.OpenAI" Version="2.5.0-beta.1" />
16+
<PackageReference Include="Azure.Identity" Version="1.17.0" />
17+
<PackageReference Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.251110.2" />
18+
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.10.2-preview.1.25552.1" />
19+
</ItemGroup>
20+
21+
</Project>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Build the application
2+
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
3+
WORKDIR /src
4+
5+
# Copy files from the current directory on the host to the working directory in the container
6+
COPY . .
7+
8+
RUN dotnet restore
9+
RUN dotnet build -c Release --no-restore
10+
RUN dotnet publish -c Release --no-build -o /app
11+
12+
# Run the application
13+
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final
14+
WORKDIR /app
15+
16+
# Copy everything needed to run the app from the "build" stage.
17+
COPY --from=build /app .
18+
19+
EXPOSE 8088
20+
ENTRYPOINT ["dotnet", "AgentWithHostedMCP.dll"]
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
// This sample shows how to create and use a simple AI agent with OpenAI Responses as the backend, that uses a Hosted MCP Tool.
4+
// In this case the OpenAI responses service will invoke any MCP tools as required. MCP tools are not invoked by the Agent Framework.
5+
// The sample demonstrates how to use MCP tools with auto approval by setting ApprovalMode to NeverRequire.
6+
7+
using Azure.AI.AgentServer.AgentFramework.Extensions;
8+
using Azure.AI.OpenAI;
9+
using Azure.Identity;
10+
using Microsoft.Agents.AI;
11+
using Microsoft.Extensions.AI;
12+
using OpenAI;
13+
14+
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
15+
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
16+
17+
// Create an MCP tool that can be called without approval.
18+
AITool mcpTool = new HostedMcpServerTool(serverName: "microsoft_learn", serverAddress: "https://learn.microsoft.com/api/mcp")
19+
{
20+
AllowedTools = ["microsoft_docs_search"],
21+
ApprovalMode = HostedMcpServerToolApprovalMode.NeverRequire
22+
};
23+
24+
// Create an agent with the MCP tool using Azure OpenAI Responses.
25+
AIAgent agent = new AzureOpenAIClient(
26+
new Uri(endpoint),
27+
new DefaultAzureCredential())
28+
.GetOpenAIResponseClient(deploymentName)
29+
.CreateAIAgent(
30+
instructions: "You answer questions by searching the Microsoft Learn content only.",
31+
name: "MicrosoftLearnAgent",
32+
tools: [mcpTool]);
33+
34+
await agent.RunAIAgentAsync();
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
**IMPORTANT!** All samples and other resources made available in this GitHub repository ("samples") are designed to assist in accelerating development of agents, solutions, and agent workflows for various scenarios. Review all provided resources and carefully test output behavior in the context of your use case. AI responses may be inaccurate and AI actions should be monitored with human oversight. Learn more in the transparency documents for [Agent Service](https://learn.microsoft.com/en-us/azure/ai-foundry/responsible-ai/agents/transparency-note) and [Agent Framework](https://github.com/microsoft/agent-framework/blob/main/TRANSPARENCY_FAQ.md).
2+
3+
Agents, solutions, or other output you create may be subject to legal and regulatory requirements, may require licenses, or may not be suitable for all industries, scenarios, or use cases. By using any sample, you are acknowledging that any output created using those samples are solely your responsibility, and that you will comply with all applicable laws, regulations, and relevant safety standards, terms of service, and codes of conduct.
4+
5+
Third-party samples contained in this folder are subject to their own designated terms, and they have not been tested or verified by Microsoft or its affiliates.
6+
7+
Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output.
8+
9+
# What this sample demonstrates
10+
11+
This sample demonstrates how to use a Hosted Model Context Protocol (MCP) server with a
12+
[Microsoft Agent Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview#ai-agents) AI agent and
13+
host it using [Azure AI AgentServer SDK](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/ai.agentserver.agentframework-readme) and
14+
deploy it to Microsoft Foundry using the Azure Developer CLI [ai agent](https://aka.ms/azdaiagent/docs) extension.
15+
16+
## How It Works
17+
18+
### MCP Integration
19+
20+
This sample uses a Hosted Model Context Protocol (MCP) server to provide external tools to the agent. The MCP workflow operates as follows:
21+
22+
1. The agent is configured with a `HostedMcpServerTool` pointing to `https://learn.microsoft.com/api/mcp`
23+
2. Only the `microsoft_docs_search` tool is enabled from the available MCP tools
24+
3. Approval mode is set to `NeverRequire`, allowing automatic tool execution without user confirmation
25+
4. When you ask questions, the Azure OpenAI Responses service automatically invokes the MCP tool to search Microsoft Learn documentation
26+
5. The agent returns answers based on the retrieved Microsoft Learn content
27+
28+
**Note**: In this configuration, the Azure OpenAI Responses service manages tool invocation directly - the Agent Framework does not handle MCP tool calls.
29+
30+
### Agent Hosting
31+
32+
The agent is hosted using the [Azure AI AgentServer SDK](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/ai.agentserver.agentframework-readme),
33+
which provisions a REST API endpoint compatible with the OpenAI Responses protocol. This allows interaction with the agent using OpenAI Responses compatible clients.
34+
35+
### Agent Deployment
36+
37+
The hosted agent can be seamlessly deployed to Microsoft Foundry using the Azure Developer CLI [ai agent](https://aka.ms/azdaiagent/docs) extension.
38+
The extension builds a container image for the agent, deploys it to Azure Container Instances (ACI), and creates a hosted agent version and deployment on Foundry Agent Service.
39+
40+
## Running the Agent Locally
41+
42+
### Prerequisites
43+
44+
Before running this sample, ensure you have:
45+
46+
1. An Azure OpenAI endpoint configured
47+
2. A deployment of a chat model (e.g., `gpt-4o-mini`)
48+
3. Azure CLI installed and authenticated (`az login`)
49+
4. .NET 9.0 SDK or later installed
50+
51+
### Environment Variables
52+
53+
Set the following environment variables:
54+
55+
- `AZURE_OPENAI_ENDPOINT` - Your Azure OpenAI endpoint URL (required)
56+
- `AZURE_OPENAI_DEPLOYMENT_NAME` - The deployment name for your chat model (optional, defaults to `gpt-4o-mini`)
57+
58+
**PowerShell:**
59+
```powershell
60+
# Replace with your Azure OpenAI endpoint
61+
$env:AZURE_OPENAI_ENDPOINT="https://your-openai-resource.openai.azure.com/"
62+
63+
# Optional, defaults to gpt-4o-mini
64+
$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o-mini"
65+
```
66+
67+
### Running the Sample
68+
69+
To run the agent, execute the following command in your terminal:
70+
71+
```powershell
72+
dotnet run
73+
```
74+
75+
This will start the hosted agent locally on `http://localhost:8080/`.
76+
77+
### Interacting with the Agent
78+
79+
You can interact with the agent using:
80+
81+
- The `run-requests.http` file in this directory to test and prompt the agent
82+
- Any OpenAI Responses compatible client by sending requests to `http://localhost:8080/`
83+
84+
Try asking questions about Microsoft documentation and technologies to see the MCP tool in action.
85+
86+
### Deploying the Agent to Microsoft Foundry
87+
88+
To deploy your agent to Microsoft Foundry, follow the comprehensive deployment guide at https://aka.ms/azdaiagent/docs
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: AgentWithHostedMCP
2+
displayName: "Microsoft Learn Response Agent with MCP"
3+
description: >
4+
An AI agent that uses Azure OpenAI Responses with a Hosted Model Context Protocol (MCP) server.
5+
The agent answers questions by searching Microsoft Learn documentation using MCP tools.
6+
This demonstrates how MCP tools can be integrated with Azure OpenAI Responses where the service
7+
itself handles tool invocation.
8+
metadata:
9+
authors:
10+
- Microsoft Agent Framework Team
11+
tags:
12+
- Azure AI AgentServer
13+
- Microsoft Agent Framework
14+
- Model Context Protocol
15+
- MCP
16+
- Tool Call Approval
17+
template:
18+
kind: hosted
19+
name: AgentWithHostedMCP
20+
protocols:
21+
- protocol: responses
22+
version: v1
23+
environment_variables:
24+
- name: AZURE_OPENAI_ENDPOINT
25+
value: ${AZURE_OPENAI_ENDPOINT}
26+
- name: AZURE_OPENAI_DEPLOYMENT_NAME
27+
value: "{{chat}}"
28+
resources:
29+
- name: chat
30+
kind: model
31+
id: gpt-4o-mini
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
@host = http://localhost:8088
2+
@endpoint = {{host}}/responses
3+
4+
### Health Check
5+
GET {{host}}/readiness
6+
7+
### Simple string input - Ask about MCP Tools
8+
POST {{endpoint}}
9+
Content-Type: application/json
10+
{
11+
"input": "Please summarize the Azure AI Agent documentation related to MCP Tool calling?"
12+
}
13+
14+
### Explicit input - Ask about Agent Framework
15+
POST {{endpoint}}
16+
Content-Type: application/json
17+
{
18+
"input": [
19+
{
20+
"type": "message",
21+
"role": "user",
22+
"content": [
23+
{
24+
"type": "input_text",
25+
"text": "What is the Microsoft Agent Framework?"
26+
}
27+
]
28+
}
29+
]
30+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net9.0</TargetFramework>
6+
7+
<Nullable>enable</Nullable>
8+
<ImplicitUsings>enable</ImplicitUsings>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Azure.AI.AgentServer.AgentFramework" Version="1.0.0-beta.4" />
13+
<PackageReference Include="Azure.AI.OpenAI" Version="2.5.0-beta.1" />
14+
<PackageReference Include="Azure.Identity" Version="1.17.0" />
15+
<PackageReference Include="Microsoft.Agents.AI.OpenAI" Version="1.0.0-preview.251110.2" />
16+
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.10.2-preview.1.25552.1" />
17+
</ItemGroup>
18+
19+
</Project>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Build the application
2+
FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build
3+
WORKDIR /src
4+
5+
# Copy files from the current directory on the host to the working directory in the container
6+
COPY . .
7+
8+
RUN dotnet restore
9+
RUN dotnet build -c Release --no-restore
10+
RUN dotnet publish -c Release --no-build -o /app
11+
12+
# Run the application
13+
FROM mcr.microsoft.com/dotnet/aspnet:9.0-alpine AS final
14+
WORKDIR /app
15+
16+
# Copy everything needed to run the app from the "build" stage.
17+
COPY --from=build /app .
18+
19+
EXPOSE 8088
20+
ENTRYPOINT ["dotnet", "AgentWithTextSearchRag.dll"]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
// This sample shows how to use TextSearchProvider to add retrieval augmented generation (RAG)
4+
// capabilities to an AI agent. The provider runs a search against an external knowledge base
5+
// before each model invocation and injects the results into the model context.
6+
7+
using Azure.AI.AgentServer.AgentFramework.Extensions;
8+
using Azure.AI.OpenAI;
9+
using Azure.Identity;
10+
using Microsoft.Agents.AI;
11+
using Microsoft.Agents.AI.Data;
12+
using Microsoft.Extensions.AI;
13+
using OpenAI;
14+
15+
var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
16+
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
17+
18+
TextSearchProviderOptions textSearchOptions = new()
19+
{
20+
// Run the search prior to every model invocation and keep a short rolling window of conversation context.
21+
SearchTime = TextSearchProviderOptions.TextSearchBehavior.BeforeAIInvoke,
22+
RecentMessageMemoryLimit = 6,
23+
};
24+
25+
AIAgent agent = new AzureOpenAIClient(
26+
new Uri(endpoint),
27+
new DefaultAzureCredential())
28+
.GetChatClient(deploymentName)
29+
.CreateAIAgent(new ChatClientAgentOptions
30+
{
31+
Instructions = "You are a helpful support specialist for Contoso Outdoors. Answer questions using the provided context and cite the source document when available.",
32+
AIContextProviderFactory = ctx => new TextSearchProvider(MockSearchAsync, ctx.SerializedState, ctx.JsonSerializerOptions, textSearchOptions)
33+
});
34+
35+
await agent.RunAIAgentAsync();
36+
37+
static Task<IEnumerable<TextSearchProvider.TextSearchResult>> MockSearchAsync(string query, CancellationToken cancellationToken)
38+
{
39+
// The mock search inspects the user's question and returns pre-defined snippets
40+
// that resemble documents stored in an external knowledge source.
41+
List<TextSearchProvider.TextSearchResult> results = new();
42+
43+
if (query.Contains("return", StringComparison.OrdinalIgnoreCase) || query.Contains("refund", StringComparison.OrdinalIgnoreCase))
44+
{
45+
results.Add(new()
46+
{
47+
SourceName = "Contoso Outdoors Return Policy",
48+
SourceLink = "https://contoso.com/policies/returns",
49+
Text = "Customers may return any item within 30 days of delivery. Items should be unused and include original packaging. Refunds are issued to the original payment method within 5 business days of inspection."
50+
});
51+
}
52+
53+
if (query.Contains("shipping", StringComparison.OrdinalIgnoreCase))
54+
{
55+
results.Add(new()
56+
{
57+
SourceName = "Contoso Outdoors Shipping Guide",
58+
SourceLink = "https://contoso.com/help/shipping",
59+
Text = "Standard shipping is free on orders over $50 and typically arrives in 3-5 business days within the continental United States. Expedited options are available at checkout."
60+
});
61+
}
62+
63+
if (query.Contains("tent", StringComparison.OrdinalIgnoreCase) || query.Contains("fabric", StringComparison.OrdinalIgnoreCase))
64+
{
65+
results.Add(new()
66+
{
67+
SourceName = "TrailRunner Tent Care Instructions",
68+
SourceLink = "https://contoso.com/manuals/trailrunner-tent",
69+
Text = "Clean the tent fabric with lukewarm water and a non-detergent soap. Allow it to air dry completely before storage and avoid prolonged UV exposure to extend the lifespan of the waterproof coating."
70+
});
71+
}
72+
73+
return Task.FromResult<IEnumerable<TextSearchProvider.TextSearchResult>>(results);
74+
}

0 commit comments

Comments
 (0)