Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1247eb9
Add foundry extension samples for python and dotnet
Feb 27, 2026
1f5ce59
Align foundry extension samples with existing hosted agent patterns
rogerbarreto Feb 27, 2026
4cd33cd
Align foundry samples: fix builds, upgrade AgentServer to beta.8
rogerbarreto Feb 27, 2026
f2ba709
Refactor hosted samples to use AIProjectClient.CreateAIAgentAsync
rogerbarreto Feb 27, 2026
7302b3d
Update READMEs to reflect AIProjectClient.CreateAIAgentAsync usage
rogerbarreto Feb 27, 2026
fc4b6db
Add HostedAgents READMEs and Foundry samples to solution
rogerbarreto Feb 27, 2026
986a601
Fix Python linting: reorder imports before load_dotenv, remove traili…
rogerbarreto Feb 27, 2026
6ccc87f
Update uv.lock to match latest package versions
rogerbarreto Feb 27, 2026
4322653
Fix trailing whitespace in foundry_single_agent agent.yaml
rogerbarreto Feb 27, 2026
4cfa2f1
Merge branch 'main' of https://github.com/microsoft/agent-framework i…
rogerbarreto Mar 3, 2026
706b3fb
Exclude dotnet.microsoft.com from link checker
rogerbarreto Mar 3, 2026
23a71b2
Align env vars to AZURE_AI_PROJECT_ENDPOINT and default model to gpt-…
rogerbarreto Mar 3, 2026
162e812
Merge branch 'main' of https://github.com/microsoft/agent-framework i…
rogerbarreto Mar 3, 2026
a48164b
Merge branch 'main' into leoyao-samples
rogerbarreto Mar 3, 2026
84cae64
Merge branch 'main' into leoyao-samples
rogerbarreto Mar 4, 2026
4291e2e
Skip flaky test CreatesWorkflowEndToEndActivities_WithCorrectName_Def…
rogerbarreto Mar 4, 2026
0ab0d6d
Remove Python foundry samples from PR scope
rogerbarreto Mar 4, 2026
4371517
Merge branch 'main' into leoyao-samples
rogerbarreto Mar 4, 2026
898f0ef
Narrow linkspector exclusion to dotnet.microsoft.com/download only
rogerbarreto Mar 4, 2026
e0a9b6c
Merge branch 'main' into leoyao-samples
rogerbarreto Mar 4, 2026
ab3093a
Merge branch 'main' into leoyao-samples
rogerbarreto Mar 4, 2026
61b005e
Merge branch 'main' into leoyao-samples
rogerbarreto Mar 5, 2026
c0cd0a7
Merge branch 'main' into leoyao-samples
rogerbarreto Mar 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/.linkspector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ ignorePatterns:
- pattern: "https://your-resource.openai.azure.com/"
- pattern: "http://host.docker.internal"
- pattern: "https://openai.github.io/openai-agents-js/openai/agents/classes/"
- pattern: "https:\/\/dotnet.microsoft.com\/download"
# excludedDirs:
# Folders which include links to localhost, since it's not ignored with regular expressions
baseUrl: https://github.com/microsoft/agent-framework/
Expand Down
2 changes: 2 additions & 0 deletions dotnet/agent-framework-dotnet.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@
<Project Path="samples/05-end-to-end/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj" />
<Project Path="samples/05-end-to-end/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj" />
<Project Path="samples/05-end-to-end/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj" />
<Project Path="samples/05-end-to-end/HostedAgents/FoundryMultiAgent/FoundryMultiAgent.csproj" />
<Project Path="samples/05-end-to-end/HostedAgents/FoundrySingleAgent/FoundrySingleAgent.csproj" />
</Folder>
<Folder Name="/Samples/05-end-to-end/AspNetAgentAuthorization/">
<File Path="samples/05-end-to-end/AspNetAgentAuthorization/docker-compose.yml" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Build the application
FROM mcr.microsoft.com/dotnet/sdk:10.0-alpine AS build
WORKDIR /src

