Files
agent-framework/dotnet/samples/AgentWebChat/AgentWebChat.AgentHost/Program.cs
T
Korolev Dmitry d10b44d6bb .NET: Enable access to hosted AIAgents via OpenAI Responses (#947)
* init

* wip

* wip wip wip

* wip wip

* open up API

* enable for multiple agents

* more wip

* make frontend respond.

* wip

* not sure if proper setup

* define type

* cleanup

* frontend streaming wip

* use System.Net.ServerSentEvents

* usings

* reformat via ichatclient

* merge main renaming + refactor

* fix main merge + fix sample (a2a change)

* fix sample

* some rebase (not working yet)

* make it at least build somehow

* make non-stream work without internal types

* Input without custom models

* implement streaming

* test frontend

* enable alerts and fix

* build fixes & rereview

* Update dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI.Responses/Microsoft.Agents.AI.Hosting.OpenAI.Responses.csproj

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update dotnet/src/Microsoft.Agents.AI.Hosting.OpenAI.Responses/Utils/ResponseItemJsonConverter.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix agent discovery

* rename

* rename project into Microsoft.Agents.AI.Hosting.OpenAI (no responses in name)

* PR address comments x1

* address PR comments x2

* correctly instantiate OpenAIResponse

* address PR comments x3

* reconfigure JSON serialization & handle AOT warnings

* fix build

* proper ref

* check update differently

* correct check

* exclude dotnet format diagnostics for IL2026 and IL3050

* space  :)

* re-review

* add comments

* remove unnecessary using

* always take last openai response item

* set responseItem Id explicitly

* add agent.name validation for uri

* cleanup

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: SergeyMenshykh <68852919+SergeyMenshykh@users.noreply.github.com>
2025-10-07 12:39:08 +00:00

97 lines
3.6 KiB
C#

// Copyright (c) Microsoft. All rights reserved.
using A2A.AspNetCore;
using AgentWebChat.AgentHost;
using AgentWebChat.AgentHost.Utilities;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Agents.AI.Hosting.A2A.AspNetCore;
using Microsoft.Agents.AI.Hosting.OpenAI;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
var builder = WebApplication.CreateBuilder(args);
// Add service defaults & Aspire client integrations.
builder.AddServiceDefaults();
builder.Services.AddOpenApi();
// Add services to the container.
builder.Services.AddProblemDetails();
// Configure the chat model and our agent.
builder.AddKeyedChatClient("chat-model");
builder.AddAIAgent(
"pirate",
instructions: "You are a pirate. Speak like a pirate",
description: "An agent that speaks like a pirate.",
chatClientServiceKey: "chat-model");
builder.AddAIAgent("knights-and-knaves", (sp, key) =>
{
var chatClient = sp.GetRequiredKeyedService<IChatClient>("chat-model");
ChatClientAgent knight = new(
chatClient,
"""
You are a knight. This means that you must always tell the truth. Your name is Alice.
Bob is standing next to you. Bob is a knave, which means he always lies.
When replying, always start with your name (Alice). Eg, "Alice: I am a knight."
""", "Alice");
ChatClientAgent knave = new(
chatClient,
"""
You are a knave. This means that you must always lie. Your name is Bob.
Alice is standing next to you. Alice is a knight, which means she always tells the truth.
When replying, always include your name (Bob). Eg, "Bob: I am a knight."
""", "Bob");
ChatClientAgent narrator = new(
chatClient,
"""
You are are the narrator of a puzzle involving knights (who always tell the truth) and knaves (who always lie).
The user is going to ask questions and guess whether Alice or Bob is the knight or knave.
Alice is standing to one side of you. Alice is a knight, which means she always tells the truth.
Bob is standing to the other side of you. Bob is a knave, which means he always lies.
When replying, always include your name (Narrator).
Once the user has deduced what type (knight or knave) both Alice and Bob are, tell them whether they are right or wrong.
If the user asks a general question about their surrounding, make something up which is consistent with the scenario.
""", "Narrator");
// TODO: How to avoid sync-over-async here?
#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits
return AgentWorkflowBuilder.BuildConcurrent([knight, knave, narrator]).AsAgentAsync(name: key).AsTask().GetAwaiter().GetResult();
#pragma warning restore VSTHRD002
});
var app = builder.Build();
app.MapOpenApi();
app.UseSwaggerUI(options => options.SwaggerEndpoint("/openapi/v1.json", "Agents API"));
// Configure the HTTP request pipeline.
app.UseExceptionHandler();
// attach a2a with simple message communication
app.MapA2A(agentName: "pirate", path: "/a2a/pirate");
app.MapA2A(agentName: "knights-and-knaves", path: "/a2a/knights-and-knaves", agentCard: new()
{
Name = "Knights and Knaves",
Description = "An agent that helps you solve the knights and knaves puzzle.",
Version = "1.0",
// Url can be not set, and SDK will help assign it.
// Url = "http://localhost:5390/a2a/knights-and-knaves"
});
app.MapOpenAIResponses("pirate");
app.MapOpenAIResponses("knights-and-knaves");
// Map the agents HTTP endpoints
app.MapAgentDiscovery("/agents");
app.MapDefaultEndpoints();
app.Run();