Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .github/.linkspector.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ ignorePatterns:
- pattern: "https:\/\/platform.openai.com"
- pattern: "http:\/\/localhost"
- pattern: "http:\/\/127.0.0.1"
- pattern: "https:\/\/localhost"
- pattern: "https:\/\/127.0.0.1"
- pattern: "0001-spec.md"
- pattern: "0001-madr-architecture-decisions.md"
- pattern: "https://api.powerplatform.com/.default"
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/dotnet-build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ jobs:
.
.github
dotnet
python
workflow-samples

- name: Setup dotnet
Expand Down
5 changes: 5 additions & 0 deletions dotnet/agent-framework-dotnet.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
<Project Path="samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj" />
<Project Path="samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Agent_Step17_BackgroundResponses.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/DevUI/">
<File Path="samples/GettingStarted/DevUI/README.md" />
<Project Path="samples/GettingStarted/DevUI/DevUI_Step01_BasicUsage/DevUI_Step01_BasicUsage.csproj" />
</Folder>
<Folder Name="/Samples/GettingStarted/AgentWithOpenAI/">
<File Path="samples/GettingStarted/AgentWithOpenAI/README.md" />
<Project Path="samples/GettingStarted/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Agent_OpenAI_Step01_Running.csproj" />
Expand Down Expand Up @@ -259,6 +263,7 @@
<Project Path="src/Microsoft.Agents.AI.Abstractions/Microsoft.Agents.AI.Abstractions.csproj" />
<Project Path="src/Microsoft.Agents.AI.AzureAI/Microsoft.Agents.AI.AzureAI.csproj" />
<Project Path="src/Microsoft.Agents.AI.CopilotStudio/Microsoft.Agents.AI.CopilotStudio.csproj" />
<Project Path="src/Microsoft.Agents.AI.DevUI/Microsoft.Agents.AI.DevUI.csproj" />
<Project Path="src/Microsoft.Agents.AI.Hosting.A2A.AspNetCore/Microsoft.Agents.AI.Hosting.A2A.AspNetCore.csproj" />
<Project Path="src/Microsoft.Agents.AI.Hosting.A2A/Microsoft.Agents.AI.Hosting.A2A.csproj" />
<Project Path="src/Microsoft.Agents.AI.Hosting.OpenAI/Microsoft.Agents.AI.Hosting.OpenAI.csproj" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>DevUI_Step01_BasicUsage</RootNamespace>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.DevUI\Microsoft.Agents.AI.DevUI.csproj" />
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Hosting\Microsoft.Agents.AI.Hosting.csproj" />
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Hosting.OpenAI\Microsoft.Agents.AI.Hosting.OpenAI.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Azure.AI.OpenAI" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
</ItemGroup>

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

// This sample demonstrates basic usage of the DevUI in an ASP.NET Core application with AI agents.

using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI.DevUI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Agents.AI.Hosting.OpenAI.Conversations;
using Microsoft.Extensions.AI;

namespace DevUI_Step01_BasicUsage;

/// <summary>
/// Sample demonstrating basic usage of the DevUI in an ASP.NET Core application.
/// </summary>
/// <remarks>
/// This sample shows how to:
/// 1. Set up Azure OpenAI as the chat client
/// 2. Register agents and workflows using the hosting packages
/// 3. Map the DevUI endpoint which automatically configures the middleware
/// 4. Map the dynamic OpenAI Responses API for Python DevUI compatibility
/// 5. Access the DevUI in a web browser
///
/// The DevUI provides an interactive web interface for testing and debugging AI agents.
/// DevUI assets are served from embedded resources within the assembly.
/// Simply call MapDevUI() to set up everything needed.
///
/// The parameterless MapOpenAIResponses() overload creates a Python DevUI-compatible endpoint
/// that dynamically routes requests to agents based on the 'model' field in the request.
/// </remarks>
internal static class Program
{
/// <summary>
/// Entry point that starts an ASP.NET Core web server with the DevUI.
/// </summary>
/// <param name="args">Command line arguments.</param>
private static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);