# Copy files from the current directory on the host to the working directory in the container
COPY . .

RUN dotnet restore
RUN dotnet build -c Release --no-restore
RUN dotnet publish -c Release --no-build -o /app -f net10.0

# Run the application
FROM mcr.microsoft.com/dotnet/aspnet:10.0-alpine AS final
WORKDIR /app

# Copy everything needed to run the app from the "build" stage.
COPY --from=build /app .

EXPOSE 8088
ENTRYPOINT ["dotnet", "FoundryMultiAgent.dll"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<!--
Disable central package management for this project.
This project requires explicit package references with versions specified inline rather than
inheriting them from Directory.Packages.props. This is necessary because a Docker image will
be created from this project, and the Docker build process only has access to this folder
and cannot access parent folders where Directory.Packages.props resides.
-->
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
</PropertyGroup>

<!--
Remove analyzer PackageReference items inherited from Directory.Packages.props.
Note: ManagePackageVersionsCentrally only controls PackageVersion items, not PackageReference items.
Directory.Packages.props contains both PackageVersion and PackageReference entries for analyzers,
and the PackageReference items are always inherited through MSBuild imports regardless of the
ManagePackageVersionsCentrally setting. We must explicitly remove them before adding our own versions.
-->
<ItemGroup>
<PackageReference Remove="Microsoft.CodeAnalysis.NetAnalyzers" />
<PackageReference Remove="Microsoft.VisualStudio.Threading.Analyzers" />
<PackageReference Remove="xunit.analyzers" />
<PackageReference Remove="Moq.Analyzers" />
<PackageReference Remove="Roslynator.Analyzers" />
<PackageReference Remove="Roslynator.CodeAnalysis.Analyzers" />
<PackageReference Remove="Roslynator.Formatting.Analyzers" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Azure.AI.AgentServer.AgentFramework" Version="1.0.0-beta.8" />
<PackageReference Include="Azure.AI.Projects" Version="1.2.0-beta.5" />
<PackageReference Include="Azure.Identity" Version="1.17.1" />
<PackageReference Include="Microsoft.Agents.AI" Version="1.0.0-preview.251219.1" />
<PackageReference Include="Microsoft.Agents.AI.AzureAI" Version="1.0.0-preview.251219.1" />
<PackageReference Include="Microsoft.Agents.AI.Workflows" Version="1.0.0-preview.251219.1" />
<PackageReference Include="OpenTelemetry" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
</ItemGroup>

<!-- Add analyzers with compatible versions -->
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="4.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<None Update="appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft. All rights reserved.

// This sample demonstrates a multi-agent workflow with Writer and Reviewer agents
// using Azure AI Foundry AIProjectClient and the Agent Framework WorkflowBuilder.

using Azure.AI.AgentServer.AgentFramework.Extensions;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;

var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT")
?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
var deploymentName = Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

Console.WriteLine($"Using Azure AI endpoint: {endpoint}");
Console.WriteLine($"Using model deployment: {deploymentName}");

// 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.
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());

// Create Foundry agents
AIAgent writerAgent = await aiProjectClient.CreateAIAgentAsync(
name: "Writer",
model: deploymentName,
instructions: "You are an excellent content writer. You create new content and edit contents based on the feedback.");

AIAgent reviewerAgent = await aiProjectClient.CreateAIAgentAsync(
name: "Reviewer",
model: deploymentName,
instructions: "You are an excellent content reviewer. Provide actionable feedback to the writer about the provided content. Provide the feedback in the most concise manner possible.");

try
{
var workflow = new WorkflowBuilder(writerAgent)
.AddEdge(writerAgent, reviewerAgent)
.Build();

Console.WriteLine("Starting Writer-Reviewer Workflow Agent Server on http://localhost:8088");
await workflow.AsAgent().RunAIAgentAsync();
}
finally
{
// Cleanup server-side agents
await aiProjectClient.Agents.DeleteAgentAsync(writerAgent.Name);
await aiProjectClient.Agents.DeleteAgentAsync(reviewerAgent.Name);
}
168 changes: 168 additions & 0 deletions dotnet/samples/05-end-to-end/HostedAgents/FoundryMultiAgent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
**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).

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.

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.

