Skip to content

Commit 243be68

Browse files
Add Agent Framework DevUI into the aiagent-webapi template (dotnet#7026)
* Integrate DevUI into the aiagent-webapi project template * Improve aiagent-webapi Program.cs per feedback. * Remove --no-devui. Fix OpenAI clients. Augment execution test sandbox ignores. * Rename to Microsoft.Agents.AI.ProjectTemplates * Set Microsoft.Agents.AI package versions * Simplify the GitHub and OpenAI key config vars for aiagent-webapi * Sort package references * Fix troubleshooting section in READMEs * Revert MEAI.Templates change. Make launchSettings .gitignore more specific. --------- Co-authored-by: Mackinnon Buck <[email protected]>
1 parent 8917d58 commit 243be68

File tree

54 files changed

+400
-236
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+400
-236
lines changed

src/ProjectTemplates/.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ package-lock.json
1212
*/src/**/Directory.Build.props
1313
*/src/**/ingestioncache.*
1414

15-
# launchSettings.json files are required for the templates.
16-
!launchSettings.json
15+
# The project templates include hard-coded launchSettings.json files
16+
!*/src/ProjectTemplates/**/Properties/launchSettings.json
1717

1818
# Templates include JS dependencies in dist folders.
1919
!**/dist/*

src/ProjectTemplates/GeneratedContent.targets

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
-->
1010
<_LocalChatTemplateVariant>aspire</_LocalChatTemplateVariant>
1111

12-
<_WebApiAgentRoot>$(MSBuildThisFileDirectory)Microsoft.Agents.AI.Templates\src\WebApiAgent\</_WebApiAgentRoot>
12+
<_WebApiAgentRoot>$(MSBuildThisFileDirectory)Microsoft.Agents.AI.ProjectTemplates\src\WebApiAgent\</_WebApiAgentRoot>
1313
<_ChatWithCustomDataContentRoot>$(MSBuildThisFileDirectory)Microsoft.Extensions.AI.Templates\src\ChatWithCustomData\</_ChatWithCustomDataContentRoot>
1414
<_McpServerContentRoot>$(MSBuildThisFileDirectory)Microsoft.Extensions.AI.Templates\src\McpServer\</_McpServerContentRoot>
1515
</PropertyGroup>
@@ -37,8 +37,8 @@
3737
Specifies external packages that get referenced in generated template content.
3838
-->
3939
<PropertyGroup>
40-
<TemplatePackageVersion_MicrosoftAgentsAI>1.0.0-preview.251104.1</TemplatePackageVersion_MicrosoftAgentsAI>
41-
<TemplatePackageVersion_MicrosoftAgentsAIHostingOpenAI>1.0.0-alpha.251104.1</TemplatePackageVersion_MicrosoftAgentsAIHostingOpenAI>
40+
<TemplatePackageVersion_MicrosoftAgentsAI>1.0.0-preview.251110.2</TemplatePackageVersion_MicrosoftAgentsAI>
41+
<TemplatePackageVersion_MicrosoftAgentsAIHostingOpenAI>1.0.0-alpha.251110.2</TemplatePackageVersion_MicrosoftAgentsAIHostingOpenAI>
4242
<TemplatePackageVersion_Aspire>9.5.1</TemplatePackageVersion_Aspire>
4343
<TemplatePackageVersion_Aspire_Preview>9.5.1-preview.1.25502.11</TemplatePackageVersion_Aspire_Preview>
4444
<TemplatePackageVersion_AzureAIProjects>1.0.0</TemplatePackageVersion_AzureAIProjects>
@@ -91,6 +91,9 @@
9191
</PropertyGroup>
9292

9393
<ItemGroup>
94+
<GeneratedContent
95+
Include="$(_WebApiAgentRoot)WebApiAgent-CSharp\WebApiAgent-CSharp.csproj.in"
96+
OutputPath="$(_WebApiAgentRoot)WebApiAgent-CSharp\WebApiAgent-CSharp.csproj" />
9497
<GeneratedContent
9598
Include="$(_ChatWithCustomDataContentRoot)ChatWithCustomData-CSharp.sln.in"
9699
OutputPath="$(_ChatWithCustomDataContentRoot)ChatWithCustomData-CSharp.sln" />
@@ -100,9 +103,6 @@
100103
<GeneratedContent
101104
Include="$(_ChatWithCustomDataContentRoot)Directory.Build.props.in"
102105
OutputPath="$(_ChatWithCustomDataContentRoot)Directory.Build.props" />
103-
<GeneratedContent
104-
Include="$(_WebApiAgentRoot)WebApiAgent-CSharp\WebApiAgent-CSharp.csproj.in"
105-
OutputPath="$(_WebApiAgentRoot)WebApiAgent-CSharp\WebApiAgent-CSharp.csproj" />
106106
<GeneratedContent
107107
Include="$(_ChatWithCustomDataContentRoot)ChatWithCustomData-CSharp.Web\ChatWithCustomData-CSharp.Web.csproj.in"
108108
OutputPath="$(_ChatWithCustomDataContentRoot)ChatWithCustomData-CSharp.Web\ChatWithCustomData-CSharp.Web.csproj" />

src/ProjectTemplates/Microsoft.Agents.AI.Templates/Microsoft.Agents.AI.Templates.csproj renamed to src/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates.csproj

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,14 @@
77
<PackageTags>dotnet-new;templates;ai;agent</PackageTags>
88

99
<Stage>preview</Stage>
10-
<PreReleaseVersionIteration>1</PreReleaseVersionIteration>
10+
11+
<!-- Set the version info to align with Microsoft.Agents.AI packages -->
12+
<MajorVersion>1</MajorVersion>
13+
<MinorVersion>0</MinorVersion>
14+
<PatchVersion>0</PatchVersion>
15+
<PreReleaseVersionLabel>preview</PreReleaseVersionLabel>
16+
<VersionSuffix>preview.251110.2</VersionSuffix>
17+
1118
<Workstream>AI</Workstream>
1219
<MinCodeCoverage>0</MinCodeCoverage>
1320
<MinMutationScore>0</MinMutationScore>

src/ProjectTemplates/Microsoft.Agents.AI.Templates/README.md renamed to src/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
# Microsoft.Agents.AI.Templates
1+
# Microsoft.Agents.AI.ProjectTemplates
22

33
Provides project templates for Microsoft.Agents.AI.

src/ProjectTemplates/Microsoft.Agents.AI.Templates/THIRD-PARTY-NOTICES.TXT renamed to src/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates/THIRD-PARTY-NOTICES.TXT

File renamed without changes.

src/ProjectTemplates/Microsoft.Agents.AI.Templates/src/WebApiAgent/WebApiAgent-CSharp/.template.config/dotnetcli.host.json renamed to src/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates/src/WebApiAgent/WebApiAgent-CSharp/.template.config/dotnetcli.host.json

File renamed without changes.

src/ProjectTemplates/Microsoft.Agents.AI.Templates/src/WebApiAgent/WebApiAgent-CSharp/.template.config/ide.host.json renamed to src/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates/src/WebApiAgent/WebApiAgent-CSharp/.template.config/ide.host.json

File renamed without changes.

src/ProjectTemplates/Microsoft.Agents.AI.Templates/src/WebApiAgent/WebApiAgent-CSharp/.template.config/ide/agent-framework.ico renamed to src/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates/src/WebApiAgent/WebApiAgent-CSharp/.template.config/ide/agent-framework.ico

File renamed without changes.

src/ProjectTemplates/Microsoft.Agents.AI.Templates/src/WebApiAgent/WebApiAgent-CSharp/.template.config/template.json renamed to src/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates/src/WebApiAgent/WebApiAgent-CSharp/.template.config/template.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"$schema": "http://json.schemastore.org/template",
33
"author": "Microsoft",
44
"classifications": [ "Common", "AI", "API", "Web", "Web API", "WebAPI", "Service" ],
5-
"identity": "Microsoft.Agents.AI.Templates.WebApiAgent.CSharp",
5+
"identity": "Microsoft.Agents.AI.ProjectTemplates.WebApiAgent.CSharp",
66
"name": "AI Agent Web API",
77
"description": "A project template for creating an AI Agent Web API application.",
88
"shortName": "aiagent-webapi",

src/ProjectTemplates/Microsoft.Agents.AI.Templates/src/WebApiAgent/WebApiAgent-CSharp/Program.cs renamed to src/ProjectTemplates/Microsoft.Agents.AI.ProjectTemplates/src/WebApiAgent/WebApiAgent-CSharp/Program.cs

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,41 @@
88
using Azure.Identity;
99
#endif
1010
using Microsoft.Agents.AI;
11+
using Microsoft.Agents.AI.DevUI;
1112
using Microsoft.Agents.AI.Hosting;
1213
using Microsoft.Agents.AI.Workflows;
1314
using Microsoft.Extensions.AI;
1415
#if (IsOllama)
1516
using OllamaSharp;
16-
#elif (IsGHModels || IsOpenAI || IsAzureOpenAI)
17+
#endif
18+
#if (IsGHModels || IsAzureOpenAI)
1719
using OpenAI;
1820
#endif
21+
#if (IsGHModels || IsOpenAI || IsAzureOpenAI)
22+
using OpenAI.Chat;
23+
#endif
1924

2025
var builder = WebApplication.CreateBuilder(args);
2126

2227
#if (IsGHModels)
2328
// You will need to set the token to your own value
2429
// You can do this using Visual Studio's "Manage User Secrets" UI, or on the command line:
2530
// cd this-project-directory
26-
// dotnet user-secrets set GitHubModels:Token YOUR-GITHUB-TOKEN
27-
var credential = new ApiKeyCredential(builder.Configuration["GitHubModels:Token"] ?? throw new InvalidOperationException("Missing configuration: GitHubModels:Token. See README for details."));
28-
var openAIOptions = new OpenAIClientOptions { Endpoint = new Uri("https://models.inference.ai.azure.com") };
29-
30-
var chatClient = new OpenAIClient(credential, openAIOptions)
31-
.GetChatClient("gpt-4o-mini").AsIChatClient();
32-
#elif (IsOllama)
33-
// You will need to have Ollama running locally with the llama3.2 model installed
34-
// Visit https://ollama.com for installation instructions
35-
var chatClient = new OllamaApiClient(new Uri("http://localhost:11434"), "llama3.2");
31+
// dotnet user-secrets set "GITHUB_TOKEN" "your-github-models-token-here"
32+
var chatClient = new ChatClient(
33+
"gpt-4o-mini",
34+
new ApiKeyCredential(builder.Configuration["GITHUB_TOKEN"] ?? throw new InvalidOperationException("Missing configuration: GITHUB_TOKEN")),
35+
new OpenAIClientOptions { Endpoint = new Uri("https://models.inference.ai.azure.com") })
36+
.AsIChatClient();
3637
#elif (IsOpenAI)
3738
// You will need to set the API key to your own value
3839
// You can do this using Visual Studio's "Manage User Secrets" UI, or on the command line:
3940
// cd this-project-directory
40-
// dotnet user-secrets set OpenAI:Key YOUR-API-KEY
41-
var openAIClient = new OpenAIClient(
42-
new ApiKeyCredential(builder.Configuration["OpenAI:Key"] ?? throw new InvalidOperationException("Missing configuration: OpenAI:Key. See README for details.")));
43-
44-
#pragma warning disable OPENAI001 // GetOpenAIResponseClient(string) is experimental and subject to change or removal in future updates.
45-
var chatClient = openAIClient.GetOpenAIResponseClient("gpt-4o-mini").AsIChatClient();
46-
#pragma warning restore OPENAI001
41+
// dotnet user-secrets set "OPENAI_KEY" "your-openai-api-key-here"
42+
var chatClient = new ChatClient(
43+
"gpt-4o-mini",
44+
new ApiKeyCredential(builder.Configuration["OPENAI_KEY"] ?? throw new InvalidOperationException("Missing configuration: OPENAI_KEY")))
45+
.AsIChatClient();
4746
#elif (IsAzureOpenAI)
4847
// You will need to set the endpoint to your own value
4948
// You can do this using Visual Studio's "Manage User Secrets" UI, or on the command line:
@@ -52,21 +51,27 @@
5251
#if (!IsManagedIdentity)
5352
// dotnet user-secrets set AzureOpenAI:Key YOUR-API-KEY
5453
#endif
55-
var azureOpenAIEndpoint = new Uri(new Uri(builder.Configuration["AzureOpenAI:Endpoint"] ?? throw new InvalidOperationException("Missing configuration: AzureOpenAI:Endpoint. See README for details.")), "/openai/v1");
56-
#if (IsManagedIdentity)
57-
#pragma warning disable OPENAI001 // OpenAIClient(AuthenticationPolicy, OpenAIClientOptions) and GetOpenAIResponseClient(string) are experimental and subject to change or removal in future updates.
58-
var azureOpenAI = new OpenAIClient(
59-
new BearerTokenPolicy(new DefaultAzureCredential(), "https://ai.azure.com/.default"),
60-
new OpenAIClientOptions { Endpoint = azureOpenAIEndpoint });
61-
62-
#elif (!IsManagedIdentity)
63-
var openAIOptions = new OpenAIClientOptions { Endpoint = azureOpenAIEndpoint };
64-
var azureOpenAI = new OpenAIClient(new ApiKeyCredential(builder.Configuration["AzureOpenAI:Key"] ?? throw new InvalidOperationException("Missing configuration: AzureOpenAI:Key. See README for details.")), openAIOptions);
54+
var azureOpenAIEndpoint = new Uri(new Uri(builder.Configuration["AzureOpenAI:Endpoint"] ?? throw new InvalidOperationException("Missing configuration: AzureOpenAI:Endpoint")), "/openai/v1");
6555

66-
#pragma warning disable OPENAI001 // GetOpenAIResponseClient(string) is experimental and subject to change or removal in future updates.
67-
#endif
68-
var chatClient = azureOpenAI.GetOpenAIResponseClient("gpt-4o-mini").AsIChatClient();
56+
#if (IsManagedIdentity)
57+
#pragma warning disable OPENAI001 // The overload accepting an AuthenticationPolicy is experimental and may change or be removed in future releases.
58+
var chatClient = new ChatClient(
59+
"gpt-4o-mini",
60+
new BearerTokenPolicy(new DefaultAzureCredential(), "https://ai.azure.com/.default"),
61+
new OpenAIClientOptions { Endpoint = azureOpenAIEndpoint })
62+
.AsIChatClient();
6963
#pragma warning restore OPENAI001
64+
#else
65+
var chatClient = new ChatClient(
66+
"gpt-4o-mini",
67+
new ApiKeyCredential(builder.Configuration["AzureOpenAI:Key"] ?? throw new InvalidOperationException("Missing configuration: AzureOpenAI:Key")),
68+
new OpenAIClientOptions { Endpoint = azureOpenAIEndpoint })
69+
.AsIChatClient();
70+
#endif
71+
#elif (IsOllama)
72+
// You will need to have Ollama running locally with the llama3.2 model installed
73+
// Visit https://ollama.com for installation instructions
74+
var chatClient = new OllamaApiClient(new Uri("http://localhost:11434"), "llama3.2");
7075
#endif
7176

7277
builder.Services.AddChatClient(chatClient);
@@ -76,8 +81,8 @@
7681
builder.AddAIAgent("editor", (sp, key) => new ChatClientAgent(
7782
chatClient,
7883
name: key,
79-
instructions: "You edit short stories to improve grammar and style. You ensure the stories are less than 300 words.",
80-
tools: [ AIFunctionFactory.Create(FormatStory) ]
84+
instructions: "You edit short stories to improve grammar and style, ensuring the stories are less than 300 words. Once finished editing, you select a title and format the story for publishing.",
85+
tools: [AIFunctionFactory.Create(FormatStory)]
8186
));
8287

8388
builder.AddWorkflow("publisher", (sp, key) => AgentWorkflowBuilder.BuildSequential(
@@ -86,17 +91,28 @@
8691
sp.GetRequiredKeyedService<AIAgent>("editor")
8792
)).AddAsAIAgent();
8893

89-
var app = builder.Build();
94+
// Register services for OpenAI responses and conversations (also required for DevUI)
95+
builder.Services.AddOpenAIResponses();
96+
builder.Services.AddOpenAIConversations();
9097

98+
var app = builder.Build();
9199
app.UseHttpsRedirection();
100+
101+
// Map endpoints for OpenAI responses and conversations (also required for DevUI)
92102
app.MapOpenAIResponses();
103+
app.MapOpenAIConversations();
104+
105+
if (builder.Environment.IsDevelopment())
106+
{
107+
// Map DevUI endpoint to /devui
108+
app.MapDevUI();
109+
}
93110

94111
app.Run();
95112

96-
[Description("Formats the story for display.")]
113+
[Description("Formats the story for publication, revealing its title.")]
97114
string FormatStory(string title, string story) => $"""
98115
**Title**: {title}
99-
**Date**: {DateTime.Today.ToShortDateString()}
100116
101117
{story}
102118
""";

0 commit comments

Comments
 (0)