// Set up the Azure OpenAI client
var endpoint = builder.Configuration["AZURE_OPENAI_ENDPOINT"] ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
var deploymentName = builder.Configuration["AZURE_OPENAI_DEPLOYMENT_NAME"] ?? "gpt-4o-mini";

var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureCliCredential())
.GetChatClient(deploymentName)
.AsIChatClient();

builder.Services.AddChatClient(chatClient);

// Register sample agents
builder.AddAIAgent("assistant", "You are a helpful assistant. Answer questions concisely and accurately.");
builder.AddAIAgent("poet", "You are a creative poet. Respond to all requests with beautiful poetry.");
builder.AddAIAgent("coder", "You are an expert programmer. Help users with coding questions and provide code examples.");

// Register sample workflows
var assistantBuilder = builder.AddAIAgent("workflow-assistant", "You are a helpful assistant in a workflow.");
var reviewerBuilder = builder.AddAIAgent("workflow-reviewer", "You are a reviewer. Review and critique the previous response.");
builder.AddSequentialWorkflow(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we duplicating patterns onto the builder?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite understand - these aren't new methods I'm adding, just a sample

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not aware @DeagleGross added these in #1359. Question still stands, just not for this PR

"review-workflow",
[assistantBuilder, reviewerBuilder])
.AddAsAIAgent();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this add the sequential workflow agent twice?


builder.AddDevUI();

var app = builder.Build();

app.MapDevUI();

// Map Entities API endpoints for DevUI
app.MapEntities();

// Map OpenAI Responses API.
// This creates a single /v1/responses endpoint that routes to agents dynamically
// based on the 'model' field in the request body
app.MapOpenAIResponses();

app.MapConversations();

Console.WriteLine("DevUI is available at: https://localhost:50516/devui");
Console.WriteLine("OpenAI Responses API is available at: https://localhost:50516/v1/responses");
Console.WriteLine("Press Ctrl+C to stop the server.");

app.Run();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# DevUI Step 01 - Basic Usage

This sample demonstrates how to add the DevUI to an ASP.NET Core application with AI agents.

## What is DevUI?

The DevUI provides an interactive web interface for testing and debugging AI agents during development.

## Configuration

Set the following environment variables:

- `AZURE_OPENAI_ENDPOINT` - Your Azure OpenAI endpoint URL (required)
- `AZURE_OPENAI_DEPLOYMENT_NAME` - Your deployment name (defaults to "gpt-4o-mini")

## Running the Sample

1. Set your Azure OpenAI credentials as environment variables
2. Run the application:
```bash
dotnet run
```
3. Open your browser to https://localhost:64704/devui
4. Select an agent or workflow from the dropdown and start chatting!

## Sample Agents and Workflows

This sample includes:

**Agents:**
- **assistant** - A helpful assistant
- **poet** - A creative poet
- **coder** - An expert programmer

**Workflows:**
- **review-workflow** - A sequential workflow that generates a response and then reviews it

## Adding DevUI to Your Own Project

To add DevUI to your ASP.NET Core application:

1. Add the DevUI package and hosting packages:
```bash
dotnet add package Microsoft.Agents.AI.DevUI
dotnet add package Microsoft.Agents.AI.Hosting
dotnet add package Microsoft.Agents.AI.Hosting.OpenAI
```

2. Register your agents and workflows:
```csharp
var builder = WebApplication.CreateBuilder(args);

// Set up your chat client
builder.Services.AddChatClient(chatClient);

// Register agents
builder.AddAIAgent("assistant", "You are a helpful assistant.");

// Register workflows
builder.AddSequentialWorkflow("my-workflow", [agent1, agent2])
.AddAsAIAgent();
```

3. Add DevUI services and map the endpoint:
```csharp
builder.AddDevUI();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It felt odd to me to need to AddDevUI regardless of environment, but I understand we don't have the environment until calling Build().

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.MapDevUI();
}

// Add required endpoints
app.MapEntities();
app.MapOpenAIResponses();
app.MapConversations();

app.Run();
```