Microsoft has no responsibility to you or others with respect to any of these samples or any resulting output.

# What this sample demonstrates

This sample demonstrates a **key advantage of code-based hosted agents**:

- **Multi-agent workflows** - Orchestrate multiple agents working together

Code-based agents can execute **any C# code** you write. This sample includes a Writer-Reviewer workflow where two agents collaborate: a Writer creates content and a Reviewer provides feedback.

The agent is hosted using the [Azure AI AgentServer SDK](https://www.nuget.org/packages/Azure.AI.AgentServer.AgentFramework/) and can be deployed to Microsoft Foundry.

## How It Works

### Multi-Agent Workflow

In [Program.cs](Program.cs), the sample creates two agents using `AIProjectClient.CreateAIAgentAsync()` from the [Microsoft.Agents.AI.AzureAI](https://www.nuget.org/packages/Microsoft.Agents.AI.AzureAI/) package:

- **Writer** - An agent that creates and edits content based on feedback
- **Reviewer** - An agent that provides actionable feedback on the content

The `WorkflowBuilder` from the [Microsoft.Agents.AI.Workflows](https://www.nuget.org/packages/Microsoft.Agents.AI.Workflows/) package connects these agents in a sequential flow:

1. The Writer receives the initial request and generates content
2. The Reviewer evaluates the content and provides feedback
3. Both agent responses are output to the user

### Agent Hosting

The agent is hosted using the [Azure AI AgentServer SDK](https://www.nuget.org/packages/Azure.AI.AgentServer.AgentFramework/),
which provisions a REST API endpoint compatible with the OpenAI Responses protocol.

## Running the Agent Locally

### Prerequisites

Before running this sample, ensure you have:

1. **Azure AI Foundry Project**
- Project created.
- Chat model deployed (e.g., `gpt-4o` or `gpt-4.1`)
- Note your project endpoint URL and model deployment name
> **Note**: You can right-click the project in the Microsoft Foundry VS Code extension and select `Copy Project Endpoint URL` to get the endpoint.
2. **Azure CLI**
- Installed and authenticated
- Run `az login` and verify with `az account show`
- Your identity needs the **Azure AI Developer** role on the Foundry resource (for `agents/write` data action required by `CreateAIAgentAsync`)

3. **.NET 10.0 SDK or later**
- Verify your version: `dotnet --version`
- Download from [https://dotnet.microsoft.com/download](https://dotnet.microsoft.com/download)

### Environment Variables

Set the following environment variables:

**PowerShell:**

```powershell
# Replace with your actual values
$env:AZURE_AI_PROJECT_ENDPOINT="https://<your-resource>.services.ai.azure.com/api/projects/<your-project>"
$env:MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
```

**Bash:**

```bash
export AZURE_AI_PROJECT_ENDPOINT="https://<your-resource>.services.ai.azure.com/api/projects/<your-project>"
export MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
```

### Running the Sample

To run the agent, execute the following command in your terminal:

```bash
dotnet restore
dotnet build
dotnet run
```

This will start the hosted agent locally on `http://localhost:8088/`.

### Interacting with the Agent

**VS Code:**

1. Open the Visual Studio Code Command Palette and execute the `Microsoft Foundry: Open Container Agent Playground Locally` command.
2. Execute the following commands to start the containerized hosted agent.
```bash
dotnet restore
dotnet build
dotnet run
```
3. Submit a request to the agent through the playground interface. For example, you may enter a prompt such as: "Create a slogan for a new electric SUV that is affordable and fun to drive."
4. Review the agent's response in the playground interface.

> **Note**: Open the local playground before starting the container agent to ensure the visualization functions correctly.
**PowerShell (Windows):**

```powershell
$body = @{
input = "Create a slogan for a new electric SUV that is affordable and fun to drive"
stream = $false
} | ConvertTo-Json
Invoke-RestMethod -Uri http://localhost:8088/responses -Method Post -Body $body -ContentType "application/json"
```

**Bash/curl (Linux/macOS):**

```bash
curl -sS -H "Content-Type: application/json" -X POST http://localhost:8088/responses \
-d '{"input": "Create a slogan for a new electric SUV that is affordable and fun to drive","stream":false}'
```

You can also use the `run-requests.http` file in this directory with the VS Code REST Client extension.

The Writer agent will generate content based on your prompt, and the Reviewer agent will provide feedback on the output.

## Deploying the Agent to Microsoft Foundry

**Preparation (required)**

Please check the environment_variables section in [agent.yaml](agent.yaml) and ensure the variables there are set in your target Microsoft Foundry Project.

To deploy the hosted agent:

1. Open the VS Code Command Palette and run the `Microsoft Foundry: Deploy Hosted Agent` command.

2. Follow the interactive deployment prompts. The extension will help you select or create the container files it needs.

3. After deployment completes, the hosted agent appears under the `Hosted Agents (Preview)` section of the extension tree. You can select the agent there to view details and test it using the integrated playground.

**What the deploy flow does for you:**

- Creates or obtains an Azure Container Registry for the target project.
- Builds and pushes a container image from your workspace (the build packages the workspace respecting `.dockerignore`).
- Creates an agent version in Microsoft Foundry using the built image. If a `.env` file exists at the workspace root, the extension will parse it and include its key/value pairs as the hosted agent's environment variables in the create request (these variables will be available to the agent runtime).
- Starts the agent container on the project's capability host. If the capability host is not provisioned, the extension will prompt you to enable it and will guide you through creating it.

## MSI Configuration in the Azure Portal

This sample requires the Microsoft Foundry Project to authenticate using a Managed Identity when running remotely in Azure. Grant the project's managed identity the required permissions by assigning the built-in [Azure AI User](https://aka.ms/foundry-ext-project-role) role.

To configure the Managed Identity:

1. In the Azure Portal, open the Foundry Project.
2. Select "Access control (IAM)" from the left-hand menu.
3. Click "Add" and choose "Add role assignment".
4. In the role selection, search for and select "Azure AI User", then click "Next".
5. For "Assign access to", choose "Managed identity".
6. Click "Select members", locate the managed identity associated with your Foundry Project (you can search by the project name), then click "Select".
7. Click "Review + assign" to complete the assignment.
8. Allow a few minutes for the role assignment to propagate before running the application.

## Additional Resources

- [Microsoft Agents Framework](https://learn.microsoft.com/en-us/agent-framework/overview/agent-framework-overview)
- [Managed Identities for Azure Resources](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/)
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml

name: FoundryMultiAgent
displayName: "Foundry Multi-Agent Workflow"
description: >
A multi-agent workflow featuring a Writer and Reviewer that collaborate
to create and refine content using Azure AI Foundry PersistentAgentsClient.
metadata:
authors:
- Microsoft Agent Framework Team
tags:
- Azure AI AgentServer
- Microsoft Agent Framework
- Multi-Agent Workflow
- Writer-Reviewer
- Content Creation
template:
kind: hosted
name: FoundryMultiAgent
protocols:
- protocol: responses
version: v1
environment_variables:
- name: AZURE_AI_PROJECT_ENDPOINT
value: ${AZURE_AI_PROJECT_ENDPOINT}
- name: MODEL_DEPLOYMENT_NAME
value: gpt-4o-mini
resources:
- name: "gpt-4o-mini"
kind: model
id: gpt-4o-mini
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"AZURE_AI_PROJECT_ENDPOINT": "https://<your-resource>.services.ai.azure.com/api/projects/<your-project>",
"MODEL_DEPLOYMENT_NAME": "gpt-4o-mini"
}
Loading
Loading