mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
469525d9e6 | ||
|
|
6e04c6bbbe | ||
|
|
f5d6056074 | ||
|
|
9586a3ea53 | ||
|
|
82bd9cf6b5 |
@@ -32,7 +32,6 @@
|
||||
<Folder Name="/Samples/GettingStarted/AgentProviders/">
|
||||
<File Path="samples/GettingStarted/AgentProviders/README.md" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_A2A/Agent_With_A2A.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/Agent_With_AzureAIAgent.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryAgent/Agent_With_AzureFoundryAgent.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureFoundryModel/Agent_With_AzureFoundryModel.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureOpenAIChatCompletion/Agent_With_AzureOpenAIChatCompletion.csproj" />
|
||||
@@ -44,6 +43,23 @@
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_OpenAIChatCompletion/Agent_With_OpenAIChatCompletion.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_OpenAIResponses/Agent_With_OpenAIResponses.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/GettingStarted/AgentProviders/AzureAIAgents/">
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step01.1_Basics/AzureAIAgents_Step01.1_Basics.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step01.2_Running/AzureAIAgents_Step01.2_Running.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step02_MultiturnConversation/AzureAIAgents_Step02_MultiturnConversation.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step03.1_UsingFunctionTools/AzureAIAgents_Step03.1_UsingFunctionTools.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step03.2_UsingFunctionTools_FromOpenAPI/AzureAIAgents_Step03.2_UsingFunctionTools_FromOpenAPI.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step04_UsingFunctionToolsWithApprovals/AzureAIAgents_Step04_UsingFunctionToolsWithApprovals.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step05_StructuredOutput/AzureAIAgents_Step05_StructuredOutput.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step06_PersistedConversations/AzureAIAgents_Step06_PersistedConversations.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step07_Observability/AzureAIAgents_Step07_Observability.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step08_DependencyInjection/AzureAIAgents_Step08_DependencyInjection.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step09_AsMcpTool/AzureAIAgents_Step09_AsMcpTool.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step10_UsingImages/AzureAIAgents_Step10_UsingImages.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step11_AsFunctionTool/AzureAIAgents_Step11_AsFunctionTool.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step12_Middleware/AzureAIAgents_Step12_Middleware.csproj" />
|
||||
<Project Path="samples/GettingStarted/AgentProviders/Agent_With_AzureAIAgent/AzureAIAgents_Step13_Plugins/AzureAIAgents_Step13_Plugins.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/GettingStarted/Agents/">
|
||||
<File Path="samples/GettingStarted/Agents/README.md" />
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step01_Running/Agent_Step01_Running.csproj" />
|
||||
@@ -62,7 +78,6 @@
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step13_Memory/Agent_Step13_Memory.csproj" />
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step14_Middleware/Agent_Step14_Middleware.csproj" />
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step15_Plugins/Agent_Step15_Plugins.csproj" />
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj" />
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step17_BackgroundResponses/Agent_Step17_BackgroundResponses.csproj" />
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step18_TextSearchRag/Agent_Step18_TextSearchRag.csproj" />
|
||||
<Project Path="samples/GettingStarted/Agents/Agent_Step19_Mem0Provider/Agent_Step19_Mem0Provider.csproj" />
|
||||
@@ -283,8 +298,8 @@
|
||||
<Project Path="src/Microsoft.Agents.AI.A2A/Microsoft.Agents.AI.A2A.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.Abstractions/Microsoft.Agents.AI.Abstractions.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.AGUI/Microsoft.Agents.AI.AGUI.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.AzureAI/Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<Project Path="src/Microsoft.Agents.AI.AzureAI.Persistent/Microsoft.Agents.AI.AzureAI.Persistent.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" />
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with Azure Foundry Agents as the backend.
|
||||
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
const string JokerName = "JokerAgent";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
var agentDefinition = new PromptAgentDefinition(model: deploymentName) { Instructions = JokerInstructions };
|
||||
|
||||
// Azure.AI.Agents SDK creates and manages agent by name and versions.
|
||||
// You can create a server side agent version with the Azure.AI.Agents SDK client below.
|
||||
var agentVersion = agentsClient.CreateAgentVersion(agentName: JokerName, definition: agentDefinition);
|
||||
|
||||
// You can retrieve an AIAgent for a already created server side agent version.
|
||||
AIAgent jokerAgent = agentsClient.GetAIAgent(agentVersion);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
AgentThread thread = jokerAgent.GetNewThread();
|
||||
Console.WriteLine(await jokerAgent.RunAsync("Tell me a joke about a pirate.", thread));
|
||||
|
||||
// Invoke the agent with streaming support.
|
||||
thread = jokerAgent.GetNewThread();
|
||||
await foreach (var update in jokerAgent.RunStreamingAsync("Tell me a joke about a pirate.", thread))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(jokerAgent.Name);
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with a multi-turn conversation.
|
||||
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
const string JokerName = "JokerAgent";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
var agentDefinition = new PromptAgentDefinition(model: deploymentName) { Instructions = JokerInstructions };
|
||||
|
||||
// Create a server side agent version with the Azure.AI.Agents SDK client.
|
||||
var agentVersion = agentsClient.CreateAgentVersion(agentName: JokerName, definition: agentDefinition);
|
||||
|
||||
// Retrieve an AIAgent for the created server side agent version.
|
||||
AIAgent jokerAgent = agentsClient.GetAIAgent(agentVersion);
|
||||
|
||||
// Invoke the agent with a multi-turn conversation, where the context is preserved in the thread object.
|
||||
AgentThread thread = jokerAgent.GetNewThread();
|
||||
Console.WriteLine(await jokerAgent.RunAsync("Tell me a joke about a pirate.", thread));
|
||||
Console.WriteLine(await jokerAgent.RunAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", thread));
|
||||
|
||||
// Invoke the agent with a multi-turn conversation and streaming, where the context is preserved in the thread object.
|
||||
thread = jokerAgent.GetNewThread();
|
||||
await foreach (var update in jokerAgent.RunStreamingAsync("Tell me a joke about a pirate.", thread))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
await foreach (var update in jokerAgent.RunStreamingAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", thread))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(jokerAgent.Name);
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use an agent with function tools.
|
||||
// It shows both non-streaming and streaming agent interactions using weather-related tools.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
const string AssistantInstructions = "You are a helpful assistant that can get weather information.";
|
||||
const string AssistantName = "WeatherAssistant";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Define the agent with function tools.
|
||||
var tool = AIFunctionFactory.Create(GetWeather);
|
||||
|
||||
// Create AIAgent directly
|
||||
AIAgent agent = await agentsClient.CreateAIAgentAsync(name: AssistantName, model: deploymentName, instructions: AssistantInstructions, tools: [tool]);
|
||||
|
||||
// Non-streaming agent interaction with function tools.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", thread));
|
||||
|
||||
// Streaming agent interaction with function tools.
|
||||
thread = agent.GetNewThread();
|
||||
await foreach (var update in agent.RunStreamingAsync("What is the weather like in Amsterdam?", thread))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.OpenApi" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="OpenAPISpec.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
{
|
||||
"openapi": "3.0.1",
|
||||
"info": {
|
||||
"title": "Github Versions API",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "https://api.github.com"
|
||||
}
|
||||
],
|
||||
"components": {
|
||||
"schemas": {
|
||||
"basic-error": {
|
||||
"title": "Basic Error",
|
||||
"description": "Basic Error",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"documentation_url": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"status": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"label": {
|
||||
"title": "Label",
|
||||
"description": "Color-coded labels help you categorize and filter your issues (just like labels in Gmail).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"description": "Unique identifier for the label.",
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"example": 208045946
|
||||
},
|
||||
"node_id": {
|
||||
"type": "string",
|
||||
"example": "MDU6TGFiZWwyMDgwNDU5NDY="
|
||||
},
|
||||
"url": {
|
||||
"description": "URL for the label",
|
||||
"example": "https://api.github.com/repositories/42/labels/bug",
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the label.",
|
||||
"example": "bug",
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"description": "Optional description of the label, such as its purpose.",
|
||||
"type": "string",
|
||||
"example": "Something isn't working",
|
||||
"nullable": true
|
||||
},
|
||||
"color": {
|
||||
"description": "6-character hex code, without the leading #, identifying the color",
|
||||
"example": "FFFFFF",
|
||||
"type": "string"
|
||||
},
|
||||
"default": {
|
||||
"description": "Whether this label comes by default in a new repository.",
|
||||
"type": "boolean",
|
||||
"example": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"node_id",
|
||||
"url",
|
||||
"name",
|
||||
"description",
|
||||
"color",
|
||||
"default"
|
||||
]
|
||||
},
|
||||
"tag": {
|
||||
"title": "Tag",
|
||||
"description": "Tag",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"example": "v0.1"
|
||||
},
|
||||
"commit": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sha": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"sha",
|
||||
"url"
|
||||
]
|
||||
},
|
||||
"zipball_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"example": "https://github.com/octocat/Hello-World/zipball/v0.1"
|
||||
},
|
||||
"tarball_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"example": "https://github.com/octocat/Hello-World/tarball/v0.1"
|
||||
},
|
||||
"node_id": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"name",
|
||||
"node_id",
|
||||
"commit",
|
||||
"zipball_url",
|
||||
"tarball_url"
|
||||
]
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"label-items": {
|
||||
"value": [
|
||||
{
|
||||
"id": 208045946,
|
||||
"node_id": "MDU6TGFiZWwyMDgwNDU5NDY=",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/labels/bug",
|
||||
"name": "bug",
|
||||
"description": "Something isn't working",
|
||||
"color": "f29513",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"id": 208045947,
|
||||
"node_id": "MDU6TGFiZWwyMDgwNDU5NDc=",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/labels/enhancement",
|
||||
"name": "enhancement",
|
||||
"description": "New feature or request",
|
||||
"color": "a2eeef",
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"tag-items": {
|
||||
"value": [
|
||||
{
|
||||
"name": "v0.1",
|
||||
"commit": {
|
||||
"sha": "c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc",
|
||||
"url": "https://api.github.com/repos/octocat/Hello-World/commits/c5b97d5ae6c19d5c5df71a34c7fbeeda2479ccbc"
|
||||
},
|
||||
"zipball_url": "https://github.com/octocat/Hello-World/zipball/v0.1",
|
||||
"tarball_url": "https://github.com/octocat/Hello-World/tarball/v0.1",
|
||||
"node_id": "MDQ6VXNlcjE="
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"parameters": {
|
||||
"owner": {
|
||||
"name": "owner",
|
||||
"description": "The account owner of the repository. The name is not case sensitive.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"repo": {
|
||||
"name": "repo",
|
||||
"description": "The name of the repository without the `.git` extension. The name is not case sensitive.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"per-page": {
|
||||
"name": "per_page",
|
||||
"description": "The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 30
|
||||
}
|
||||
},
|
||||
"page": {
|
||||
"name": "page",
|
||||
"description": "The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"",
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"default": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"not_found": {
|
||||
"description": "Resource not found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/basic-error"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"link": {
|
||||
"example": "<https://api.github.com/resource?page=2>; rel=\"next\", <https://api.github.com/resource?page=5>; rel=\"last\"",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"paths": {
|
||||
"/repos/{owner}/{repo}/tags": {
|
||||
"get": {
|
||||
"summary": "List repository tags",
|
||||
"description": "",
|
||||
"tags": [
|
||||
"repos"
|
||||
],
|
||||
"operationId": "repos/list-tags",
|
||||
"externalDocs": {
|
||||
"description": "API method documentation",
|
||||
"url": "https://docs.github.com/rest/repos/repos#list-repository-tags"
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/owner"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/repo"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/per-page"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/page"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/tag"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"default": {
|
||||
"$ref": "#/components/examples/tag-items"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"Link": {
|
||||
"$ref": "#/components/headers/link"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"x-github": {
|
||||
"githubCloudOnly": false,
|
||||
"enabledForGitHubApps": true,
|
||||
"category": "repos",
|
||||
"subcategory": "repos"
|
||||
}
|
||||
}
|
||||
},
|
||||
"/repos/{owner}/{repo}/labels": {
|
||||
"get": {
|
||||
"summary": "List labels for a repository",
|
||||
"description": "Lists all labels for a repository.",
|
||||
"tags": [
|
||||
"issues"
|
||||
],
|
||||
"operationId": "issues/list-labels-for-repo",
|
||||
"externalDocs": {
|
||||
"description": "API method documentation",
|
||||
"url": "https://docs.github.com/rest/issues/labels#list-labels-for-a-repository"
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/parameters/owner"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/repo"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/per-page"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/parameters/page"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/label"
|
||||
}
|
||||
},
|
||||
"examples": {
|
||||
"default": {
|
||||
"$ref": "#/components/examples/label-items"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"headers": {
|
||||
"Link": {
|
||||
"$ref": "#/components/headers/link"
|
||||
}
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/components/responses/not_found"
|
||||
}
|
||||
},
|
||||
"x-github": {
|
||||
"githubCloudOnly": false,
|
||||
"enabledForGitHubApps": true,
|
||||
"category": "issues",
|
||||
"subcategory": "labels"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use an agent with function tools provided via an OpenAPI spec.
|
||||
// It uses functionality from Semantic Kernel to parse the OpenAPI spec and create function tools to use with the Agent Framework Agent.
|
||||
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.SemanticKernel;
|
||||
using Microsoft.SemanticKernel.Plugins.OpenApi;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// Load the OpenAPI Spec from a file.
|
||||
KernelPlugin plugin = await OpenApiKernelPluginFactory.CreateFromOpenApiAsync("github", "OpenAPISpec.json");
|
||||
|
||||
// Convert the Semantic Kernel plugin to Agent Framework function tools.
|
||||
// This requires a dummy Kernel instance, since KernelFunctions cannot execute without one.
|
||||
Kernel kernel = new();
|
||||
List<AITool> tools = plugin.Select(x => x.WithKernel(kernel)).Cast<AITool>().ToList();
|
||||
|
||||
const string AssistantInstructions = "You are a helpful assistant that can query GitHub repositories.";
|
||||
const string AssistantName = "GitHubAssistant";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Create AIAgent directly
|
||||
AIAgent agent = await agentsClient.CreateAIAgentAsync(name: AssistantName, model: deploymentName, instructions: AssistantInstructions, tools: tools);
|
||||
|
||||
// Run the agent with the OpenAPI function tools.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
Console.WriteLine(await agent.RunAsync("Please list the names, colors and descriptions of all the labels available in the microsoft/agent-framework repository on github.", thread));
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use an agent with function tools that require a human in the loop for approvals.
|
||||
// It shows both non-streaming and streaming agent interactions using weather-related tools.
|
||||
// If the agent is hosted in a service, with a remote user, combine this sample with the Persisted Conversations sample to persist the chat history
|
||||
// while the agent is waiting for user input.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// Create a sample function tool that the agent can use.
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
const string AssistantInstructions = "You are a helpful assistant that can get weather information.";
|
||||
const string AssistantName = "WeatherAssistant";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
var approvalTool = new ApprovalRequiredAIFunction(AIFunctionFactory.Create(GetWeather));
|
||||
|
||||
// Create AIAgent directly
|
||||
AIAgent agent = await agentsClient.CreateAIAgentAsync(name: AssistantName, model: deploymentName, instructions: AssistantInstructions, tools: [approvalTool]);
|
||||
|
||||
// Call the agent with approval-required function tools.
|
||||
// The agent will request approval before invoking the function.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
var response = await agent.RunAsync("What is the weather like in Amsterdam?", thread);
|
||||
|
||||
// Check if there are any user input requests (approvals needed).
|
||||
var userInputRequests = response.UserInputRequests.ToList();
|
||||
|
||||
while (userInputRequests.Count > 0)
|
||||
{
|
||||
// Ask the user to approve each function call request.
|
||||
// For simplicity, we are assuming here that only function approval requests are being made.
|
||||
var userInputMessages = userInputRequests
|
||||
.OfType<FunctionApprovalRequestContent>()
|
||||
.Select(functionApprovalRequest =>
|
||||
{
|
||||
Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {functionApprovalRequest.FunctionCall.Name}");
|
||||
var approved = Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false;
|
||||
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(approved)]);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
// Pass the user input responses back to the agent for further processing.
|
||||
response = await agent.RunAsync(userInputMessages, thread);
|
||||
|
||||
userInputRequests = response.UserInputRequests.ToList();
|
||||
}
|
||||
|
||||
Console.WriteLine($"\nAgent: {response}");
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to configure an agent to produce structured output.
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using SampleApp;
|
||||
|
||||
#pragma warning disable CA5399
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = "gpt-5"; // Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string AssistantInstructions = "You are a helpful assistant that extracts structured information about people.";
|
||||
const string AssistantName = "StructuredOutputAssistant";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Create ChatClientAgent directly
|
||||
ChatClientAgent agent = await agentsClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
new ChatClientAgentOptions(name: AssistantName, instructions: AssistantInstructions));
|
||||
|
||||
// Set PersonInfo as the type parameter of RunAsync method to specify the expected structured output from the agent and invoke the agent with some unstructured input.
|
||||
AgentRunResponse<PersonInfo> response = await agent.RunAsync<PersonInfo>("Please provide information about John Smith, who is a 35-year-old software engineer.");
|
||||
|
||||
// Access the structured output via the Result property of the agent response.
|
||||
Console.WriteLine("Assistant Output:");
|
||||
Console.WriteLine($"Name: {response.Result.Name}");
|
||||
Console.WriteLine($"Age: {response.Result.Age}");
|
||||
Console.WriteLine($"Occupation: {response.Result.Occupation}");
|
||||
|
||||
// Create the ChatClientAgent with the specified name, instructions, and expected structured output the agent should produce.
|
||||
ChatClientAgent agentWithPersonInfo = agentsClient.CreateAIAgent(model: deploymentName, new ChatClientAgentOptions(name: AssistantName, instructions: AssistantInstructions)
|
||||
{
|
||||
ChatOptions = new()
|
||||
{
|
||||
ResponseFormat = Microsoft.Extensions.AI.ChatResponseFormat.ForJsonSchema<PersonInfo>()
|
||||
}
|
||||
});
|
||||
|
||||
// Invoke the agent with some unstructured input while streaming, to extract the structured information from.
|
||||
var updates = agentWithPersonInfo.RunStreamingAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");
|
||||
|
||||
// Assemble all the parts of the streamed output, since we can only deserialize once we have the full json,
|
||||
// then deserialize the response into the PersonInfo class.
|
||||
PersonInfo personInfo = (await updates.ToAgentRunResponseAsync()).Deserialize<PersonInfo>(JsonSerializerOptions.Web);
|
||||
|
||||
Console.WriteLine("Assistant Output:");
|
||||
Console.WriteLine($"Name: {personInfo.Name}");
|
||||
Console.WriteLine($"Age: {personInfo.Age}");
|
||||
Console.WriteLine($"Occupation: {personInfo.Occupation}");
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents information about a person, including their name, age, and occupation, matched to the JSON schema used in the agent.
|
||||
/// </summary>
|
||||
[Description("Information about a person including their name, age, and occupation")]
|
||||
public class PersonInfo
|
||||
{
|
||||
[JsonPropertyName("name")]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[JsonPropertyName("age")]
|
||||
public int? Age { get; set; }
|
||||
|
||||
[JsonPropertyName("occupation")]
|
||||
public string? Occupation { get; set; }
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with a conversation that can be persisted to disk.
|
||||
|
||||
using System.Text.Json;
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
const string JokerName = "JokerAgent";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
AIAgent agent = await agentsClient.CreateAIAgentAsync(name: JokerName, model: deploymentName, instructions: JokerInstructions);
|
||||
|
||||
// Start a new thread for the agent conversation.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
|
||||
// Run the agent with a new thread.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread));
|
||||
|
||||
// Serialize the thread state to a JsonElement, so it can be stored for later use.
|
||||
JsonElement serializedThread = thread.Serialize();
|
||||
|
||||
// Save the serialized thread to a temporary file (for demonstration purposes).
|
||||
string tempFilePath = Path.GetTempFileName();
|
||||
await File.WriteAllTextAsync(tempFilePath, JsonSerializer.Serialize(serializedThread));
|
||||
|
||||
// Load the serialized thread from the temporary file (for demonstration purposes).
|
||||
JsonElement reloadedSerializedThread = JsonSerializer.Deserialize<JsonElement>(await File.ReadAllTextAsync(tempFilePath));
|
||||
|
||||
// Deserialize the thread state after loading from storage.
|
||||
AgentThread resumedThread = agent.DeserializeThread(reloadedSerializedThread);
|
||||
|
||||
// Run the agent again with the resumed thread.
|
||||
Console.WriteLine(await agent.RunAsync("Now tell the same joke in the voice of a pirate, and add some emojis to the joke.", resumedThread));
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" />
|
||||
<PackageReference Include="OpenTelemetry" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use a simple AI agent with Azure Foundry Agents as the backend that logs telemetry using OpenTelemetry.
|
||||
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Azure.Monitor.OpenTelemetry.Exporter;
|
||||
using Microsoft.Agents.AI;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
var applicationInsightsConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING");
|
||||
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
const string JokerName = "JokerAgent";
|
||||
|
||||
// Create TracerProvider with console exporter
|
||||
// This will output the telemetry data to the console.
|
||||
string sourceName = Guid.NewGuid().ToString("N");
|
||||
var tracerProviderBuilder = Sdk.CreateTracerProviderBuilder()
|
||||
.AddSource(sourceName)
|
||||
.AddConsoleExporter();
|
||||
if (!string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
|
||||
{
|
||||
tracerProviderBuilder.AddAzureMonitorTraceExporter(options => options.ConnectionString = applicationInsightsConnectionString);
|
||||
}
|
||||
using var tracerProvider = tracerProviderBuilder.Build();
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
AIAgent agent = agentsClient.CreateAIAgent(name: JokerName, model: deploymentName, instructions: JokerInstructions)
|
||||
.AsBuilder()
|
||||
.UseOpenTelemetry(sourceName: sourceName)
|
||||
.Build();
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread));
|
||||
|
||||
// Invoke the agent with streaming support.
|
||||
thread = agent.GetNewThread();
|
||||
await foreach (var update in agent.RunStreamingAsync("Tell me a joke about a pirate.", thread))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#pragma warning disable CA1812
|
||||
|
||||
// This sample shows how to use dependency injection to register an AIAgent and use it from a hosted service with a user input chat loop.
|
||||
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerInstructions = "You are good at telling jokes.";
|
||||
const string JokerName = "JokerAgent";
|
||||
|
||||
// Create a host builder that we will register services with and then run.
|
||||
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
// Add the agents client to the service collection.
|
||||
builder.Services.AddSingleton((sp) => new AgentsClient(new Uri(endpoint), new AzureCliCredential()));
|
||||
|
||||
// Add the AI agent to the service collection.
|
||||
builder.Services.AddSingleton<AIAgent>((sp)
|
||||
=> sp.GetRequiredService<AgentsClient>()
|
||||
.CreateAIAgent(name: JokerName, model: deploymentName, instructions: JokerInstructions));
|
||||
|
||||
// Add a sample service that will use the agent to respond to user input.
|
||||
builder.Services.AddHostedService<SampleService>();
|
||||
|
||||
// Build and run the host.
|
||||
using IHost host = builder.Build();
|
||||
await host.RunAsync().ConfigureAwait(false);
|
||||
|
||||
/// <summary>
|
||||
/// A sample service that uses an AI agent to respond to user input.
|
||||
/// </summary>
|
||||
internal sealed class SampleService(AIAgent agent, IHostApplicationLifetime appLifetime) : IHostedService
|
||||
{
|
||||
private AgentThread? _thread;
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
// Create a thread that will be used for the entirety of the service lifetime so that the user can ask follow up questions.
|
||||
this._thread = agent.GetNewThread();
|
||||
_ = this.RunAsync(appLifetime.ApplicationStopping);
|
||||
}
|
||||
|
||||
public async Task RunAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
// Delay a little to allow the service to finish starting.
|
||||
await Task.Delay(100, cancellationToken);
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
Console.WriteLine("\nAgent: Ask me to tell you a joke about a specific topic. To exit just press Ctrl+C or enter without any input.\n");
|
||||
Console.Write("> ");
|
||||
var input = Console.ReadLine();
|
||||
|
||||
// If the user enters no input, signal the application to shut down.
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
appLifetime.StopApplication();
|
||||
break;
|
||||
}
|
||||
|
||||
// Stream the output to the console as it is generated.
|
||||
await foreach (var update in agent.RunStreamingAsync(input, this._thread, cancellationToken: cancellationToken))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>3afc9b74-af74-4d8e-ae96-fa1c511d11ac</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents.Persistent" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
<PackageReference Include="ModelContextProtocol" />
|
||||
<PackageReference Include="System.Net.ServerSentEvents" VersionOverride="10.0.0-rc.2.25502.107" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to expose an AI agent as an MCP tool.
|
||||
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using ModelContextProtocol.Server;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerInstructions = "You are good at telling jokes, and you always start each joke with 'Aye aye, captain!'.";
|
||||
const string JokerName = "JokerAgent";
|
||||
const string JokerDescription = "An agent that tells jokes.";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
AIAgent agent = agentsClient.CreateAIAgent(
|
||||
name: JokerName,
|
||||
model: deploymentName,
|
||||
instructions: JokerInstructions,
|
||||
creationOptions: new() { Description = JokerDescription });
|
||||
|
||||
// Convert the agent to an AIFunction and then to an MCP tool.
|
||||
// The agent name and description will be used as the mcp tool name and description.
|
||||
McpServerTool tool = McpServerTool.Create(agent.AsAIFunction());
|
||||
|
||||
// Register the MCP server with StdIO transport and expose the tool via the server.
|
||||
HostApplicationBuilder builder = Host.CreateEmptyApplicationBuilder(settings: null);
|
||||
builder.Services
|
||||
.AddMcpServer()
|
||||
.WithStdioServerTransport()
|
||||
.WithTools([tool]);
|
||||
|
||||
Console.WriteLine("Starting MCP Tool server. Press Ctrl+C to exit.");
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
This sample demonstrates how to expose an existing AI agent as an MCP tool.
|
||||
|
||||
## Run the sample
|
||||
|
||||
To run the sample, please use one of the following MCP clients: https://modelcontextprotocol.io/clients
|
||||
|
||||
Alternatively, use the QuickstartClient sample from this repository: https://github.com/modelcontextprotocol/csharp-sdk/tree/main/samples/QuickstartClient
|
||||
|
||||
## Run the sample using MCP Inspector
|
||||
|
||||
To use the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector), follow these steps:
|
||||
|
||||
1. Open a terminal in the Agent_Step10_AsMcpTool project directory.
|
||||
1. Run the `npx @modelcontextprotocol/inspector dotnet run` command to start the MCP Inspector. Make sure you have [node.js](https://nodejs.org/en/download/) and npm installed.
|
||||
```bash
|
||||
npx @modelcontextprotocol/inspector dotnet run
|
||||
```
|
||||
1. When the inspector is running, it will display a URL in the terminal, like this:
|
||||
```
|
||||
MCP Inspector is up and running at http://127.0.0.1:6274
|
||||
```
|
||||
1. Open a web browser and navigate to the URL displayed in the terminal. If not opened automatically, this will open the MCP Inspector interface.
|
||||
1. In the MCP Inspector interface, add the following environment variables to allow your MCP server to access Azure AI Foundry Project to create and run the agent:
|
||||
- AZURE_FOUNDRY_PROJECT_ENDPOINT = https://your-resource.openai.azure.com/ # Replace with your Azure AI Foundry Project endpoint
|
||||
- AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME = gpt-4o-mini # Replace with your model deployment name
|
||||
1. Find and click the `Connect` button in the MCP Inspector interface to connect to the MCP server.
|
||||
1. As soon as the connection is established, open the `Tools` tab in the MCP Inspector interface and select the `Joker` tool from the list.
|
||||
1. Specify your prompt as a value for the `query` argument, for example: `Tell me a joke about a pirate` and click the `Run Tool` button to run the tool.
|
||||
1. The agent will process the request and return a response in accordance with the provided instructions that instruct it to always start each joke with 'Aye aye, captain!'.
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use Image Multi-Modality with an AI agent.
|
||||
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
|
||||
const string VisionInstructions = "You are a helpful agent that can analyze images";
|
||||
const string VisionName = "VisionAgent";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
AIAgent agent = agentsClient.CreateAIAgent(name: VisionName, model: deploymentName, instructions: VisionInstructions);
|
||||
|
||||
ChatMessage message = new(ChatRole.User, [
|
||||
new TextContent("What do you see in this image?"),
|
||||
new UriContent("https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", "image/jpeg")
|
||||
]);
|
||||
|
||||
var thread = agent.GetNewThread();
|
||||
|
||||
await foreach (var update in agent.RunStreamingAsync(message, thread))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
# Using Images with AI Agents
|
||||
|
||||
This sample demonstrates how to use image multi-modality with an AI agent. It shows how to create a vision-enabled agent that can analyze and describe images using Azure OpenAI.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating a persistent AI agent with vision capabilities
|
||||
- Sending both text and image content to an agent in a single message
|
||||
- Using `UriContent` to Uri referenced images
|
||||
- Processing multimodal input (text + image) with an AI agent
|
||||
|
||||
## Key features
|
||||
|
||||
- **Vision Agent**: Creates an agent specifically instructed to analyze images
|
||||
- **Multimodal Input**: Combines text questions with image uri in a single message
|
||||
- **Azure OpenAI Integration**: Uses AzureOpenAI LLM agents
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before running this sample, ensure you have:
|
||||
|
||||
1. An Azure OpenAI project set up
|
||||
2. A compatible model deployment (e.g., gpt-4o)
|
||||
3. Azure CLI installed and authenticated
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/" # Replace with your Azure OpenAI endpoint
|
||||
$env:AZURE_OPENAI_DEPLOYMENT_NAME="gpt-4o" # Replace with your model deployment name (optional, defaults to gpt-4o)
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
Navigate to the sample directory and run:
|
||||
|
||||
```powershell
|
||||
cd Agent_Step11_UsingImages
|
||||
dotnet run
|
||||
```
|
||||
|
||||
## Expected behavior
|
||||
|
||||
The sample will:
|
||||
|
||||
1. Create a vision-enabled agent named "VisionAgent"
|
||||
2. Send a message containing both text ("What do you see in this image?") and a Uri image of a green walk
|
||||
3. The agent will analyze the image and provide a description
|
||||
4. Clean up resources by deleting the thread and agent
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>3afc9b74-af74-4d8e-ae96-fa1c511d11ac</UserSecretsId>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use an Azure Foundry Agents AI agent as a function tool.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string WeatherInstructions = "You answer questions about the weather.";
|
||||
const string WeatherName = "WeatherAgent";
|
||||
const string MainInstructions = "You are a helpful assistant who responds in French.";
|
||||
const string MainName = "MainAgent";
|
||||
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Create the weather agent with function tools.
|
||||
var weatherTool = AIFunctionFactory.Create(GetWeather);
|
||||
AIAgent weatherAgent = agentsClient.CreateAIAgent(
|
||||
name: WeatherName,
|
||||
model: deploymentName,
|
||||
instructions: WeatherInstructions,
|
||||
tools: [weatherTool]);
|
||||
|
||||
// Create the main agent, and provide the weather agent as a function tool.
|
||||
AIAgent agent = agentsClient.CreateAIAgent(
|
||||
name: MainName,
|
||||
model: deploymentName,
|
||||
instructions: MainInstructions,
|
||||
tools: [weatherAgent.AsAIFunction()]);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", thread));
|
||||
|
||||
// Cleanup by agent name removes the agent versions created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
agentsClient.DeleteAgent(weatherAgent.Name);
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows multiple middleware layers working together with Azure Foundry Agents:
|
||||
// agent run (PII filtering and guardrails),
|
||||
// function invocation (logging and result overrides), and human-in-the-loop
|
||||
// approval workflows for sensitive function calls.
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Text.RegularExpressions;
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
// Get Azure AI Foundry configuration from environment variables
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = System.Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o";
|
||||
|
||||
const string AssistantInstructions = "You are an AI assistant that helps people find information.";
|
||||
const string AssistantName = "InformationAssistant";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
[Description("Get the weather for a given location.")]
|
||||
static string GetWeather([Description("The location to get the weather for.")] string location)
|
||||
=> $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
|
||||
[Description("The current datetime offset.")]
|
||||
static string GetDateTime()
|
||||
=> DateTimeOffset.Now.ToString();
|
||||
|
||||
var dateTimeTool = AIFunctionFactory.Create(GetDateTime, name: nameof(GetDateTime));
|
||||
var getWeatherTool = AIFunctionFactory.Create(GetWeather, name: nameof(GetWeather));
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
AIAgent originalAgent = agentsClient.CreateAIAgent(
|
||||
name: AssistantName,
|
||||
model: deploymentName,
|
||||
instructions: AssistantInstructions,
|
||||
tools: [getWeatherTool, dateTimeTool]);
|
||||
|
||||
// Adding middleware to the agent level
|
||||
var middlewareEnabledAgent = originalAgent
|
||||
.AsBuilder()
|
||||
.Use(FunctionCallMiddleware)
|
||||
.Use(FunctionCallOverrideWeather)
|
||||
.Use(PIIMiddleware, null)
|
||||
.Use(GuardrailMiddleware, null)
|
||||
.Build();
|
||||
|
||||
var thread = middlewareEnabledAgent.GetNewThread();
|
||||
|
||||
Console.WriteLine("\n\n=== Example 1: Wording Guardrail ===");
|
||||
var guardRailedResponse = await middlewareEnabledAgent.RunAsync("Tell me something harmful.");
|
||||
Console.WriteLine($"Guard railed response: {guardRailedResponse}");
|
||||
|
||||
Console.WriteLine("\n\n=== Example 2: PII detection ===");
|
||||
var piiResponse = await middlewareEnabledAgent.RunAsync("My name is John Doe, call me at 123-456-7890 or email me at john@something.com");
|
||||
Console.WriteLine($"Pii filtered response: {piiResponse}");
|
||||
|
||||
Console.WriteLine("\n\n=== Example 3: Agent function middleware ===");
|
||||
|
||||
// Agent function middleware support is limited to agents that wraps a upstream ChatClientAgent or derived from it.
|
||||
|
||||
var functionCallResponse = await middlewareEnabledAgent.RunAsync("What's the current time and the weather in Seattle?", thread);
|
||||
Console.WriteLine($"Function calling response: {functionCallResponse}");
|
||||
|
||||
// Special per-request middleware agent.
|
||||
Console.WriteLine("\n\n=== Example 4: Middleware with human in the loop function approval ===");
|
||||
|
||||
AIAgent humamInTheLoopAgent = agentsClient.CreateAIAgent(
|
||||
name: "HumanInTheLoopAgent",
|
||||
model: deploymentName,
|
||||
instructions: "You are an Human in the loop testing AI assistant that helps people find information.",
|
||||
|
||||
// Adding a function with approval required
|
||||
tools: [new ApprovalRequiredAIFunction(AIFunctionFactory.Create(GetWeather, name: nameof(GetWeather)))]);
|
||||
|
||||
// Using the ConsolePromptingApprovalMiddleware for a specific request to handle user approval during function calls.
|
||||
var response = await humamInTheLoopAgent
|
||||
.AsBuilder()
|
||||
.Use(ConsolePromptingApprovalMiddleware, null)
|
||||
.Build()
|
||||
.RunAsync("What's the current time and the weather in Seattle?");
|
||||
|
||||
Console.WriteLine($"HumamInTheLoopAgent agent middleware response: {response}");
|
||||
|
||||
// Function invocation middleware that logs before and after function calls.
|
||||
async ValueTask<object?> FunctionCallMiddleware(AIAgent agent, FunctionInvocationContext context, Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next, CancellationToken cancellationToken)
|
||||
{
|
||||
Console.WriteLine($"Function Name: {context!.Function.Name} - Middleware 1 Pre-Invoke");
|
||||
var result = await next(context, cancellationToken);
|
||||
Console.WriteLine($"Function Name: {context!.Function.Name} - Middleware 1 Post-Invoke");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Function invocation middleware that overrides the result of the GetWeather function.
|
||||
async ValueTask<object?> FunctionCallOverrideWeather(AIAgent agent, FunctionInvocationContext context, Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next, CancellationToken cancellationToken)
|
||||
{
|
||||
Console.WriteLine($"Function Name: {context!.Function.Name} - Middleware 2 Pre-Invoke");
|
||||
|
||||
var result = await next(context, cancellationToken);
|
||||
|
||||
if (context.Function.Name == nameof(GetWeather))
|
||||
{
|
||||
// Override the result of the GetWeather function
|
||||
result = "The weather is sunny with a high of 25°C.";
|
||||
}
|
||||
Console.WriteLine($"Function Name: {context!.Function.Name} - Middleware 2 Post-Invoke");
|
||||
return result;
|
||||
}
|
||||
|
||||
// This middleware redacts PII information from input and output messages.
|
||||
async Task<AgentRunResponse> PIIMiddleware(IEnumerable<ChatMessage> messages, AgentThread? thread, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken)
|
||||
{
|
||||
// Redact PII information from input messages
|
||||
var filteredMessages = FilterMessages(messages);
|
||||
Console.WriteLine("Pii Middleware - Filtered Messages Pre-Run");
|
||||
|
||||
var response = await innerAgent.RunAsync(filteredMessages, thread, options, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Redact PII information from output messages
|
||||
response.Messages = FilterMessages(response.Messages);
|
||||
|
||||
Console.WriteLine("Pii Middleware - Filtered Messages Post-Run");
|
||||
|
||||
return response;
|
||||
|
||||
static IList<ChatMessage> FilterMessages(IEnumerable<ChatMessage> messages)
|
||||
{
|
||||
return messages.Select(m => new ChatMessage(m.Role, FilterPii(m.Text))).ToList();
|
||||
}
|
||||
|
||||
static string FilterPii(string content)
|
||||
{
|
||||
// Regex patterns for PII detection (simplified for demonstration)
|
||||
Regex[] piiPatterns = [
|
||||
new(@"\b\d{3}-\d{3}-\d{4}\b", RegexOptions.Compiled), // Phone number (e.g., 123-456-7890)
|
||||
new(@"\b[\w\.-]+@[\w\.-]+\.\w+\b", RegexOptions.Compiled), // Email address
|
||||
new(@"\b[A-Z][a-z]+\s[A-Z][a-z]+\b", RegexOptions.Compiled) // Full name (e.g., John Doe)
|
||||
];
|
||||
|
||||
foreach (var pattern in piiPatterns)
|
||||
{
|
||||
content = pattern.Replace(content, "[REDACTED: PII]");
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
// This middleware enforces guardrails by redacting certain keywords from input and output messages.
|
||||
async Task<AgentRunResponse> GuardrailMiddleware(IEnumerable<ChatMessage> messages, AgentThread? thread, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken)
|
||||
{
|
||||
// Redact keywords from input messages
|
||||
var filteredMessages = FilterMessages(messages);
|
||||
|
||||
Console.WriteLine("Guardrail Middleware - Filtered messages Pre-Run");
|
||||
|
||||
// Proceed with the agent run
|
||||
var response = await innerAgent.RunAsync(filteredMessages, thread, options, cancellationToken);
|
||||
|
||||
// Redact keywords from output messages
|
||||
response.Messages = FilterMessages(response.Messages);
|
||||
|
||||
Console.WriteLine("Guardrail Middleware - Filtered messages Post-Run");
|
||||
|
||||
return response;
|
||||
|
||||
List<ChatMessage> FilterMessages(IEnumerable<ChatMessage> messages)
|
||||
{
|
||||
return messages.Select(m => new ChatMessage(m.Role, FilterContent(m.Text))).ToList();
|
||||
}
|
||||
|
||||
static string FilterContent(string content)
|
||||
{
|
||||
foreach (var keyword in new[] { "harmful", "illegal", "violence" })
|
||||
{
|
||||
if (content.Contains(keyword, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return "[REDACTED: Forbidden content]";
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
// This middleware handles Human in the loop console interaction for any user approval required during function calling.
|
||||
async Task<AgentRunResponse> ConsolePromptingApprovalMiddleware(IEnumerable<ChatMessage> messages, AgentThread? thread, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken)
|
||||
{
|
||||
var response = await innerAgent.RunAsync(messages, thread, options, cancellationToken);
|
||||
|
||||
var userInputRequests = response.UserInputRequests.ToList();
|
||||
|
||||
while (userInputRequests.Count > 0)
|
||||
{
|
||||
// Ask the user to approve each function call request.
|
||||
// For simplicity, we are assuming here that only function approval requests are being made.
|
||||
|
||||
// Pass the user input responses back to the agent for further processing.
|
||||
response.Messages = userInputRequests
|
||||
.OfType<FunctionApprovalRequestContent>()
|
||||
.Select(functionApprovalRequest =>
|
||||
{
|
||||
Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {functionApprovalRequest.FunctionCall.Name}");
|
||||
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(Console.ReadLine()?.Equals("Y", StringComparison.OrdinalIgnoreCase) ?? false)]);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
response = await innerAgent.RunAsync(response.Messages, thread, options, cancellationToken);
|
||||
|
||||
userInputRequests = response.UserInputRequests.ToList();
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(middlewareEnabledAgent.Name);
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
# Agent Middleware
|
||||
|
||||
This sample demonstrates how to add middleware to intercept:
|
||||
- Chat client calls (global and per‑request)
|
||||
- Agent runs (guardrails and PII filtering)
|
||||
- Function calling (logging/override)
|
||||
|
||||
## What This Sample Shows
|
||||
|
||||
1. Azure OpenAI integration via `AzureOpenAIClient` and `AzureCliCredential`
|
||||
2. Chat client middleware using `ChatClientBuilder.Use(...)`
|
||||
3. Agent run middleware (PII redaction and wording guardrails)
|
||||
4. Function invocation middleware (logging and overriding a tool result)
|
||||
5. Per‑request chat client middleware
|
||||
6. Per‑request function pipeline with approval
|
||||
7. Combining agent‑level and per‑request middleware
|
||||
|
||||
## Function Invocation Middleware
|
||||
|
||||
Not all agents support function invocation middleware.
|
||||
|
||||
Attempting to use function middleware on agents that do not wrap a ChatClientAgent or derives from it will throw an InvalidOperationException.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. Environment variables:
|
||||
- `AZURE_OPENAI_ENDPOINT`: Your Azure OpenAI endpoint
|
||||
- `AZURE_OPENAI_DEPLOYMENT_NAME`: Chat deployment name (optional; defaults to `gpt-4o`)
|
||||
2. Sign in with Azure CLI (PowerShell):
|
||||
```powershell
|
||||
az login
|
||||
```
|
||||
|
||||
## Running the Sample
|
||||
|
||||
Use PowerShell:
|
||||
```powershell
|
||||
cd dotnet/samples/GettingStarted/Agents/Agent_Step14_Middleware
|
||||
dotnet run
|
||||
```
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<NoWarn>$(NoWarn);CA1812</NoWarn>
|
||||
<RootNamespace>Agent_Step15_Plugins</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Azure.AI.Agents" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use plugins with an AI agent. Plugin classes can
|
||||
// depend on other services that need to be injected. In this sample, the
|
||||
// AgentPlugin class uses the WeatherProvider and CurrentTimeProvider classes
|
||||
// to get weather and current time information. Both services are registered
|
||||
// in the service collection and injected into the plugin.
|
||||
// Plugin classes may have many methods, but only some are intended to be used
|
||||
// as AI functions. The AsAITools method of the plugin class shows how to specify
|
||||
// which methods should be exposed to the AI agent.
|
||||
|
||||
using Azure.AI.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string AssistantInstructions = "You are a helpful assistant that helps people find information.";
|
||||
const string AssistantName = "PluginAssistant";
|
||||
|
||||
// Create a service collection to hold the agent plugin and its dependencies.
|
||||
ServiceCollection services = new();
|
||||
services.AddSingleton<WeatherProvider>();
|
||||
services.AddSingleton<CurrentTimeProvider>();
|
||||
services.AddSingleton<AgentPlugin>(); // The plugin depends on WeatherProvider and CurrentTimeProvider registered above.
|
||||
|
||||
IServiceProvider serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
var agentsClient = new AgentsClient(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Define the agent with plugin tools
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
AIAgent agent = agentsClient.CreateAIAgent(
|
||||
name: AssistantName,
|
||||
model: deploymentName,
|
||||
instructions: AssistantInstructions,
|
||||
tools: serviceProvider.GetRequiredService<AgentPlugin>().AsAITools().ToList(),
|
||||
services: serviceProvider);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
AgentThread thread = agent.GetNewThread();
|
||||
Console.WriteLine(await agent.RunAsync("Tell me current time and weather in Seattle.", thread));
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
agentsClient.DeleteAgent(agent.Name);
|
||||
|
||||
/// <summary>
|
||||
/// The agent plugin that provides weather and current time information.
|
||||
/// </summary>
|
||||
/// <param name="weatherProvider">The weather provider to get weather information.</param>
|
||||
internal sealed class AgentPlugin(WeatherProvider weatherProvider)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the weather information for the specified location.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method demonstrates how to use the dependency that was injected into the plugin class.
|
||||
/// </remarks>
|
||||
/// <param name="location">The location to get the weather for.</param>
|
||||
/// <returns>The weather information for the specified location.</returns>
|
||||
public string GetWeather(string location)
|
||||
{
|
||||
return weatherProvider.GetWeather(location);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current date and time for the specified location.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method demonstrates how to resolve a dependency using the service provider passed to the method.
|
||||
/// </remarks>
|
||||
/// <param name="sp">The service provider to resolve the <see cref="CurrentTimeProvider"/>.</param>
|
||||
/// <param name="location">The location to get the current time for.</param>
|
||||
/// <returns>The current date and time as a <see cref="DateTimeOffset"/>.</returns>
|
||||
public DateTimeOffset GetCurrentTime(IServiceProvider sp, string location)
|
||||
{
|
||||
// Resolve the CurrentTimeProvider from the service provider
|
||||
var currentTimeProvider = sp.GetRequiredService<CurrentTimeProvider>();
|
||||
|
||||
return currentTimeProvider.GetCurrentTime(location);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the functions provided by this plugin.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// In real world scenarios, a class may have many methods and only a subset of them may be intended to be exposed as AI functions.
|
||||
/// This method demonstrates how to explicitly specify which methods should be exposed to the AI agent.
|
||||
/// </remarks>
|
||||
/// <returns>The functions provided by this plugin.</returns>
|
||||
public IEnumerable<AITool> AsAITools()
|
||||
{
|
||||
yield return AIFunctionFactory.Create(this.GetWeather);
|
||||
yield return AIFunctionFactory.Create(this.GetCurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The weather provider that returns weather information.
|
||||
/// </summary>
|
||||
internal sealed class WeatherProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the weather information for the specified location.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The weather information is hardcoded for demonstration purposes.
|
||||
/// In a real application, this could call a weather API to get actual weather data.
|
||||
/// </remarks>
|
||||
/// <param name="location">The location to get the weather for.</param>
|
||||
/// <returns>The weather information for the specified location.</returns>
|
||||
public string GetWeather(string location)
|
||||
{
|
||||
return $"The weather in {location} is cloudy with a high of 15°C.";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides the current date and time.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class returns the current date and time using the system's clock.
|
||||
/// </remarks>
|
||||
internal sealed class CurrentTimeProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the current date and time.
|
||||
/// </summary>
|
||||
/// <param name="location">The location to get the current time for (not used in this implementation).</param>
|
||||
/// <returns>The current date and time as a <see cref="DateTimeOffset"/>.</returns>
|
||||
public DateTimeOffset GetCurrentTime(string location)
|
||||
{
|
||||
return DateTimeOffset.Now;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="tools">The tools to use when interacting with the agent. This is required when using prompt agent definitions with tools.</param>
|
||||
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations based on the latest version of the named Azure AI Agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="name"/> is <see langword="null"/>.</exception>
|
||||
@@ -37,6 +38,7 @@ public static class AgentsClientExtensions
|
||||
IList<AITool>? tools = null,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -51,6 +53,7 @@ public static class AgentsClientExtensions
|
||||
tools,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
services,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -62,6 +65,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="tools">The tools to use when interacting with the agent. This is required when using prompt agent definitions with tools.</param>
|
||||
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations based on the latest version of the named Azure AI Agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="name"/> is <see langword="null"/>.</exception>
|
||||
@@ -74,6 +78,7 @@ public static class AgentsClientExtensions
|
||||
IList<AITool>? tools = null,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -88,6 +93,7 @@ public static class AgentsClientExtensions
|
||||
tools,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
services,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -99,6 +105,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="tools">The tools to use when interacting with the agent. This is required when using prompt agent definitions with tools.</param>
|
||||
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations based on the latest version of the Azure AI Agent.</returns>
|
||||
/// <remarks>When using prompt agent definitions with tools the parameter <paramref name="tools"/> needs to be provided.</remarks>
|
||||
@@ -108,6 +115,7 @@ public static class AgentsClientExtensions
|
||||
IList<AITool>? tools = null,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -119,7 +127,7 @@ public static class AgentsClientExtensions
|
||||
tools,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools: true,
|
||||
services,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -131,10 +139,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="tools">The tools to use when interacting with the agent. This is required when using prompt agent definitions with tools.</param>
|
||||
/// <param name="clientFactory">Provides a way to customize the creation of the underlying <see cref="IChatClient"/> used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="requireInvocableTools">
|
||||
/// This defaults to <see langword="true" /> and indicates whether to enforce the presence of invocable tools when the AIAgent is created with an agent definition that uses them.
|
||||
/// Setting this to <see langword="false" /> will require manual handling of in-proc tool invocations by the caller.
|
||||
/// </param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations based on the provided version of the Azure AI Agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="agentVersion"/> is <see langword="null"/>.</exception>
|
||||
@@ -145,7 +150,7 @@ public static class AgentsClientExtensions
|
||||
IList<AITool>? tools = null,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
bool requireInvocableTools = true,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -159,7 +164,8 @@ public static class AgentsClientExtensions
|
||||
tools,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools);
|
||||
requireInvocableTools: true,
|
||||
services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -169,6 +175,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="options">The options for creating the agent. Cannot be <see langword="null"/>.</param>
|
||||
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the operation if needed.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
|
||||
@@ -177,6 +184,7 @@ public static class AgentsClientExtensions
|
||||
ChatClientAgentOptions options,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -200,7 +208,8 @@ public static class AgentsClientExtensions
|
||||
agentOptions,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools: true);
|
||||
requireInvocableTools: true,
|
||||
services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -210,6 +219,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="options">The options for creating the agent. Cannot be <see langword="null"/>.</param>
|
||||
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the operation if needed.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
|
||||
@@ -218,6 +228,7 @@ public static class AgentsClientExtensions
|
||||
ChatClientAgentOptions options,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -241,7 +252,8 @@ public static class AgentsClientExtensions
|
||||
agentOptions,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools: true);
|
||||
requireInvocableTools: true,
|
||||
services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -255,6 +267,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="creationOptions">Settings that control the creation of the agent.</param>
|
||||
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/>, <paramref name="model"/>, or <paramref name="instructions"/> is <see langword="null"/>.</exception>
|
||||
@@ -269,6 +282,7 @@ public static class AgentsClientExtensions
|
||||
AgentVersionCreationOptions? creationOptions = null,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -285,6 +299,7 @@ public static class AgentsClientExtensions
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools: true,
|
||||
services,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -299,6 +314,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="creationOptions">Settings that control the creation of the agent.</param>
|
||||
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/>, <paramref name="model"/>, or <paramref name="instructions"/> is <see langword="null"/>.</exception>
|
||||
@@ -313,6 +329,7 @@ public static class AgentsClientExtensions
|
||||
AgentVersionCreationOptions? creationOptions = null,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -329,6 +346,7 @@ public static class AgentsClientExtensions
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools: true,
|
||||
services,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -340,6 +358,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="options">The options for creating the agent. Cannot be <see langword="null"/>.</param>
|
||||
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the operation if needed.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
|
||||
@@ -350,6 +369,7 @@ public static class AgentsClientExtensions
|
||||
ChatClientAgentOptions options,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -385,7 +405,8 @@ public static class AgentsClientExtensions
|
||||
agentOptions,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
RequireInvocableTools);
|
||||
RequireInvocableTools,
|
||||
services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -396,6 +417,7 @@ public static class AgentsClientExtensions
|
||||
/// <param name="options">The options for creating the agent. Cannot be <see langword="null"/>.</param>
|
||||
/// <param name="clientFactory">A factory function to customize the creation of the chat client used by the agent.</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <param name="services">An optional <see cref="IServiceProvider"/> to use for resolving services required by the <see cref="AIFunction"/> instances being invoked.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> to cancel the operation if needed.</param>
|
||||
/// <returns>A <see cref="ChatClientAgent"/> instance that can be used to perform operations on the newly created agent.</returns>
|
||||
/// <exception cref="ArgumentNullException">Thrown when <paramref name="agentsClient"/> or <paramref name="options"/> is <see langword="null"/>.</exception>
|
||||
@@ -406,6 +428,7 @@ public static class AgentsClientExtensions
|
||||
ChatClientAgentOptions options,
|
||||
Func<IChatClient, IChatClient>? clientFactory = null,
|
||||
OpenAIClientOptions? openAIClientOptions = null,
|
||||
IServiceProvider? services = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -441,7 +464,8 @@ public static class AgentsClientExtensions
|
||||
agentOptions,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
RequireInvocableTools);
|
||||
RequireInvocableTools,
|
||||
services);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -484,6 +508,7 @@ public static class AgentsClientExtensions
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools: false,
|
||||
services: null,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -528,6 +553,7 @@ public static class AgentsClientExtensions
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools: false,
|
||||
services: null,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
@@ -542,6 +568,7 @@ public static class AgentsClientExtensions
|
||||
Func<IChatClient, IChatClient>? clientFactory,
|
||||
OpenAIClientOptions? openAIClientOptions,
|
||||
bool requireInvocableTools,
|
||||
IServiceProvider? services,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Throw.IfNull(agentsClient);
|
||||
@@ -560,7 +587,8 @@ public static class AgentsClientExtensions
|
||||
tools,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools);
|
||||
requireInvocableTools,
|
||||
services);
|
||||
}
|
||||
|
||||
private static async Task<ChatClientAgent> CreateAIAgentAsync(
|
||||
@@ -572,6 +600,7 @@ public static class AgentsClientExtensions
|
||||
Func<IChatClient, IChatClient>? clientFactory,
|
||||
OpenAIClientOptions? openAIClientOptions,
|
||||
bool requireInvocableTools,
|
||||
IServiceProvider? services,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
Throw.IfNullOrWhitespace(name);
|
||||
@@ -590,7 +619,8 @@ public static class AgentsClientExtensions
|
||||
tools,
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools);
|
||||
requireInvocableTools,
|
||||
services);
|
||||
}
|
||||
|
||||
/// <summary>This method creates an <see cref="ChatClientAgent"/> with the specified ChatClientAgentOptions.</summary>
|
||||
@@ -600,16 +630,17 @@ public static class AgentsClientExtensions
|
||||
ChatClientAgentOptions agentOptions,
|
||||
Func<IChatClient, IChatClient>? clientFactory,
|
||||
OpenAIClientOptions? openAIClientOptions,
|
||||
bool requireInvocableTools)
|
||||
bool requireInvocableTools,
|
||||
IServiceProvider? services)
|
||||
{
|
||||
IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentVersion, openAIClientOptions);
|
||||
IChatClient chatClient = new AzureAIAgentChatClient(agentsClient, agentVersion, agentOptions.ChatOptions, openAIClientOptions);
|
||||
|
||||
if (clientFactory is not null)
|
||||
{
|
||||
chatClient = clientFactory(chatClient);
|
||||
}
|
||||
|
||||
return new ChatClientAgent(chatClient, agentOptions);
|
||||
return new ChatClientAgent(chatClient, agentOptions, services: services);
|
||||
}
|
||||
|
||||
/// <summary>This method creates an <see cref="ChatClientAgent"/> with a auto-generated ChatClientAgentOptions from the specified configuration parameters.</summary>
|
||||
@@ -619,20 +650,22 @@ public static class AgentsClientExtensions
|
||||
IList<AITool>? tools,
|
||||
Func<IChatClient, IChatClient>? clientFactory,
|
||||
OpenAIClientOptions? openAIClientOptions,
|
||||
bool requireInvocableTools)
|
||||
bool requireInvocableTools,
|
||||
IServiceProvider? services)
|
||||
=> CreateChatClientAgent(
|
||||
agentsClient,
|
||||
agentVersion,
|
||||
CreateChatClientAgentOptions(agentVersion, tools, requireInvocableTools),
|
||||
CreateChatClientAgentOptions(agentVersion, new ChatOptions() { Tools = tools }, requireInvocableTools),
|
||||
clientFactory,
|
||||
openAIClientOptions,
|
||||
requireInvocableTools);
|
||||
requireInvocableTools,
|
||||
services);
|
||||
|
||||
/// <summary>
|
||||
/// This method creates <see cref="ChatClientAgentOptions"/> for the specified <see cref="AgentVersion"/> and the provided tools.
|
||||
/// </summary>
|
||||
/// <param name="agentVersion">The agent version.</param>
|
||||
/// <param name="tools">The tools to use when interacting with the agent.</param>
|
||||
/// <param name="chatOptions">The <see cref="ChatOptions"/> to use when interacting with the agent.</param>
|
||||
/// <param name="requireInvocableTools">Indicates whether to enforce the presence of invocable tools when the AIAgent is created with an agent definition that uses them.</param>
|
||||
/// <returns>The created <see cref="ChatClientAgentOptions"/>.</returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown when the agent definition requires in-process tools but none were provided.</exception>
|
||||
@@ -641,7 +674,7 @@ public static class AgentsClientExtensions
|
||||
/// This method rebuilds the agent options from the agent definition returned by the version and combine with the in-proc tools when provided
|
||||
/// this ensures that all required tools are provided and the definition of the agent options are consistent with the agent definition coming from the server.
|
||||
/// </remarks>
|
||||
private static ChatClientAgentOptions CreateChatClientAgentOptions(AgentVersion agentVersion, IList<AITool>? tools, bool requireInvocableTools)
|
||||
private static ChatClientAgentOptions CreateChatClientAgentOptions(AgentVersion agentVersion, ChatOptions? chatOptions, bool requireInvocableTools)
|
||||
{
|
||||
var agentDefinition = agentVersion.Definition;
|
||||
|
||||
@@ -649,7 +682,7 @@ public static class AgentsClientExtensions
|
||||
if (agentDefinition is PromptAgentDefinition { Tools: { Count: > 0 } definitionTools })
|
||||
{
|
||||
// Check if no tools were provided while the agent definition requires in-proc tools.
|
||||
if (requireInvocableTools && tools is null or { Count: 0 } && definitionTools.Any(t => t is FunctionTool))
|
||||
if (requireInvocableTools && chatOptions?.Tools is null or { Count: 0 } && definitionTools.Any(t => t is FunctionTool))
|
||||
{
|
||||
throw new ArgumentException("The agent definition in-process tools must be provided in the extension method tools parameter.");
|
||||
}
|
||||
@@ -663,7 +696,7 @@ public static class AgentsClientExtensions
|
||||
if (responseTool is FunctionTool functionTool)
|
||||
{
|
||||
// Check if a tool with the same type and name exists in the provided tools.
|
||||
var matchingTool = tools?.FirstOrDefault(t =>
|
||||
var matchingTool = chatOptions?.Tools?.FirstOrDefault(t =>
|
||||
requireInvocableTools
|
||||
? t is AIFunction tf && functionTool.FunctionName == tf.Name // When invocable tools are required, match only AIFunction.
|
||||
: (t is AIFunctionDeclaration tfd && functionTool.FunctionName == tfd.Name) ? true // When not required, match AIFunctionDeclaration OR
|
||||
@@ -698,18 +731,16 @@ public static class AgentsClientExtensions
|
||||
|
||||
if (agentDefinition is PromptAgentDefinition promptAgentDefinition)
|
||||
{
|
||||
agentOptions.ChatOptions ??= chatOptions?.Clone() ?? new();
|
||||
agentOptions.Instructions = promptAgentDefinition.Instructions;
|
||||
agentOptions.ChatOptions = new()
|
||||
{
|
||||
Temperature = promptAgentDefinition.Temperature,
|
||||
TopP = promptAgentDefinition.TopP,
|
||||
Instructions = promptAgentDefinition.Instructions,
|
||||
};
|
||||
agentOptions.ChatOptions.Temperature = promptAgentDefinition.Temperature;
|
||||
agentOptions.ChatOptions.TopP = promptAgentDefinition.TopP;
|
||||
agentOptions.ChatOptions.Instructions = promptAgentDefinition.Instructions;
|
||||
}
|
||||
|
||||
if (agentTools is { Count: > 0 })
|
||||
{
|
||||
agentOptions.ChatOptions ??= new ChatOptions();
|
||||
agentOptions.ChatOptions ??= chatOptions?.Clone() ?? new();
|
||||
agentOptions.ChatOptions.Tools = agentTools;
|
||||
}
|
||||
|
||||
@@ -728,7 +759,7 @@ public static class AgentsClientExtensions
|
||||
/// <returns>A <see cref="ChatClientAgentOptions"/> instance configured according to the specified parameters.</returns>
|
||||
private static ChatClientAgentOptions CreateChatClientAgentOptions(AgentVersion agentVersion, ChatClientAgentOptions? options, bool requireInvocableTools)
|
||||
{
|
||||
var agentOptions = CreateChatClientAgentOptions(agentVersion, options?.ChatOptions?.Tools, requireInvocableTools);
|
||||
var agentOptions = CreateChatClientAgentOptions(agentVersion, options?.ChatOptions, requireInvocableTools);
|
||||
if (options is not null)
|
||||
{
|
||||
agentOptions.AIContextProviderFactory = options.AIContextProviderFactory;
|
||||
|
||||
@@ -22,6 +22,7 @@ internal sealed class AzureAIAgentChatClient : DelegatingChatClient
|
||||
private readonly ChatClientMetadata? _metadata;
|
||||
private readonly AgentsClient _agentsClient;
|
||||
private readonly AgentVersion _agentVersion;
|
||||
private readonly ChatOptions? _chatOptions;
|
||||
|
||||
/// <summary>
|
||||
/// The usage of a no-op model is a necessary change to avoid OpenAIClients to throw exceptions when
|
||||
@@ -34,16 +35,17 @@ internal sealed class AzureAIAgentChatClient : DelegatingChatClient
|
||||
/// </summary>
|
||||
/// <param name="agentsClient">An instance of <see cref="AgentsClient"/> to interact with Azure AI Agents services.</param>
|
||||
/// <param name="agentRecord">An instance of <see cref="AgentRecord"/> representing the specific agent to use.</param>
|
||||
/// <param name="chatOptions">An instance of <see cref="ChatOptions"/> representing the options on how the agent was predefined</param>
|
||||
/// <param name="openAIClientOptions">An optional <see cref="OpenAIClientOptions"/> for configuring the underlying OpenAI client.</param>
|
||||
/// <remarks>
|
||||
/// The <see cref="IChatClient"/> provided should be decorated with a <see cref="AzureAIAgentChatClient"/> for proper functionality.
|
||||
/// </remarks>
|
||||
internal AzureAIAgentChatClient(AgentsClient agentsClient, AgentRecord agentRecord, OpenAIClientOptions? openAIClientOptions = null)
|
||||
: this(agentsClient, Throw.IfNull(agentRecord).Versions.Latest, openAIClientOptions)
|
||||
internal AzureAIAgentChatClient(AgentsClient agentsClient, AgentRecord agentRecord, ChatOptions? chatOptions, OpenAIClientOptions? openAIClientOptions = null)
|
||||
: this(agentsClient, Throw.IfNull(agentRecord).Versions.Latest, chatOptions, openAIClientOptions)
|
||||
{
|
||||
}
|
||||
|
||||
internal AzureAIAgentChatClient(AgentsClient agentsClient, AgentVersion agentVersion, OpenAIClientOptions? openAIClientOptions = null)
|
||||
internal AzureAIAgentChatClient(AgentsClient agentsClient, AgentVersion agentVersion, ChatOptions? chatOptions, OpenAIClientOptions? openAIClientOptions = null)
|
||||
: base(agentsClient
|
||||
.GetOpenAIClient(openAIClientOptions)
|
||||
.GetOpenAIResponseClient((agentVersion.Definition as PromptAgentDefinition)?.Model ?? NoOpModel)
|
||||
@@ -52,6 +54,7 @@ internal sealed class AzureAIAgentChatClient : DelegatingChatClient
|
||||
this._agentsClient = Throw.IfNull(agentsClient);
|
||||
this._agentVersion = Throw.IfNull(agentVersion);
|
||||
this._metadata = new ChatClientMetadata("azure.ai.agents");
|
||||
this._chatOptions = chatOptions;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -94,8 +97,12 @@ internal sealed class AzureAIAgentChatClient : DelegatingChatClient
|
||||
|
||||
private ChatOptions GetConversationEnabledChatOptions(ChatOptions? chatOptions, string conversationId)
|
||||
{
|
||||
// Ignore all the chatOptions provided as agents options can't be set per-request basis.
|
||||
var conversationChatOptions = new ChatOptions();
|
||||
// Start with a clone of the base chat options defined for the agent, if any.
|
||||
ChatOptions conversationChatOptions = this._chatOptions?.Clone() ?? new();
|
||||
|
||||
// Ignore per-request all options that can't be overriden.
|
||||
conversationChatOptions.Instructions = null;
|
||||
conversationChatOptions.Tools = null;
|
||||
|
||||
// Preserve the original RawRepresentationFactory
|
||||
var originalFactory = chatOptions?.RawRepresentationFactory;
|
||||
|
||||
@@ -191,25 +191,7 @@ public sealed class AgentsClientExtensionsTests
|
||||
};
|
||||
|
||||
// Act
|
||||
var agent = client.GetAIAgent(agentVersion, tools: tools, requireInvocableTools: true);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
Assert.IsType<ChatClientAgent>(agent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that GetAIAgent with requireInvocableTools=false allows declarative functions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void GetAIAgent_WithAgentVersion_WithRequireInvocableToolsFalse_AllowsDeclarativeFunctions()
|
||||
{
|
||||
// Arrange
|
||||
AgentsClient client = this.CreateTestAgentsClient();
|
||||
AgentVersion agentVersion = this.CreateTestAgentVersion();
|
||||
|
||||
// Act - should not throw even without tools when requireInvocableTools is false
|
||||
var agent = client.GetAIAgent(agentVersion, requireInvocableTools: false);
|
||||
var agent = client.GetAIAgent(agentVersion, tools: tools);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(agent);
|
||||
|
||||
Reference in New Issue
Block a user