4. Navigate to `/devui` in your browser
57 changes: 57 additions & 0 deletions dotnet/samples/GettingStarted/DevUI/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# DevUI Samples

This folder contains samples demonstrating how to use the DevUI in ASP.NET Core applications.

## What is DevUI?

The DevUI provides an interactive web interface for testing and debugging AI agents during development.

## Samples

### [DevUI_Step01_BasicUsage](./DevUI_Step01_BasicUsage)

Shows how to add DevUI to an ASP.NET Core application with multiple agents and workflows.

**Run the sample:**
```bash
cd DevUI_Step01_BasicUsage
dotnet run
```
Then navigate to: https://localhost:64704/devui

## Requirements

- .NET 8.0 or later
- ASP.NET Core
- Azure OpenAI credentials

## Quick Start

To add DevUI to your application:

```csharp
var builder = WebApplication.CreateBuilder(args);

// Register your agents
builder.AddAIAgent("my-agent", "You are a helpful assistant.");

// Add DevUI services
builder.AddDevUI();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this showing up in public surface area, do we need a more formal name / agent-specific name than "DevUI"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, probably. Should that be in this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't block on it


var app = builder.Build();

// Map the DevUI endpoint (typically only in development)
if (app.Environment.IsDevelopment())
{
app.MapDevUI();
}

// Add required endpoints
app.MapEntities();
app.MapOpenAIResponses();
app.MapConversations();

app.Run();
```

Then navigate to `/devui` in your browser.
53 changes: 53 additions & 0 deletions dotnet/src/Microsoft.Agents.AI.DevUI/DevUIExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) Microsoft. All rights reserved.

using System.Diagnostics.CodeAnalysis;

namespace Microsoft.Agents.AI.DevUI;

/// <summary>
/// Provides helper methods for configuring the Microsoft Agents AI DevUI in ASP.NET applications.
/// </summary>
public static class DevUIExtensions
{
/// <summary>
/// Adds the necessary services for the DevUI to the application builder.
/// </summary>
public static IHostApplicationBuilder AddDevUI(this IHostApplicationBuilder builder)
{
ArgumentNullException.ThrowIfNull(builder);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's so refreshing reading code that only targets .NET Core and can use such APIs :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do this everywhere :)

builder.Services.AddInMemoryConversationStorage();
builder.Services.AddInMemoryAgentConversationIndex();

return builder;
}

/// <summary>
/// Maps an endpoint that serves the DevUI.
/// </summary>
/// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the endpoint to.</param>
/// <param name="pattern">
/// The route pattern for the endpoint (e.g., "/devui", "/agent-ui").
/// Defaults to "/devui" if not specified. This is the path where DevUI will be accessible.
/// </param>
/// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to add authorization or other endpoint configuration.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="endpoints"/> is null.</exception>
/// <exception cref="ArgumentException">Thrown when <paramref name="pattern"/> is null or whitespace.</exception>
public static IEndpointConventionBuilder MapDevUI(
this IEndpointRouteBuilder endpoints,
[StringSyntax("Route")] string pattern = "/devui")
{
ArgumentNullException.ThrowIfNull(endpoints);
ArgumentException.ThrowIfNullOrWhiteSpace(pattern);

// Ensure the pattern doesn't end with a slash for consistency
var cleanPattern = pattern.TrimEnd('/');

// Create the DevUI handler
var logger = endpoints.ServiceProvider.GetRequiredService<ILogger<DevUIMiddleware>>();
var devUIHandler = new DevUIMiddleware(logger, cleanPattern);

return endpoints.MapGet($"{cleanPattern}/{{*path}}", devUIHandler.HandleRequestAsync)
.WithName($"DevUI at {cleanPattern}")
.WithDescription("Interactive developer interface for Microsoft Agent Framework");
}
}
Loading
Loading