Merge branch 'main' into dependabot/nuget/dotnet/AWSSDK.Extensions.Bedrock.MEAI-4.0.6.4
@@ -0,0 +1,125 @@
|
||||
---
|
||||
status: accepted
|
||||
contact: rogerbarreto
|
||||
date: 2026-03-06
|
||||
deciders: rogerbarreto, alliscode
|
||||
consulted: ""
|
||||
informed: ""
|
||||
---
|
||||
|
||||
# Foundry agent surface stays centered on `ChatClientAgent`
|
||||
|
||||
## Context
|
||||
|
||||
The Microsoft Foundry integration exposes two distinct usage patterns:
|
||||
|
||||
1. Direct Responses usage, where callers provide model, instructions, and tools at runtime.
|
||||
2. Server-side versioned agents, where callers create and manage `AgentVersion` resources through `AIProjectClient.Agents`.
|
||||
|
||||
We briefly explored adding public wrapper types such as `FoundryAgent`, `FoundryVersionedAgent`, and `FoundryResponsesChatClient` to make those paths feel more specialized. That direction created extra public types, duplicated existing `ChatClientAgent` behavior, and pushed samples toward compatibility helpers instead of the native Azure SDK flow.
|
||||
|
||||
## Decision
|
||||
|
||||
Keep the public surface centered on `ChatClientAgent`.
|
||||
|
||||
- Direct Responses scenarios use `AIProjectClient.AsAIAgent(...)`.
|
||||
- Server-side versioned scenarios use native `AIProjectClient.Agents` APIs to create or retrieve agent resources, then wrap `AgentRecord` or `AgentVersion` with `AIProjectClient.AsAIAgent(...)`.
|
||||
- Compatibility helpers such as `AIProjectClient.CreateAIAgentAsync(...)` and `AIProjectClient.GetAIAgentAsync(...)` remain only as obsolete migration shims.
|
||||
- Public wrapper types `FoundryAgent`, `FoundryVersionedAgent`, `FoundryResponsesChatClient`, and `FoundryResponsesChatClientAgent` are not part of the chosen direction.
|
||||
|
||||
## Why
|
||||
|
||||
- `ChatClientAgent` is already the framework abstraction used everywhere else.
|
||||
- `AIProjectClient` is the native Azure SDK entry point for versioned agent lifecycle operations.
|
||||
- A single agent abstraction avoids parallel type hierarchies for the same backend.
|
||||
- Samples become clearer when they show either:
|
||||
- direct Responses construction via `AIProjectClient.AsAIAgent(...)`, or
|
||||
- native Foundry resource management via `AIProjectClient.Agents`.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Direct Responses path
|
||||
|
||||
Use the convenience overloads on `AIProjectClient`:
|
||||
|
||||
```csharp
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), credential);
|
||||
|
||||
ChatClientAgent agent = aiProjectClient.AsAIAgent(
|
||||
model: deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "JokerAgent");
|
||||
```
|
||||
|
||||
Or use composed `ChatClientAgent`
|
||||
|
||||
```csharp
|
||||
ProjectResponsesClient projectResponsesClient = new(new Uri(endpoint), new DefaultAzureCredential(), new AgentReference($"model:{deploymentName}"));
|
||||
|
||||
ChatClientAgent agent = new(
|
||||
chatClient: projectResponsesClient.AsIChatClient(),
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "JokerAgent");
|
||||
```
|
||||
|
||||
This path is code-first and does not create a persistent server-side agent.
|
||||
|
||||
### Versioned agent path
|
||||
|
||||
Use the convenience overloads on `AIProjectClient`:
|
||||
|
||||
```csharp
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), credential);
|
||||
|
||||
AgentVersion version = await aiProjectClient.Agents.CreateAgentVersionAsync(
|
||||
"JokerAgent",
|
||||
new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(deploymentName)
|
||||
{
|
||||
Instructions = "You are good at telling jokes."
|
||||
}));
|
||||
|
||||
ChatClientAgent agent = aiProjectClient.AsAIAgent(version);
|
||||
```
|
||||
|
||||
Or use composed `ChatClientAgent`
|
||||
|
||||
```csharp
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), credential);
|
||||
|
||||
AgentVersion version = await aiProjectClient.Agents.CreateAgentVersionAsync(
|
||||
"JokerAgent",
|
||||
new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(deploymentName)
|
||||
{
|
||||
Instructions = "You are good at telling jokes."
|
||||
}));
|
||||
|
||||
ProjectResponsesClient projectResponsesClient = aiProjectClient
|
||||
.GetProjectOpenAIClient()
|
||||
.GetProjectResponsesClientForAgent(new AgentReference(version.Name, version.Version));
|
||||
|
||||
ChatClientAgent agent = new(
|
||||
chatClient: projectResponsesClient.AsIChatClient(),
|
||||
name: "JokerAgent");
|
||||
```
|
||||
|
||||
### Samples
|
||||
|
||||
- `FoundryAgents/` samples show the direct Responses path with `AIProjectClient.AsAIAgent(...)`.
|
||||
- `FoundryVersionedAgents/` samples should show native `AIProjectClient.Agents` create/get/delete flows plus `AsAIAgent(...)`.
|
||||
|
||||
### Compatibility APIs
|
||||
|
||||
Obsolete helper extensions remain only to ease migration of existing code. New samples and new guidance should not be written against them.
|
||||
|
||||
## Rejected direction
|
||||
|
||||
Do not introduce or preserve separate public wrapper types whose main purpose is to forward to `ChatClientAgent` while carrying Foundry-specific naming.
|
||||
|
||||
That approach:
|
||||
|
||||
- duplicates lifecycle concepts already present on `AIProjectClient`,
|
||||
- fragments the public API,
|
||||
- complicates samples and docs,
|
||||
- and makes migration harder by encouraging wrapper-specific affordances.
|
||||
@@ -1,4 +1,4 @@
|
||||
<Solution>
|
||||
<Solution>
|
||||
<Configurations>
|
||||
<BuildType Name="Debug" />
|
||||
<BuildType Name="Publish" />
|
||||
@@ -121,6 +121,34 @@
|
||||
<Project Path="samples/02-agents/AgentWithAnthropic/Agent_Anthropic_Step03_UsingFunctionTools/Agent_Anthropic_Step03_UsingFunctionTools.csproj" />
|
||||
<Project Path="samples/02-agents/AgentWithAnthropic/Agent_Anthropic_Step04_UsingSkills/Agent_Anthropic_Step04_UsingSkills.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/02-agents/AgentsWithFoundry/">
|
||||
<File Path="samples/02-agents/AgentsWithFoundry/README.md" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Agent_Step00_FoundryAgentLifecycle.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Agent_Step01_Basics.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Agent_Step02.1_MultiturnConversation.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Agent_Step02.2_MultiturnWithServerConversations.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/Agent_Step07_Observability.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/Agent_Step08_DependencyInjection.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Agent_Step09_UsingMcpClientAsTools.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/Agent_Step10_UsingImages.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/Agent_Step11_AsFunctionTool.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step12_Middleware/Agent_Step12_Middleware.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/Agent_Step13_Plugins.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/Agent_Step14_CodeInterpreter.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Agent_Step15_ComputerUse.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/Agent_Step16_FileSearch.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/Agent_Step17_OpenAPITools.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Agent_Step21_WebSearch.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj" />
|
||||
<Project Path="samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/Agent_Step23_LocalMCP.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/02-agents/AgentWithMemory/">
|
||||
<File Path="samples/02-agents/AgentWithMemory/README.md" />
|
||||
<Project Path="samples/02-agents/AgentWithMemory/AgentWithMemory_Step01_ChatHistoryMemory/AgentWithMemory_Step01_ChatHistoryMemory.csproj" />
|
||||
@@ -143,35 +171,6 @@
|
||||
<Project Path="samples/02-agents/AgentWithRAG/AgentWithRAG_Step03_CustomRAGDataSource/AgentWithRAG_Step03_CustomRAGDataSource.csproj" />
|
||||
<Project Path="samples/02-agents/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/AgentWithRAG_Step04_FoundryServiceRAG.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/02-agents/FoundryAgents/">
|
||||
<File Path="samples/02-agents/FoundryAgents/README.md" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/FoundryAgents_Evaluations_Step01_RedTeaming.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/FoundryAgents_Evaluations_Step02_SelfReflection.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step16_FileSearch/FoundryAgents_Step16_FileSearch.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/FoundryAgents_Step17_OpenAPITools.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/FoundryAgents_Step18_BingCustomSearch.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/FoundryAgents_Step19_SharePoint.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/FoundryAgents_Step20_MicrosoftFabric.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/FoundryAgents_Step21_WebSearch.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/FoundryAgents_Step22_MemorySearch.csproj" />
|
||||
<Project Path="samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/FoundryAgents_Step23_LocalMCP.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Samples/02-agents/ModelContextProtocol/">
|
||||
<File Path="samples/02-agents/ModelContextProtocol/README.md" />
|
||||
<Project Path="samples/02-agents/ModelContextProtocol/Agent_MCP_Server/Agent_MCP_Server.csproj" />
|
||||
@@ -318,8 +317,8 @@
|
||||
<Folder Name="/Samples/05-end-to-end/AspNetAgentAuthorization/">
|
||||
<File Path="samples/05-end-to-end/AspNetAgentAuthorization/docker-compose.yml" />
|
||||
<File Path="samples/05-end-to-end/AspNetAgentAuthorization/README.md" />
|
||||
<Project Path="samples/05-end-to-end/AspNetAgentAuthorization/Service/Service.csproj" />
|
||||
<Project Path="samples/05-end-to-end/AspNetAgentAuthorization/RazorWebClient/RazorWebClient.csproj" />
|
||||
<Project Path="samples/05-end-to-end/AspNetAgentAuthorization/Service/Service.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/Solution Items/">
|
||||
<File Path=".editorconfig" />
|
||||
|
||||
@@ -70,7 +70,7 @@ while ((input = Console.ReadLine()) != null && !input.Equals("exit", StringCompa
|
||||
|
||||
if (approvalRequest.AdditionalProperties != null)
|
||||
{
|
||||
approvalResponse.AdditionalProperties = new AdditionalPropertiesDictionary();
|
||||
approvalResponse.AdditionalProperties = [];
|
||||
foreach (var kvp in approvalRequest.AdditionalProperties)
|
||||
{
|
||||
approvalResponse.AdditionalProperties[kvp.Key] = kvp.Value;
|
||||
|
||||
@@ -131,9 +131,9 @@ internal sealed class ServerFunctionApprovalClientAgent : DelegatingAIAgent
|
||||
transformedContents ??= CopyContentsUpToIndex(message.Contents, contentIndex);
|
||||
approvalCalls.Remove(functionResult.CallId);
|
||||
}
|
||||
else if (transformedContents != null)
|
||||
else
|
||||
{
|
||||
transformedContents.Add(content);
|
||||
transformedContents?.Add(content);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,10 +155,10 @@ internal sealed class ServerFunctionApprovalClientAgent : DelegatingAIAgent
|
||||
result ??= CopyMessagesUpToIndex(messages, messageIndex);
|
||||
result.Add(newMessage);
|
||||
}
|
||||
else if (result != null)
|
||||
else
|
||||
{
|
||||
// We're already copying messages, so copy this unchanged message too
|
||||
result.Add(message);
|
||||
result?.Add(message);
|
||||
}
|
||||
// If result is null, we haven't made any changes yet, so keep processing
|
||||
}
|
||||
|
||||
@@ -57,16 +57,10 @@ internal sealed class ServerFunctionApprovalAgent : DelegatingAIAgent
|
||||
throw new InvalidOperationException("Invalid request_approval tool call");
|
||||
}
|
||||
|
||||
var request = toolCall.Arguments.TryGetValue("request", out var reqObj) &&
|
||||
var request = (toolCall.Arguments.TryGetValue("request", out var reqObj) &&
|
||||
reqObj is JsonElement argsElement &&
|
||||
argsElement.Deserialize(jsonSerializerOptions.GetTypeInfo(typeof(ApprovalRequest))) is ApprovalRequest approvalRequest &&
|
||||
approvalRequest != null ? approvalRequest : null;
|
||||
|
||||
if (request == null)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to deserialize approval request from tool call");
|
||||
}
|
||||
|
||||
approvalRequest != null ? approvalRequest : null) ?? throw new InvalidOperationException("Failed to deserialize approval request from tool call");
|
||||
return new ToolApprovalRequestContent(
|
||||
requestId: request.ApprovalId,
|
||||
new FunctionCallContent(
|
||||
@@ -77,17 +71,11 @@ internal sealed class ServerFunctionApprovalAgent : DelegatingAIAgent
|
||||
|
||||
private static ToolApprovalResponseContent ConvertToolResultToApprovalResponse(FunctionResultContent result, ToolApprovalRequestContent approval, JsonSerializerOptions jsonSerializerOptions)
|
||||
{
|
||||
var approvalResponse = result.Result is JsonElement je ?
|
||||
var approvalResponse = (result.Result is JsonElement je ?
|
||||
(ApprovalResponse?)je.Deserialize(jsonSerializerOptions.GetTypeInfo(typeof(ApprovalResponse))) :
|
||||
result.Result is string str ?
|
||||
(ApprovalResponse?)JsonSerializer.Deserialize(str, jsonSerializerOptions.GetTypeInfo(typeof(ApprovalResponse))) :
|
||||
result.Result as ApprovalResponse;
|
||||
|
||||
if (approvalResponse == null)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to deserialize approval response from tool result");
|
||||
}
|
||||
|
||||
result.Result as ApprovalResponse) ?? throw new InvalidOperationException("Failed to deserialize approval response from tool result");
|
||||
return approval.CreateResponse(approvalResponse.Approved);
|
||||
}
|
||||
#pragma warning restore MEAI001
|
||||
@@ -121,7 +109,7 @@ internal sealed class ServerFunctionApprovalAgent : DelegatingAIAgent
|
||||
// Track approval ID to original call ID mapping
|
||||
_ = new Dictionary<string, string>();
|
||||
#pragma warning disable MEAI001 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
|
||||
Dictionary<string, ToolApprovalRequestContent> trackedRequestApprovalToolCalls = new(); // Remote approvals
|
||||
Dictionary<string, ToolApprovalRequestContent> trackedRequestApprovalToolCalls = []; // Remote approvals
|
||||
for (int messageIndex = 0; messageIndex < messages.Count; messageIndex++)
|
||||
{
|
||||
var message = messages[messageIndex];
|
||||
@@ -146,7 +134,7 @@ internal sealed class ServerFunctionApprovalAgent : DelegatingAIAgent
|
||||
});
|
||||
}
|
||||
else if (content is FunctionResultContent toolResult &&
|
||||
trackedRequestApprovalToolCalls.TryGetValue(toolResult.CallId, out var approval) == true)
|
||||
trackedRequestApprovalToolCalls.TryGetValue(toolResult.CallId, out var approval))
|
||||
{
|
||||
result ??= CopyMessagesUpToIndex(messages, messageIndex);
|
||||
transformedContents ??= CopyContentsUpToIndex(message.Contents, j);
|
||||
@@ -161,9 +149,9 @@ internal sealed class ServerFunctionApprovalAgent : DelegatingAIAgent
|
||||
AdditionalProperties = message.AdditionalProperties
|
||||
});
|
||||
}
|
||||
else if (result != null)
|
||||
else
|
||||
{
|
||||
result.Add(message);
|
||||
result?.Add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,10 +72,9 @@ internal sealed class StatefulAgent<TState> : DelegatingAIAgent
|
||||
if (content is DataContent dataContent && dataContent.MediaType == "application/json")
|
||||
{
|
||||
// Deserialize the state
|
||||
TState? newState = JsonSerializer.Deserialize(
|
||||
if (JsonSerializer.Deserialize(
|
||||
dataContent.Data.Span,
|
||||
this._jsonSerializerOptions.GetTypeInfo(typeof(TState))) as TState;
|
||||
if (newState != null)
|
||||
this._jsonSerializerOptions.GetTypeInfo(typeof(TState))) is TState newState)
|
||||
{
|
||||
this.State = newState;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
var deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
@@ -30,14 +31,18 @@ var createdAgentVersion = aiProjectClient.Agents.CreateAgentVersion(agentName: J
|
||||
// agentVersion.Name = <agentName>
|
||||
|
||||
// You can use an AIAgent with an already created server side agent version.
|
||||
AIAgent existingJokerAgent = aiProjectClient.AsAIAgent(createdAgentVersion);
|
||||
FoundryAgent existingJokerAgent = aiProjectClient.AsAIAgent(createdAgentVersion);
|
||||
|
||||
// You can also create another AIAgent version by providing the same name with a different definition.
|
||||
AIAgent newJokerAgent = await aiProjectClient.CreateAIAgentAsync(name: JokerName, model: deploymentName, instructions: "You are extremely hilarious at telling jokes.");
|
||||
AgentVersion newJokerAgentVersion = await aiProjectClient.Agents.CreateAgentVersionAsync(
|
||||
JokerName,
|
||||
new AgentVersionCreationOptions(new PromptAgentDefinition(model: deploymentName) { Instructions = "You are extremely hilarious at telling jokes." }));
|
||||
FoundryAgent newJokerAgent = aiProjectClient.AsAIAgent(newJokerAgentVersion);
|
||||
|
||||
// You can also get the AIAgent latest version just providing its name.
|
||||
AIAgent jokerAgentLatest = await aiProjectClient.GetAIAgentAsync(name: JokerName);
|
||||
var latestAgentVersion = jokerAgentLatest.GetService<AgentVersion>()!;
|
||||
AgentRecord jokerAgentRecord = await aiProjectClient.Agents.GetAgentAsync(JokerName);
|
||||
FoundryAgent jokerAgentLatest = aiProjectClient.AsAIAgent(jokerAgentRecord);
|
||||
AgentVersion latestAgentVersion = jokerAgentRecord.GetLatestVersion();
|
||||
|
||||
// The AIAgent version can be accessed via the GetService method.
|
||||
Console.WriteLine($"Latest agent version id: {latestAgentVersion.Id}");
|
||||
|
||||
@@ -5,20 +5,13 @@
|
||||
using Anthropic;
|
||||
using Anthropic.Core;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY") ?? throw new InvalidOperationException("ANTHROPIC_API_KEY is not set.");
|
||||
var model = Environment.GetEnvironmentVariable("ANTHROPIC_CHAT_MODEL_NAME") ?? "claude-haiku-4-5";
|
||||
|
||||
AIAgent agent = new AnthropicClient(new ClientOptions { ApiKey = apiKey })
|
||||
AIAgent agent =
|
||||
new AnthropicClient(new ClientOptions { ApiKey = apiKey })
|
||||
.AsAIAgent(model: model, instructions: "You are good at telling jokes.", name: "Joker");
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
var response = await agent.RunAsync("Tell me a joke about a pirate.");
|
||||
Console.WriteLine(response);
|
||||
|
||||
// Invoke the agent with streaming support.
|
||||
await foreach (var update in agent.RunStreamingAsync("Tell me a joke about a pirate."))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
}
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
|
||||
@@ -11,6 +11,7 @@ using System.Text.Json;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
using Microsoft.Agents.AI.FoundryMemory;
|
||||
|
||||
string foundryEndpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
@@ -19,6 +20,9 @@ string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLO
|
||||
string embeddingModelName = Environment.GetEnvironmentVariable("AZURE_AI_EMBEDDING_DEPLOYMENT_NAME") ?? "text-embedding-ada-002";
|
||||
|
||||
// Create an AIProjectClient for Foundry with Azure Identity authentication.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
DefaultAzureCredential credential = new();
|
||||
AIProjectClient projectClient = new(new Uri(foundryEndpoint), credential);
|
||||
|
||||
@@ -33,11 +37,15 @@ FoundryMemoryProvider memoryProvider = new(
|
||||
memoryStoreName,
|
||||
stateInitializer: _ => new(new FoundryMemoryProviderScope("sample-user-123")));
|
||||
|
||||
AIAgent agent = await projectClient.CreateAIAgentAsync(deploymentName,
|
||||
options: new ChatClientAgentOptions()
|
||||
FoundryAgent agent = projectClient.AsAIAgent(
|
||||
new ChatClientAgentOptions()
|
||||
{
|
||||
Name = "TravelAssistantWithFoundryMemory",
|
||||
ChatOptions = new() { Instructions = "You are a friendly travel assistant. Use known memories about the user when responding, and do not invent details." },
|
||||
ChatOptions = new()
|
||||
{
|
||||
ModelId = deploymentName,
|
||||
Instructions = "You are a friendly travel assistant. Use known memories about the user when responding, and do not invent details."
|
||||
},
|
||||
AIContextProviders = [memoryProvider]
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Agent Framework Retrieval Augmented Generation (RAG)
|
||||
# Agent Framework Retrieval Augmented Generation (RAG)
|
||||
|
||||
These samples show how to create an agent with the Agent Framework that uses Memory to remember previous conversations or facts from previous conversations.
|
||||
|
||||
@@ -10,4 +10,4 @@ These samples show how to create an agent with the Agent Framework that uses Mem
|
||||
|[Memory with Azure AI Foundry](./AgentWithMemory_Step04_MemoryUsingFoundry/)|This sample demonstrates how to create and run an agent that uses Azure AI Foundry's managed memory service to extract and retrieve individual memories.|
|
||||
|[Bounded Chat History with Overflow](./AgentWithMemory_Step05_BoundedChatHistory/)|This sample demonstrates how to create a bounded chat history provider that overflows older messages to a vector store and recalls them as memories.|
|
||||
|
||||
> **See also**: [Memory Search with Foundry Agents](../FoundryAgents/FoundryAgents_Step22_MemorySearch/) - demonstrates using the built-in Memory Search tool with Azure Foundry Agents.
|
||||
> **See also**: [Memory Search with Foundry Agents](../AgentsWithFoundry/Agent_Step22_MemorySearch/) - demonstrates using the built-in Memory Search tool with Azure Foundry agents.
|
||||
|
||||
@@ -4,28 +4,14 @@
|
||||
|
||||
using System.ClientModel;
|
||||
using Microsoft.Agents.AI;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
using OpenAI.Responses;
|
||||
|
||||
var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new InvalidOperationException("OPENAI_API_KEY is not set.");
|
||||
var model = Environment.GetEnvironmentVariable("OPENAI_CHAT_MODEL_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
AIAgent agent = new OpenAIClient(apiKey)
|
||||
.GetChatClient(model)
|
||||
.AsAIAgent(instructions: "You are good at telling jokes.", name: "Joker");
|
||||
AIAgent agent =
|
||||
new ResponsesClient(new ApiKeyCredential(apiKey))
|
||||
.AsAIAgent(model: model, instructions: "You are good at telling jokes.", name: "Joker");
|
||||
|
||||
UserChatMessage chatMessage = new("Tell me a joke about a pirate.");
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
ChatCompletion chatCompletion = await agent.RunAsync([chatMessage]);
|
||||
Console.WriteLine(chatCompletion.Content.Last().Text);
|
||||
|
||||
// Invoke the agent with streaming support.
|
||||
AsyncCollectionResult<StreamingChatCompletionUpdate> completionUpdates = agent.RunStreamingAsync([chatMessage]);
|
||||
await foreach (StreamingChatCompletionUpdate completionUpdate in completionUpdates)
|
||||
{
|
||||
if (completionUpdate.ContentUpdate.Count > 0)
|
||||
{
|
||||
Console.WriteLine(completionUpdate.ContentUpdate[0].Text);
|
||||
}
|
||||
}
|
||||
// Once you have the agent, you can invoke it like any other AIAgent.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
|
||||
using System.ClientModel;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
using OpenAI;
|
||||
using OpenAI.Files;
|
||||
using OpenAI.Responses;
|
||||
using OpenAI.VectorStores;
|
||||
|
||||
var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
@@ -37,14 +39,20 @@ ClientResult<VectorStore> vectorStoreCreate = await vectorStoreClient.CreateVect
|
||||
FileIds = { uploadResult.Value.Id }
|
||||
});
|
||||
|
||||
var fileSearchTool = new HostedFileSearchTool() { Inputs = [new HostedVectorStoreContent(vectorStoreCreate.Value.Id)] };
|
||||
// Use the native OpenAI SDK FileSearchTool directly with the vector store ID.
|
||||
#pragma warning disable OPENAI001
|
||||
FileSearchTool fileSearchTool = new([vectorStoreCreate.Value.Id]);
|
||||
#pragma warning restore OPENAI001
|
||||
|
||||
AIAgent agent = await aiProjectClient
|
||||
.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: "AskContoso",
|
||||
instructions: "You are a helpful support specialist for Contoso Outdoors. Answer questions using the provided context and cite the source document when available.",
|
||||
tools: [fileSearchTool]);
|
||||
AgentVersion agentVersion = await aiProjectClient.Agents.CreateAgentVersionAsync(
|
||||
"AskContoso",
|
||||
new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = "You are a helpful support specialist for Contoso Outdoors. Answer questions using the provided context and cite the source document when available.",
|
||||
Tools = { fileSearchTool }
|
||||
}));
|
||||
FoundryAgent agent = aiProjectClient.AsAIAgent(agentVersion);
|
||||
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// This sample shows how to expose an AI agent as an MCP tool.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -18,11 +19,17 @@ var deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYME
|
||||
var aiProjectClient = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create a server side agent and expose it as an AIAgent.
|
||||
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
instructions: "You are good at telling jokes, and you always start each joke with 'Aye aye, captain!'.",
|
||||
name: "Joker",
|
||||
description: "An agent that tells jokes.");
|
||||
AgentVersion agentVersion = await aiProjectClient.Agents.CreateAgentVersionAsync(
|
||||
"Joker",
|
||||
new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = "You are good at telling jokes, and you always start each joke with 'Aye aye, captain!'.",
|
||||
})
|
||||
{
|
||||
Description = "An agent that tells jokes.",
|
||||
});
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(agentVersion);
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -189,9 +189,9 @@ async Task<AgentResponse> PIIMiddleware(IEnumerable<ChatMessage> messages, Agent
|
||||
// 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)
|
||||
MyRegex(), // Phone number (e.g., 123-456-7890)
|
||||
EmailRegex(), // Email address
|
||||
FullNameRegex() // Full name (e.g., John Doe)
|
||||
];
|
||||
|
||||
foreach (var pattern in piiPatterns)
|
||||
@@ -309,3 +309,15 @@ internal sealed class DateTimeContextProvider : MessageAIContextProvider
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
internal partial class Program
|
||||
{
|
||||
[GeneratedRegex(@"\b\d{3}-\d{3}-\d{4}\b", RegexOptions.Compiled)]
|
||||
private static partial Regex MyRegex();
|
||||
|
||||
[GeneratedRegex(@"\b[\w\.-]+@[\w\.-]+\.\w+\b", RegexOptions.Compiled)]
|
||||
private static partial Regex EmailRegex();
|
||||
|
||||
[GeneratedRegex(@"\b[A-Z][a-z]+\s[A-Z][a-z]+\b", RegexOptions.Compiled)]
|
||||
private static partial Regex FullNameRegex();
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ var bingConnectionId = Environment.GetEnvironmentVariable("AZURE_AI_BING_CONNECT
|
||||
PersistentAgentsAdministrationClientOptions persistentAgentsClientOptions = new();
|
||||
persistentAgentsClientOptions.Retry.NetworkTimeout = TimeSpan.FromMinutes(20);
|
||||
|
||||
// Get a client to create/retrieve server side agents with.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
// Get a client to create/retrieve server side agents with.
|
||||
PersistentAgentsClient persistentAgentsClient = new(endpoint, new DefaultAzureCredential(), persistentAgentsClientOptions);
|
||||
|
||||
// Define and configure the Deep Research tool.
|
||||
|
||||
@@ -23,12 +23,14 @@ Before running this sample, ensure you have:
|
||||
|
||||
Pay special attention to the purple `Note` boxes in the Azure documentation.
|
||||
|
||||
**Note**: The Bing Connection ID must be from the **project**, not the resource. It has the following format:
|
||||
**Note**: The Bing Grounding Connection ID must be the **full ARM resource URI** from the project, not just the connection name. It has the following format:
|
||||
|
||||
```
|
||||
/subscriptions/<sub_id>/resourceGroups/<rg_name>/providers/<provider_name>/accounts/<account_name>/projects/<project_name>/connections/<connection_name>
|
||||
/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<account>/projects/<project>/connections/<connection-name>
|
||||
```
|
||||
|
||||
You can find this in the Azure AI Foundry portal under **Management > Connected resources**, or retrieve it programmatically via the connections API (`.id` property).
|
||||
|
||||
## Environment Variables
|
||||
|
||||
Set the following environment variables:
|
||||
@@ -37,8 +39,8 @@ Set the following environment variables:
|
||||
# Replace with your Azure AI Foundry project endpoint
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-project.services.ai.azure.com/"
|
||||
|
||||
# Replace with your Bing connection ID from the project
|
||||
$env:AZURE_AI_BING_CONNECTION_ID="/subscriptions/.../connections/your-bing-connection"
|
||||
# Replace with your Bing Grounding connection ID (full ARM resource URI)
|
||||
$env:AZURE_AI_BING_CONNECTION_ID="/subscriptions/<sub-id>/resourceGroups/<rg>/providers/Microsoft.CognitiveServices/accounts/<account>/projects/<project>/connections/<connection-name>"
|
||||
|
||||
# Optional, defaults to o3-deep-research
|
||||
$env:AZURE_AI_REASONING_DEPLOYMENT_NAME="o3-deep-research"
|
||||
|
||||
@@ -24,12 +24,12 @@ var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT
|
||||
Func<Task<string[]>> loadNextThreeCalendarEvents = async () =>
|
||||
{
|
||||
// In a real implementation, this method would connect to a calendar service
|
||||
return new string[]
|
||||
{
|
||||
return
|
||||
[
|
||||
"Doctor's appointment today at 15:00",
|
||||
"Team meeting today at 17:00",
|
||||
"Birthday party today at 20:00"
|
||||
};
|
||||
];
|
||||
};
|
||||
|
||||
// Create an agent with an AI context provider attached that aggregates two other providers:
|
||||
@@ -87,7 +87,7 @@ namespace SampleApp
|
||||
internal sealed class TodoListAIContextProvider : AIContextProvider
|
||||
{
|
||||
private static List<string> GetTodoItems(AgentSession? session)
|
||||
=> session?.StateBag.GetValue<List<string>>(nameof(TodoListAIContextProvider)) ?? new List<string>();
|
||||
=> session?.StateBag.GetValue<List<string>>(nameof(TodoListAIContextProvider)) ?? [];
|
||||
|
||||
private static void SetTodoItems(AgentSession? session, List<string> items)
|
||||
=> session?.StateBag.SetValue(nameof(TodoListAIContextProvider), items);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create, use, and clean up a FoundryAgent backed by a server-side
|
||||
// versioned agent in Azure AI Foundry. It demonstrates the full lifecycle:
|
||||
// create agent version -> wrap as FoundryAgent -> run -> delete.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string JokerName = "JokerAgent";
|
||||
|
||||
// Create the AIProjectClient to manage server-side agents.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential());
|
||||
|
||||
// Create a server-side agent version using the native SDK.
|
||||
AgentVersion agentVersion = await aiProjectClient.Agents.CreateAgentVersionAsync(
|
||||
JokerName,
|
||||
new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = "You are good at telling jokes.",
|
||||
}));
|
||||
|
||||
// Wrap the agent version as a FoundryAgent using the AsAIAgent extension.
|
||||
FoundryAgent agent = aiProjectClient.AsAIAgent(agentVersion);
|
||||
|
||||
// Once you have the agent, you can invoke it like any other AIAgent.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
|
||||
// Cleanup: deletes the agent and all its versions.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
@@ -0,0 +1,23 @@
|
||||
# Agent Step 00 - FoundryAgent Lifecycle
|
||||
|
||||
This sample demonstrates the full lifecycle of a `FoundryAgent` backed by a server-side versioned agent in Microsoft Foundry: create → run → delete.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A Microsoft Foundry project endpoint
|
||||
- A model deployment name (defaults to `gpt-4o-mini`)
|
||||
- Azure CLI installed and authenticated
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Required |
|
||||
| --- | --- | --- |
|
||||
| `AZURE_AI_PROJECT_ENDPOINT` | Microsoft Foundry project endpoint | Yes |
|
||||
| `AZURE_AI_MODEL_DEPLOYMENT_NAME` | Model deployment name | No (defaults to `gpt-4o-mini`) |
|
||||
|
||||
## Running the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step00_FoundryAgentLifecycle
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and run a basic agent with AIProjectClient.AsAIAgent(...).
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIAgent agent =
|
||||
new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
|
||||
.AsAIAgent(model: deploymentName, instructions: "You are good at telling jokes.", name: "JokerAgent");
|
||||
|
||||
// Once you have the agent, you can invoke it like any other AIAgent.
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
@@ -0,0 +1,55 @@
|
||||
# Creating and Running a Basic Agent with the Responses API
|
||||
|
||||
This sample demonstrates how to create and run a basic AI agent using the `ChatClientAgent`, which uses the Microsoft Foundry Responses API directly without creating server-side agent definitions.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating a `ChatClientAgent` with instructions and a model
|
||||
- Running a simple single-turn conversation
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Microsoft Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
Navigate to the AgentsWithFoundry sample directory and run:
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step01_Basics
|
||||
```
|
||||
|
||||
## Alternative: Composable approach
|
||||
|
||||
You can also create the same agent by composing the underlying `IChatClient` directly. This gives you full control over the chat client pipeline:
|
||||
|
||||
```csharp
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
AIAgent agent = new ChatClientAgent(
|
||||
chatClient: aiProjectClient.GetProjectOpenAIClient().GetProjectResponsesClient().AsIChatClient(deploymentName),
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "JokerAgent");
|
||||
```
|
||||
|
||||
This approach is useful when you need to customize the chat client pipeline or swap providers (e.g., Anthropic, OpenAI) while keeping the same agent code.
|
||||
@@ -9,8 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create a multi-turn conversation agent using sessions.
|
||||
// Context is preserved across multiple runs via response ID chaining in the session.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIAgent agent = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
|
||||
.AsAIAgent(deploymentName, instructions: "You are good at telling jokes.", name: "JokerAgent");
|
||||
|
||||
// Create a session to maintain context across multiple runs.
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
// First turn
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session));
|
||||
|
||||
// Second turn — the agent remembers the first turn via the session.
|
||||
Console.WriteLine(await agent.RunAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", session));
|
||||
@@ -0,0 +1,36 @@
|
||||
# Multi-turn Conversation
|
||||
|
||||
This sample demonstrates how to implement multi-turn conversations where context is preserved across multiple agent runs using sessions and response ID chaining.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating an agent with instructions
|
||||
- Using sessions to maintain conversation context across multiple runs
|
||||
- Response ID chaining for multi-turn conversations
|
||||
- No server-side conversation creation required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Microsoft Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
Navigate to the AgentsWithFoundry sample directory and run:
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step02.1_MultiturnConversation
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use server-side conversations with a FoundryAgent.
|
||||
// Server-side conversations persist on the Foundry service and are visible in the Foundry Project UI.
|
||||
// Use this when you need conversation history to be stored and accessible server-side.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
FoundryAgent agent = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
|
||||
.AsAIAgent(deploymentName, instructions: "You are good at telling jokes.", name: "JokerAgent");
|
||||
|
||||
// CreateConversationSessionAsync creates a server-side ProjectConversation
|
||||
// that persists on the Foundry service and is visible in the Foundry Project UI.
|
||||
AgentSession session = await agent.CreateConversationSessionAsync();
|
||||
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session));
|
||||
Console.WriteLine(await agent.RunAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", session));
|
||||
|
||||
// Streaming with server-side conversation context.
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Tell me another joke, but about a ninja this time.", session))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
@@ -0,0 +1,36 @@
|
||||
# Multi-turn Conversation with Server-Side Conversations
|
||||
|
||||
This sample demonstrates how to use server-side conversations with a `FoundryAgent`. Server-side conversations persist on the Foundry service and are visible in the Foundry Project UI, making them ideal when you need conversation history to be stored and accessible server-side.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating a `FoundryAgent` with instructions
|
||||
- Using `CreateConversationSessionAsync` to create a server-side `ProjectConversation`
|
||||
- Multi-turn conversations with both text and streaming output
|
||||
- Server-side conversation persistence visible in the Foundry Project UI
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Microsoft Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
Navigate to the AgentsWithFoundry sample directory and run:
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step02.2_MultiturnWithServerConversations
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use function tools.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
[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.";
|
||||
|
||||
// Define the function tool.
|
||||
AITool tool = AIFunctionFactory.Create(GetWeather);
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create a AIAgent with function tools.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are a helpful assistant that can get weather information.",
|
||||
name: "WeatherAssistant",
|
||||
tools: [tool]);
|
||||
|
||||
// Non-streaming agent interaction with function tools.
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", session));
|
||||
|
||||
// Streaming agent interaction with function tools.
|
||||
session = await agent.CreateSessionAsync();
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("What is the weather like in Amsterdam?", session))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
# Using Function Tools with the Responses API
|
||||
|
||||
This sample demonstrates how to use function tools with the `ChatClientAgent`, allowing the agent to call custom functions to retrieve information.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating function tools using `AIFunctionFactory`
|
||||
- Passing function tools to a `ChatClientAgent`
|
||||
- Running agents with function tools (text output)
|
||||
- Running agents with function tools (streaming output)
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Microsoft Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
Navigate to the AgentsWithFoundry sample directory and run:
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step03_UsingFunctionTools
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,9 +1,6 @@
|
||||
// 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.Projects;
|
||||
@@ -11,18 +8,13 @@ using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_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";
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
@@ -30,16 +22,16 @@ AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredent
|
||||
|
||||
ApprovalRequiredAIFunction approvalTool = new(AIFunctionFactory.Create(GetWeather, name: nameof(GetWeather)));
|
||||
|
||||
// Create AIAgent directly
|
||||
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(name: AssistantName, model: deploymentName, instructions: AssistantInstructions, tools: [approvalTool]);
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are a helpful assistant that can get weather information.",
|
||||
name: "WeatherAssistant",
|
||||
tools: [approvalTool]);
|
||||
|
||||
// Call the agent with approval-required function tools.
|
||||
// The agent will request approval before invoking the function.
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
AgentResponse response = await agent.RunAsync("What is the weather like in Amsterdam?", session);
|
||||
|
||||
// Check if there are any approval requests.
|
||||
// For simplicity, we are assuming here that only function approvals are pending.
|
||||
List<ToolApprovalRequestContent> approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType<ToolApprovalRequestContent>().ToList();
|
||||
|
||||
while (approvalRequests.Count > 0)
|
||||
@@ -53,13 +45,8 @@ while (approvalRequests.Count > 0)
|
||||
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(approved)]);
|
||||
});
|
||||
|
||||
// Pass the user input responses back to the agent for further processing.
|
||||
response = await agent.RunAsync(userInputMessages, session);
|
||||
|
||||
approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType<ToolApprovalRequestContent>().ToList();
|
||||
}
|
||||
|
||||
Console.WriteLine($"\nAgent: {response}");
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
@@ -0,0 +1,30 @@
|
||||
# Using Function Tools with Approvals via the Responses API
|
||||
|
||||
This sample demonstrates how to use function tools that require human-in-the-loop approval before execution.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating function tools that require approval using `ApprovalRequiredAIFunction`
|
||||
- Handling approval requests from the agent
|
||||
- Passing approval responses back to the agent
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step04_UsingFunctionToolsWithApprovals
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -15,29 +15,23 @@ using SampleApp;
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_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.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create ChatClientAgent directly
|
||||
ChatClientAgent agent = await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
new ChatClientAgentOptions()
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(new ChatClientAgentOptions
|
||||
{
|
||||
Name = "StructuredOutputAssistant",
|
||||
ChatOptions = new()
|
||||
{
|
||||
Name = AssistantName,
|
||||
ChatOptions = new()
|
||||
{
|
||||
Instructions = AssistantInstructions,
|
||||
ResponseFormat = Microsoft.Extensions.AI.ChatResponseFormat.ForJsonSchema<PersonInfo>()
|
||||
}
|
||||
});
|
||||
ModelId = deploymentName,
|
||||
Instructions = "You are a helpful assistant that extracts structured information about people.",
|
||||
ResponseFormat = Microsoft.Extensions.AI.ChatResponseFormat.ForJsonSchema<PersonInfo>()
|
||||
}
|
||||
});
|
||||
|
||||
// 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.
|
||||
// Set PersonInfo as the type parameter of RunAsync method to specify the expected structured output.
|
||||
AgentResponse<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.
|
||||
@@ -46,39 +40,21 @@ 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 = await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
new ChatClientAgentOptions()
|
||||
{
|
||||
Name = AssistantName,
|
||||
ChatOptions = new()
|
||||
{
|
||||
Instructions = AssistantInstructions,
|
||||
ResponseFormat = Microsoft.Extensions.AI.ChatResponseFormat.ForJsonSchema<PersonInfo>()
|
||||
}
|
||||
});
|
||||
// Invoke the agent with streaming support, then deserialize the assembled response.
|
||||
IAsyncEnumerable<AgentResponseUpdate> updates = agent.RunStreamingAsync("Please provide information about Jane Doe, who is a 28-year-old data scientist.");
|
||||
|
||||
// Invoke the agent with some unstructured input while streaming, to extract the structured information from.
|
||||
IAsyncEnumerable<AgentResponseUpdate> 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 = JsonSerializer.Deserialize<PersonInfo>((await updates.ToAgentResponseAsync()).Text, JsonSerializerOptions.Web)
|
||||
?? throw new InvalidOperationException("Failed to deserialize the streamed response into PersonInfo.");
|
||||
|
||||
Console.WriteLine("Assistant Output:");
|
||||
Console.WriteLine("\nStreaming 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.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(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.
|
||||
/// Represents information about a person.
|
||||
/// </summary>
|
||||
[Description("Information about a person including their name, age, and occupation")]
|
||||
public class PersonInfo
|
||||
@@ -0,0 +1,29 @@
|
||||
# Structured Output with the Responses API
|
||||
|
||||
This sample demonstrates how to configure an agent to produce structured output using JSON schema.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Using `RunAsync<T>()` to get typed structured output from the agent
|
||||
- Deserializing streamed responses into structured types
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step05_StructuredOutput
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,6 +1,6 @@
|
||||
// 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.
|
||||
// This sample shows how to persist and resume conversations.
|
||||
|
||||
using System.Text.Json;
|
||||
using Azure.AI.Projects;
|
||||
@@ -10,16 +10,14 @@ using Microsoft.Agents.AI;
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_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.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(name: JokerName, model: deploymentName, instructions: JokerInstructions);
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "JokerAgent");
|
||||
|
||||
// Start a new session for the agent conversation.
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
@@ -42,6 +40,3 @@ AgentSession resumedSession = await agent.DeserializeSessionAsync(reloadedSerial
|
||||
|
||||
// Run the agent again with the resumed session.
|
||||
Console.WriteLine(await agent.RunAsync("Now tell the same joke in the voice of a pirate, and add some emojis to the joke.", resumedSession));
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
@@ -0,0 +1,30 @@
|
||||
# Persisted Conversations with the Responses API
|
||||
|
||||
This sample demonstrates how to persist and resume agent conversations using session serialization.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Serializing agent sessions to JSON for persistence
|
||||
- Saving and loading sessions from disk
|
||||
- Resuming conversations with preserved context
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step06_PersistedConversations
|
||||
```
|
||||
@@ -9,8 +9,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" />
|
||||
<PackageReference Include="OpenTelemetry" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" />
|
||||
@@ -1,6 +1,6 @@
|
||||
// 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.
|
||||
// This sample shows how to add OpenTelemetry observability to an agent.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
@@ -9,15 +9,11 @@ using Microsoft.Agents.AI;
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Trace;
|
||||
|
||||
string? applicationInsightsConnectionString = Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING");
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
string? 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.
|
||||
// Create TracerProvider with console exporter.
|
||||
string sourceName = Guid.NewGuid().ToString("N");
|
||||
TracerProviderBuilder tracerProviderBuilder = Sdk.CreateTracerProviderBuilder()
|
||||
.AddSource(sourceName)
|
||||
@@ -28,14 +24,16 @@ if (!string.IsNullOrWhiteSpace(applicationInsightsConnectionString))
|
||||
}
|
||||
using var tracerProvider = tracerProviderBuilder.Build();
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
AIAgent agent = (await aiProjectClient.CreateAIAgentAsync(name: JokerName, model: deploymentName, instructions: JokerInstructions))
|
||||
AIAgent agent = aiProjectClient
|
||||
.AsAIAgent(
|
||||
deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "JokerAgent")
|
||||
.AsBuilder()
|
||||
.UseOpenTelemetry(sourceName: sourceName)
|
||||
.Build();
|
||||
@@ -48,8 +46,7 @@ Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session
|
||||
session = await agent.CreateSessionAsync();
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync("Tell me a joke about a pirate.", session))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
Console.WriteLine();
|
||||
@@ -0,0 +1,31 @@
|
||||
# Observability with the Responses API
|
||||
|
||||
This sample demonstrates how to add OpenTelemetry observability to an agent using console and Azure Monitor exporters.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Configuring OpenTelemetry tracing with console exporter
|
||||
- Optional Azure Application Insights integration
|
||||
- Using `.AsBuilder().UseOpenTelemetry()` to add telemetry to the agent
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
$env:APPLICATIONINSIGHTS_CONNECTION_STRING="..." # Optional
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step07_Observability
|
||||
```
|
||||
@@ -11,8 +11,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use dependency injection to register a AIAgent and use it from a hosted service.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using SampleApp;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "JokerAgent");
|
||||
|
||||
// Create a host builder that we will register services with and then run.
|
||||
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
|
||||
|
||||
// Add the AI agent to the service collection.
|
||||
builder.Services.AddSingleton(agent);
|
||||
|
||||
// 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);
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
/// <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 AgentSession? _session;
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
this._session = await agent.CreateSessionAsync(cancellationToken);
|
||||
_ = this.RunAsync(appLifetime.ApplicationStopping);
|
||||
}
|
||||
|
||||
public async Task RunAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
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("> ");
|
||||
string? input = Console.ReadLine();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
appLifetime.StopApplication();
|
||||
break;
|
||||
}
|
||||
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(input, this._session, cancellationToken: cancellationToken))
|
||||
{
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
Console.WriteLine("\nShutting down...");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# Dependency Injection with the Responses API
|
||||
|
||||
This sample demonstrates how to register a `ChatClientAgent` in a dependency injection container and use it from a hosted service.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Registering `ChatClientAgent` as an `AIAgent` in the service collection
|
||||
- Using the agent from a `IHostedService` with an interactive chat loop
|
||||
- Streaming responses in a hosted service context
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step08_DependencyInjection
|
||||
```
|
||||
@@ -6,16 +6,15 @@
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<NoWarn>$(NoWarn);CA1812</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="ModelContextProtocol" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use MCP client tools with an agent.
|
||||
// It connects to the Microsoft Learn MCP server via HTTP and uses its tools.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using ModelContextProtocol.Client;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// Connect to the Microsoft Learn MCP server via HTTP (Streamable HTTP transport).
|
||||
Console.WriteLine("Connecting to MCP server at https://learn.microsoft.com/api/mcp ...");
|
||||
|
||||
await using McpClient mcpClient = await McpClient.CreateAsync(new HttpClientTransport(new()
|
||||
{
|
||||
Endpoint = new Uri("https://learn.microsoft.com/api/mcp"),
|
||||
Name = "Microsoft Learn MCP",
|
||||
}));
|
||||
|
||||
// Retrieve the list of tools available on the MCP server.
|
||||
IList<McpClientTool> mcpTools = await mcpClient.ListToolsAsync();
|
||||
Console.WriteLine($"MCP tools available: {string.Join(", ", mcpTools.Select(t => t.Name))}");
|
||||
|
||||
List<AITool> agentTools = [.. mcpTools.Cast<AITool>()];
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are a helpful assistant that can help with Microsoft documentation questions. Use the Microsoft Learn MCP tool to search for documentation.",
|
||||
name: "DocsAgent",
|
||||
tools: agentTools);
|
||||
|
||||
Console.WriteLine($"Agent '{agent.Name}' created. Asking a question...\n");
|
||||
|
||||
const string Prompt = "How does one create an Azure storage account using az cli?";
|
||||
Console.WriteLine($"User: {Prompt}\n");
|
||||
Console.WriteLine($"Agent: {await agent.RunAsync(Prompt)}");
|
||||
@@ -0,0 +1,29 @@
|
||||
# Using MCP Client as Tools with the Responses API
|
||||
|
||||
This sample shows how to use MCP (Model Context Protocol) client tools with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Connecting to an MCP server via HTTP client transport
|
||||
- Retrieving MCP tools and passing them to a `ChatClientAgent`
|
||||
- Using MCP tools for agent interactions without server-side agent creation
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
- Node.js installed (for npx/MCP server)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="assets\walkway.jpg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use Image Multi-Modality with an AI agent.
|
||||
// This sample shows how to use image multi-modality with an agent.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
@@ -10,29 +10,25 @@ using Microsoft.Extensions.AI;
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_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.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(name: VisionName, model: deploymentName, instructions: VisionInstructions);
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are a helpful agent that can analyze images.",
|
||||
name: "VisionAgent");
|
||||
|
||||
ChatMessage message = new(ChatRole.User, [
|
||||
new TextContent("What do you see in this image?"),
|
||||
await DataContent.LoadFromAsync("Assets/walkway.jpg"),
|
||||
await DataContent.LoadFromAsync("assets/walkway.jpg"),
|
||||
]);
|
||||
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
|
||||
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(message, session))
|
||||
{
|
||||
Console.WriteLine(update);
|
||||
Console.Write(update);
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
Console.WriteLine();
|
||||
@@ -0,0 +1,30 @@
|
||||
# Using Images with the Responses API
|
||||
|
||||
This sample demonstrates how to use image multi-modality with an agent.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Loading images using `DataContent.LoadFromAsync`
|
||||
- Sending images alongside text to the agent
|
||||
- Streaming the agent's image analysis response
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and a vision-capable model deployment (e.g., `gpt-4o`)
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step10_UsingImages
|
||||
```
|
||||
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to create and use an Azure Foundry Agents AI agent as a function tool.
|
||||
// This sample shows how to use one agent as a function tool for another agent.
|
||||
|
||||
using System.ComponentModel;
|
||||
using Azure.AI.Projects;
|
||||
@@ -8,43 +8,29 @@ using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_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.
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create the weather agent with function tools.
|
||||
AITool weatherTool = AIFunctionFactory.Create(GetWeather);
|
||||
AIAgent weatherAgent = await aiProjectClient.CreateAIAgentAsync(
|
||||
name: WeatherName,
|
||||
model: deploymentName,
|
||||
instructions: WeatherInstructions,
|
||||
AIAgent weatherAgent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You answer questions about the weather.",
|
||||
name: "WeatherAgent",
|
||||
tools: [weatherTool]);
|
||||
|
||||
// Create the main agent, and provide the weather agent as a function tool.
|
||||
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
|
||||
name: MainName,
|
||||
model: deploymentName,
|
||||
instructions: MainInstructions,
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are a helpful assistant who responds in French.",
|
||||
name: "MainAgent",
|
||||
tools: [weatherAgent.AsAIFunction()]);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", session));
|
||||
|
||||
// Cleanup by agent name removes the agent versions created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(weatherAgent.Name);
|
||||
@@ -0,0 +1,30 @@
|
||||
# Agent as a Function Tool with the Responses API
|
||||
|
||||
This sample demonstrates how to use one agent as a function tool for another agent.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating a specialized agent (weather) with function tools
|
||||
- Exposing an agent as a function tool using `.AsAIFunction()`
|
||||
- Composing agents where one agent delegates to another
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step11_AsFunctionTool
|
||||
```
|
||||
@@ -3,15 +3,13 @@
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -1,6 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows multiple middleware layers working together with Azure Foundry Agents:
|
||||
// This sample shows multiple middleware layers working together with a ChatClientAgent:
|
||||
// agent run (PII filtering and guardrails),
|
||||
// function invocation (logging and result overrides), and human-in-the-loop
|
||||
// approval workflows for sensitive function calls.
|
||||
@@ -12,19 +12,6 @@ using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
// Get Azure AI Foundry configuration from environment variables
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = System.Environment.GetEnvironmentVariable("AZURE_AI_MODEL_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.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
[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.";
|
||||
@@ -33,14 +20,20 @@ static string GetWeather([Description("The location to get the weather for.")] s
|
||||
static string GetDateTime()
|
||||
=> DateTimeOffset.Now.ToString();
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
AITool dateTimeTool = AIFunctionFactory.Create(GetDateTime, name: nameof(GetDateTime));
|
||||
AITool getWeatherTool = AIFunctionFactory.Create(GetWeather, name: nameof(GetWeather));
|
||||
|
||||
// Define the agent you want to create. (Prompt Agent in this case)
|
||||
AIAgent originalAgent = await aiProjectClient.CreateAIAgentAsync(
|
||||
name: AssistantName,
|
||||
model: deploymentName,
|
||||
instructions: AssistantInstructions,
|
||||
AIAgent originalAgent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are an AI assistant that helps people find information.",
|
||||
name: "InformationAssistant",
|
||||
tools: [getWeatherTool, dateTimeTool]);
|
||||
|
||||
// Adding middleware to the agent level
|
||||
@@ -63,24 +56,17 @@ AgentResponse piiResponse = await middlewareEnabledAgent.RunAsync("My name is Jo
|
||||
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.
|
||||
|
||||
AgentResponse functionCallResponse = await middlewareEnabledAgent.RunAsync("What's the current time and the weather in Seattle?", session);
|
||||
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 humanInTheLoopAgent = await aiProjectClient.CreateAIAgentAsync(
|
||||
AIAgent humanInTheLoopAgent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: "You are a Human in the loop testing AI assistant that helps people find information.",
|
||||
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.
|
||||
AgentResponse response = await humanInTheLoopAgent
|
||||
.AsBuilder()
|
||||
.Use(ConsolePromptingApprovalMiddleware, null)
|
||||
@@ -108,7 +94,6 @@ async ValueTask<object?> FunctionCallOverrideWeather(AIAgent agent, FunctionInvo
|
||||
|
||||
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");
|
||||
@@ -118,18 +103,16 @@ async ValueTask<object?> FunctionCallOverrideWeather(AIAgent agent, FunctionInvo
|
||||
// This middleware redacts PII information from input and output messages.
|
||||
async Task<AgentResponse> PIIMiddleware(IEnumerable<ChatMessage> messages, AgentSession? session, 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, session, options, cancellationToken).ConfigureAwait(false);
|
||||
var agentResponse = await innerAgent.RunAsync(filteredMessages, session, options, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Redact PII information from output messages
|
||||
response.Messages = FilterMessages(response.Messages);
|
||||
agentResponse.Messages = FilterMessages(agentResponse.Messages);
|
||||
|
||||
Console.WriteLine("Pii Middleware - Filtered Messages Post-Run");
|
||||
|
||||
return response;
|
||||
return agentResponse;
|
||||
|
||||
static IList<ChatMessage> FilterMessages(IEnumerable<ChatMessage> messages)
|
||||
{
|
||||
@@ -138,11 +121,10 @@ async Task<AgentResponse> PIIMiddleware(IEnumerable<ChatMessage> messages, Agent
|
||||
|
||||
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)
|
||||
MyRegex(),
|
||||
EmailRegex(),
|
||||
FullNameRegex()
|
||||
];
|
||||
|
||||
foreach (var pattern in piiPatterns)
|
||||
@@ -157,20 +139,17 @@ async Task<AgentResponse> PIIMiddleware(IEnumerable<ChatMessage> messages, Agent
|
||||
// This middleware enforces guardrails by redacting certain keywords from input and output messages.
|
||||
async Task<AgentResponse> GuardrailMiddleware(IEnumerable<ChatMessage> messages, AgentSession? session, 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, session, options, cancellationToken);
|
||||
var agentResponse = await innerAgent.RunAsync(filteredMessages, session, options, cancellationToken);
|
||||
|
||||
// Redact keywords from output messages
|
||||
response.Messages = FilterMessages(response.Messages);
|
||||
agentResponse.Messages = FilterMessages(agentResponse.Messages);
|
||||
|
||||
Console.WriteLine("Guardrail Middleware - Filtered messages Post-Run");
|
||||
|
||||
return response;
|
||||
return agentResponse;
|
||||
|
||||
List<ChatMessage> FilterMessages(IEnumerable<ChatMessage> messages)
|
||||
{
|
||||
@@ -194,16 +173,13 @@ async Task<AgentResponse> GuardrailMiddleware(IEnumerable<ChatMessage> messages,
|
||||
// This middleware handles Human in the loop console interaction for any user approval required during function calling.
|
||||
async Task<AgentResponse> ConsolePromptingApprovalMiddleware(IEnumerable<ChatMessage> messages, AgentSession? session, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken)
|
||||
{
|
||||
AgentResponse response = await innerAgent.RunAsync(messages, session, options, cancellationToken);
|
||||
AgentResponse agentResponse = await innerAgent.RunAsync(messages, session, options, cancellationToken);
|
||||
|
||||
// For simplicity, we are assuming here that only function approvals are pending.
|
||||
List<ToolApprovalRequestContent> approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType<ToolApprovalRequestContent>().ToList();
|
||||
List<ToolApprovalRequestContent> approvalRequests = agentResponse.Messages.SelectMany(m => m.Contents).OfType<ToolApprovalRequestContent>().ToList();
|
||||
|
||||
while (approvalRequests.Count > 0)
|
||||
{
|
||||
// Ask the user to approve each function call request.
|
||||
// Pass the user input responses back to the agent for further processing.
|
||||
response.Messages = approvalRequests
|
||||
agentResponse.Messages = approvalRequests
|
||||
.ConvertAll(functionApprovalRequest =>
|
||||
{
|
||||
Console.WriteLine($"The agent would like to invoke the following function, please reply Y to approve: Name {((FunctionCallContent)functionApprovalRequest.ToolCall).Name}");
|
||||
@@ -211,13 +187,22 @@ async Task<AgentResponse> ConsolePromptingApprovalMiddleware(IEnumerable<ChatMes
|
||||
return new ChatMessage(ChatRole.User, [functionApprovalRequest.CreateResponse(approved)]);
|
||||
});
|
||||
|
||||
response = await innerAgent.RunAsync(response.Messages, session, options, cancellationToken);
|
||||
agentResponse = await innerAgent.RunAsync(agentResponse.Messages, session, options, cancellationToken);
|
||||
|
||||
approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType<ToolApprovalRequestContent>().ToList();
|
||||
approvalRequests = agentResponse.Messages.SelectMany(m => m.Contents).OfType<ToolApprovalRequestContent>().ToList();
|
||||
}
|
||||
|
||||
return response;
|
||||
return agentResponse;
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(middlewareEnabledAgent.Name);
|
||||
internal partial class Program
|
||||
{
|
||||
[GeneratedRegex(@"\b\d{3}-\d{3}-\d{4}\b", RegexOptions.Compiled)]
|
||||
private static partial Regex MyRegex();
|
||||
|
||||
[GeneratedRegex(@"\b[\w\.-]+@[\w\.-]+\.\w+\b", RegexOptions.Compiled)]
|
||||
private static partial Regex EmailRegex();
|
||||
|
||||
[GeneratedRegex(@"\b[A-Z][a-z]+\s[A-Z][a-z]+\b", RegexOptions.Compiled)]
|
||||
private static partial Regex FullNameRegex();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
# Middleware with the Responses API
|
||||
|
||||
This sample demonstrates multiple middleware layers working together: PII filtering, guardrails, function invocation logging, and human-in-the-loop approval.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Agent-level run middleware (PII filtering, guardrail enforcement)
|
||||
- Function-level middleware (logging, result overrides)
|
||||
- Human-in-the-loop approval workflows for sensitive function calls
|
||||
- Using `.AsBuilder().Use()` to compose middleware
|
||||
- No server-side agent creation or cleanup required
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\Agent_Step12_Middleware
|
||||
```
|
||||
@@ -10,13 +10,12 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,153 @@
|
||||
// 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.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using SampleApp;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_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();
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create a ChatClientAgent with the options-based constructor to pass services.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(new ChatClientAgentOptions
|
||||
{
|
||||
Name = AssistantName,
|
||||
ChatOptions = new() { ModelId = deploymentName, Instructions = AssistantInstructions, Tools = serviceProvider.GetRequiredService<AgentPlugin>().AsAITools().ToList() }
|
||||
},
|
||||
services: serviceProvider);
|
||||
|
||||
// Invoke the agent and output the text result.
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
Console.WriteLine(await agent.RunAsync("Tell me current time and weather in Seattle.", session));
|
||||
|
||||
namespace SampleApp
|
||||
{
|
||||
/// <summary>
|
||||
/// The agent plugin that provides weather and current time information.
|
||||
/// </summary>
|
||||
internal sealed class AgentPlugin
|
||||
{
|
||||
private readonly WeatherProvider _weatherProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentPlugin"/> class.
|
||||
/// </summary>
|
||||
/// <param name="weatherProvider">The weather provider to get weather information.</param>
|
||||
public AgentPlugin(WeatherProvider weatherProvider)
|
||||
{
|
||||
this._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 this._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)
|
||||
{
|
||||
CurrentTimeProvider 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);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class WeatherProvider
|
||||
{
|
||||
private readonly string _weatherSummary = "cloudy with a high of 15°C";
|
||||
|
||||
/// <summary>
|
||||
/// The weather provider that returns weather information.
|
||||
/// </summary>
|
||||
/// <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 {this._weatherSummary}.";
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class CurrentTimeProvider
|
||||
{
|
||||
private readonly TimeProvider _timeProvider = TimeProvider.System;
|
||||
|
||||
/// <summary>
|
||||
/// Provides the current date and time.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This class returns the current date and time using the system's clock.
|
||||
/// </remarks>
|
||||
/// <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 this._timeProvider.GetLocalNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Using Plugins with the Responses API
|
||||
|
||||
This sample shows how to use plugins with a `ChatClientAgent` using the Responses API directly, with dependency injection for plugin services.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Creating plugin classes with injected dependencies
|
||||
- Registering services and building a service provider
|
||||
- Passing `services` to the `ChatClientAgent` via the options-based constructor
|
||||
- Using `AIFunctionFactory` to expose plugin methods as AI tools
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -9,7 +9,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,61 +1,31 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use Code Interpreter Tool with AI Agents.
|
||||
// This sample shows how to use Code Interpreter Tool with AIProjectClient.AsAIAgent(...).
|
||||
|
||||
using System.Text;
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using OpenAI.Assistants;
|
||||
using OpenAI.Responses;
|
||||
|
||||
const string AgentInstructions = "You are a personal math tutor. When asked a math question, write and run code using the python tool to answer the question.";
|
||||
const string AgentName = "CoderAgent-RAPI";
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string AgentInstructions = "You are a personal math tutor. When asked a math question, write and run code using the python tool to answer the question.";
|
||||
const string AgentNameMEAI = "CoderAgent-MEAI";
|
||||
const string AgentNameNative = "CoderAgent-NATIVE";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Option 1 - Using HostedCodeInterpreterTool + AgentOptions (MEAI + AgentFramework)
|
||||
// Create the server side agent version
|
||||
AIAgent agentOption1 = await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: AgentNameMEAI,
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(
|
||||
deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: AgentName,
|
||||
tools: [new HostedCodeInterpreterTool() { Inputs = [] }]);
|
||||
|
||||
// Option 2 - Using PromptAgentDefinition SDK native type
|
||||
// Create the server side agent version
|
||||
AIAgent agentOption2 = await aiProjectClient.CreateAIAgentAsync(
|
||||
name: AgentNameNative,
|
||||
creationOptions: new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = AgentInstructions,
|
||||
Tools = {
|
||||
ResponseTool.CreateCodeInterpreterTool(
|
||||
new CodeInterpreterToolContainer(
|
||||
CodeInterpreterToolContainerConfiguration.CreateAutomaticContainerConfiguration(fileIds: [])
|
||||
)
|
||||
),
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Either invoke option1 or option2 agent, should have same result
|
||||
// Option 1
|
||||
AgentResponse response = await agentOption1.RunAsync("I need to solve the equation sin(x) + x^2 = 42");
|
||||
|
||||
// Option 2
|
||||
// AgentResponse response = await agentOption2.RunAsync("I need to solve the equation sin(x) + x^2 = 42");
|
||||
AgentResponse response = await agent.RunAsync("I need to solve the equation sin(x) + x^2 = 42");
|
||||
|
||||
// Get the CodeInterpreterToolCallContent
|
||||
CodeInterpreterToolCallContent? toolCallContent = response.Messages.SelectMany(m => m.Contents).OfType<CodeInterpreterToolCallContent>().FirstOrDefault();
|
||||
@@ -87,7 +57,3 @@ foreach (AIAnnotation annotation in response.Messages.SelectMany(m => m.Contents
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agentOption1.Name);
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agentOption2.Name);
|
||||
@@ -0,0 +1,28 @@
|
||||
# Code Interpreter with the Responses API
|
||||
|
||||
This sample shows how to use the Code Interpreter tool with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Using `HostedCodeInterpreterTool` with `ChatClientAgent`
|
||||
- Extracting code input and output from agent responses
|
||||
- Handling code interpreter annotations and file citations
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -29,5 +29,5 @@
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
|
Before Width: | Height: | Size: 2.5 MiB After Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 2.3 MiB After Width: | Height: | Size: 2.3 MiB |
@@ -1,11 +1,11 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use Computer Use Tool with AI Agents.
|
||||
// This sample shows how to use Computer Use Tool with a ChatClientAgent.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
@@ -15,59 +15,32 @@ internal sealed class Program
|
||||
{
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "computer-use-preview";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
const string AgentInstructions = @"
|
||||
You are a computer automation assistant.
|
||||
|
||||
Be direct and efficient. When you reach the search results page, read and describe the actual search result titles and descriptions you can see.
|
||||
";
|
||||
|
||||
const string AgentNameMEAI = "ComputerAgent-MEAI";
|
||||
const string AgentNameNative = "ComputerAgent-NATIVE";
|
||||
const string AgentName = "ComputerAgent-RAPI";
|
||||
|
||||
// Option 1 - Using ComputerUseTool + AgentOptions (MEAI + AgentFramework)
|
||||
// Create AIAgent directly
|
||||
AIAgent agentOption1 = await aiProjectClient.CreateAIAgentAsync(
|
||||
name: AgentNameMEAI,
|
||||
model: deploymentName,
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "computer-use-preview";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create a AIAgent with ComputerUseTool.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: AgentName,
|
||||
description: "Computer automation agent with screen interaction capabilities.",
|
||||
tools: [
|
||||
ResponseTool.CreateComputerTool(ComputerToolEnvironment.Browser, 1026, 769).AsAITool(),
|
||||
FoundryAITool.CreateComputerTool(ComputerToolEnvironment.Browser, 1026, 769),
|
||||
]);
|
||||
|
||||
// Option 2 - Using PromptAgentDefinition SDK native type
|
||||
// Create the server side agent version
|
||||
AIAgent agentOption2 = await aiProjectClient.CreateAIAgentAsync(
|
||||
name: AgentNameNative,
|
||||
creationOptions: new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = AgentInstructions,
|
||||
Tools = { ResponseTool.CreateComputerTool(
|
||||
environment: new ComputerToolEnvironment("windows"),
|
||||
displayWidth: 1026,
|
||||
displayHeight: 769) }
|
||||
})
|
||||
);
|
||||
|
||||
// Either invoke option1 or option2 agent, should have same result
|
||||
// Option 1
|
||||
await InvokeComputerUseAgentAsync(agentOption1);
|
||||
|
||||
// Option 2
|
||||
//await InvokeComputerUseAgentAsync(agentOption2);
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agentOption1.Name);
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agentOption2.Name);
|
||||
await InvokeComputerUseAgentAsync(agent);
|
||||
}
|
||||
|
||||
private static async Task InvokeComputerUseAgentAsync(AIAgent agent)
|
||||
@@ -94,10 +67,8 @@ internal sealed class Program
|
||||
// Initial request with screenshot - start with Bing search page
|
||||
Console.WriteLine("Starting computer automation session (initial screenshot: cua_browser_search.png)...");
|
||||
|
||||
// IMPORTANT: Computer-use with the Azure Agents API differs from the vanilla OpenAI Responses API.
|
||||
// The Azure Agents API rejects requests that include previous_response_id alongside
|
||||
// computer_call_output items. To work around this, each call uses a fresh session (avoiding
|
||||
// previous_response_id) and re-sends the full conversation context as input items instead.
|
||||
// We use PreviousResponseId to chain calls, sending only the new computer_call_output items
|
||||
// instead of re-sending the full context.
|
||||
AgentSession session = await agent.CreateSessionAsync();
|
||||
AgentResponse response = await agent.RunAsync(message, session: session, options: runOptions);
|
||||
|
||||
@@ -161,31 +132,15 @@ internal sealed class Program
|
||||
|
||||
Console.WriteLine("Sending action result back to agent...");
|
||||
|
||||
// Build the follow-up messages with full conversation context.
|
||||
// The Azure Agents API rejects previous_response_id when computer_call_output items are
|
||||
// present, so we must re-send all prior output items (reasoning, computer_call, etc.)
|
||||
// as input items alongside the computer_call_output to maintain conversation continuity.
|
||||
List<ChatMessage> followUpMessages = [];
|
||||
|
||||
// Re-send all response output items as an assistant message so the API has full context
|
||||
List<AIContent> priorOutputContents = response.Messages
|
||||
.SelectMany(m => m.Contents)
|
||||
.ToList();
|
||||
followUpMessages.Add(new ChatMessage(ChatRole.Assistant, priorOutputContents));
|
||||
|
||||
// Add the computer_call_output as a user message
|
||||
// Send only the computer_call_output — the session carries PreviousResponseId for context continuity.
|
||||
AIContent callOutput = new()
|
||||
{
|
||||
RawRepresentation = new ComputerCallOutputResponseItem(
|
||||
currentCallId,
|
||||
output: ComputerCallOutput.CreateScreenshotOutput(new BinaryData(screenInfo.ImageBytes), "image/png"))
|
||||
};
|
||||
followUpMessages.Add(new ChatMessage(ChatRole.User, [callOutput]));
|
||||
|
||||
// Create a fresh session so ConversationId does not carry over a previous_response_id.
|
||||
// Without this, the Azure Agents API returns an error when computer_call_output is present.
|
||||
session = await agent.CreateSessionAsync();
|
||||
response = await agent.RunAsync(followUpMessages, session: session, options: runOptions);
|
||||
response = await agent.RunAsync([new ChatMessage(ChatRole.User, [callOutput])], session: session, options: runOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Computer Use with the Responses API
|
||||
|
||||
This sample shows how to use the Computer Use tool with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Using `FoundryAITool.CreateComputerTool()` with `ChatClientAgent`
|
||||
- Processing computer call actions (click, type, key press)
|
||||
- Managing the computer use interaction loop with screenshots
|
||||
- Handling the Azure Agents API workaround for `previous_response_id` with `computer_call_output`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="computer-use-preview"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -9,7 +9,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,22 +1,20 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use File Search Tool with AI Agents.
|
||||
// This sample shows how to use File Search Tool with a ChatClientAgent.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using OpenAI.Assistants;
|
||||
using OpenAI.Files;
|
||||
using OpenAI.Responses;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string AgentInstructions = "You are a helpful assistant that can search through uploaded files to answer questions.";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
// We need the AIProjectClient to upload files and create vector stores.
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
@@ -52,8 +50,11 @@ var vectorStoreResult = await vectorStoresClient.CreateVectorStoreAsync(
|
||||
string vectorStoreId = vectorStoreResult.Value.Id;
|
||||
Console.WriteLine($"Created vector store, vector store ID: {vectorStoreId}");
|
||||
|
||||
AIAgent agent = await CreateAgentWithMEAI();
|
||||
// AIAgent agent = await CreateAgentWithNativeSDK();
|
||||
// Create a AIAgent with HostedFileSearchTool.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: "FileSearchAgent-RAPI",
|
||||
tools: [new HostedFileSearchTool() { Inputs = [new HostedVectorStoreContent(vectorStoreId)] }]);
|
||||
|
||||
// Run the agent
|
||||
Console.WriteLine("\n--- Running File Search Agent ---");
|
||||
@@ -73,39 +74,9 @@ foreach (AIAnnotation annotation in response.Messages.SelectMany(m => m.Contents
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
// Cleanup file resources.
|
||||
Console.WriteLine("\n--- Cleanup ---");
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
await vectorStoresClient.DeleteVectorStoreAsync(vectorStoreId);
|
||||
await filesClient.DeleteFileAsync(uploadedFile.Id);
|
||||
File.Delete(searchFilePath);
|
||||
Console.WriteLine("Cleanup completed successfully.");
|
||||
|
||||
// --- Agent Creation Options ---
|
||||
|
||||
#pragma warning disable CS8321 // Local function is declared but never used
|
||||
// Option 1 - Using HostedFileSearchTool (MEAI + AgentFramework)
|
||||
async Task<AIAgent> CreateAgentWithMEAI()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: "FileSearchAgent-MEAI",
|
||||
instructions: AgentInstructions,
|
||||
tools: [new HostedFileSearchTool() { Inputs = [new HostedVectorStoreContent(vectorStoreId)] }]);
|
||||
}
|
||||
|
||||
// Option 2 - Using PromptAgentDefinition with ResponseTool.CreateFileSearchTool (Native SDK)
|
||||
async Task<AIAgent> CreateAgentWithNativeSDK()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
name: "FileSearchAgent-NATIVE",
|
||||
creationOptions: new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = AgentInstructions,
|
||||
Tools = {
|
||||
ResponseTool.CreateFileSearchTool(vectorStoreIds: [vectorStoreId])
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# File Search with the Responses API
|
||||
|
||||
This sample shows how to use the File Search tool with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Uploading files and creating vector stores via `AIProjectClient`
|
||||
- Using `HostedFileSearchTool` with `ChatClientAgent`
|
||||
- Handling file citation annotations in agent responses
|
||||
- Cleaning up file resources after use
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -6,15 +6,14 @@
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<NoWarn>$(NoWarn);IDE0059</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -6,16 +6,32 @@ using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using OpenAI.Responses;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
// Warning: DefaultAzureCredential is intended for simplicity in development. For production scenarios, consider using a more specific credential.
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
const string AgentInstructions = "You are a helpful assistant that can use the countries API to retrieve information about countries by their currency code.";
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// A simple OpenAPI specification for the REST Countries API
|
||||
const string CountriesOpenApiSpec = """
|
||||
AITool openApiTool = FoundryAITool.CreateOpenApiTool(CreateOpenAPIFunctionDefinition());
|
||||
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: "OpenAPIToolsAgent",
|
||||
tools: [openApiTool]);
|
||||
|
||||
// Run the agent with a question about countries
|
||||
Console.WriteLine(await agent.RunAsync("What countries use the Euro (EUR) as their currency? Please list them."));
|
||||
|
||||
OpenApiFunctionDefinition CreateOpenAPIFunctionDefinition()
|
||||
{
|
||||
// A simple OpenAPI specification for the REST Countries API
|
||||
const string CountriesOpenApiSpec = """
|
||||
{
|
||||
"openapi": "3.1.0",
|
||||
"info": {
|
||||
@@ -68,49 +84,12 @@ const string CountriesOpenApiSpec = """
|
||||
}
|
||||
""";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create the OpenAPI function definition
|
||||
var openApiFunction = new OpenApiFunctionDefinition(
|
||||
"get_countries",
|
||||
BinaryData.FromString(CountriesOpenApiSpec),
|
||||
new OpenAPIAnonymousAuthenticationDetails())
|
||||
{
|
||||
Description = "Retrieve information about countries by currency code"
|
||||
};
|
||||
|
||||
AIAgent agent = await CreateAgentWithMEAI();
|
||||
// AIAgent agent = await CreateAgentWithNativeSDK();
|
||||
|
||||
// Run the agent with a question about countries
|
||||
Console.WriteLine(await agent.RunAsync("What countries use the Euro (EUR) as their currency? Please list them."));
|
||||
|
||||
// Cleanup by deleting the agent
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
|
||||
// --- Agent Creation Options ---
|
||||
|
||||
// Option 1 - Using AsAITool wrapping for OpenApiTool (MEAI + AgentFramework)
|
||||
async Task<AIAgent> CreateAgentWithMEAI()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: "OpenAPIToolsAgent-MEAI",
|
||||
instructions: AgentInstructions,
|
||||
tools: [((ResponseTool)AgentTool.CreateOpenApiTool(openApiFunction)).AsAITool()]);
|
||||
}
|
||||
|
||||
// Option 2 - Using PromptAgentDefinition with AgentTool.CreateOpenApiTool (Native SDK)
|
||||
async Task<AIAgent> CreateAgentWithNativeSDK()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
name: "OpenAPIToolsAgent-NATIVE",
|
||||
creationOptions: new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = AgentInstructions,
|
||||
Tools = { (ResponseTool)AgentTool.CreateOpenApiTool(openApiFunction) }
|
||||
})
|
||||
);
|
||||
// Create the OpenAPI function definition
|
||||
return new(
|
||||
"get_countries",
|
||||
BinaryData.FromString(CountriesOpenApiSpec),
|
||||
new OpenAPIAnonymousAuthenticationDetails())
|
||||
{
|
||||
Description = "Retrieve information about countries by currency code"
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# OpenAPI Tools with the Responses API
|
||||
|
||||
This sample shows how to use OpenAPI tools with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Defining an OpenAPI specification inline
|
||||
- Creating an `OpenAPIFunctionDefinition` for the REST Countries API
|
||||
- Using `FoundryAITool.CreateOpenApiTool()` with `ChatClientAgent`
|
||||
- Server-side execution of OpenAPI tool calls
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -9,7 +9,6 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.AI.Projects" />
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use Bing Custom Search Tool with AI Agents.
|
||||
// This sample shows how to use Bing Custom Search Tool with a ChatClientAgent.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using OpenAI.Responses;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
string connectionId = Environment.GetEnvironmentVariable("AZURE_AI_CUSTOM_SEARCH_CONNECTION_ID") ?? throw new InvalidOperationException("AZURE_AI_CUSTOM_SEARCH_CONNECTION_ID is not set.");
|
||||
string instanceName = Environment.GetEnvironmentVariable("AZURE_AI_CUSTOM_SEARCH_INSTANCE_NAME") ?? throw new InvalidOperationException("AZURE_AI_CUSTOM_SEARCH_INSTANCE_NAME is not set.");
|
||||
|
||||
@@ -18,19 +16,24 @@ const string AgentInstructions = """
|
||||
Use the available Bing Custom Search tools to answer questions and perform tasks.
|
||||
""";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
// Bing Custom Search tool parameters
|
||||
BingCustomSearchToolOptions bingCustomSearchToolParameters = new([
|
||||
new BingCustomSearchConfiguration(connectionId, instanceName)
|
||||
]);
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Bing Custom Search tool parameters shared by both options
|
||||
BingCustomSearchToolOptions bingCustomSearchToolParameters = new([
|
||||
new BingCustomSearchConfiguration(connectionId, instanceName)
|
||||
]);
|
||||
|
||||
AIAgent agent = await CreateAgentWithMEAIAsync();
|
||||
// AIAgent agent = await CreateAgentWithNativeSDKAsync();
|
||||
// Create a AIAgent with Bing Custom Search tool.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: "BingCustomSearchAgent-RAPI",
|
||||
tools: [FoundryAITool.CreateBingCustomSearchTool(bingCustomSearchToolParameters)]);
|
||||
|
||||
Console.WriteLine($"Created agent: {agent.Name}");
|
||||
|
||||
@@ -42,35 +45,3 @@ foreach (var message in response.Messages)
|
||||
{
|
||||
Console.WriteLine(message.Text);
|
||||
}
|
||||
|
||||
// Cleanup by deleting the agent
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
Console.WriteLine($"\nDeleted agent: {agent.Name}");
|
||||
|
||||
// --- Agent Creation Options ---
|
||||
|
||||
// Option 1 - Using AsAITool wrapping for the ResponseTool returned by AgentTool.CreateBingCustomSearchTool (MEAI + AgentFramework)
|
||||
async Task<AIAgent> CreateAgentWithMEAIAsync()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: "BingCustomSearchAgent-MEAI",
|
||||
instructions: AgentInstructions,
|
||||
tools: [((ResponseTool)AgentTool.CreateBingCustomSearchTool(bingCustomSearchToolParameters)).AsAITool()]);
|
||||
}
|
||||
|
||||
// Option 2 - Using PromptAgentDefinition with AgentTool.CreateBingCustomSearchTool (Native SDK)
|
||||
async Task<AIAgent> CreateAgentWithNativeSDKAsync()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
name: "BingCustomSearchAgent-NATIVE",
|
||||
creationOptions: new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = AgentInstructions,
|
||||
Tools = {
|
||||
(ResponseTool)AgentTool.CreateBingCustomSearchTool(bingCustomSearchToolParameters),
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
# Bing Custom Search with the Responses API
|
||||
|
||||
This sample shows how to use the Bing Custom Search tool with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Configuring `BingCustomSearchToolParameters` with connection ID and instance name
|
||||
- Using `FoundryAITool.CreateBingCustomSearchTool()` with `ChatClientAgent`
|
||||
- Processing search results from agent responses
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
- Bing Custom Search resource configured with a connection ID
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
$env:AZURE_AI_CUSTOM_SEARCH_CONNECTION_ID="your-connection-id" # The full ARM resource URI, e.g., "/subscriptions/.../connections/your-bing-connection"
|
||||
$env:AZURE_AI_CUSTOM_SEARCH_INSTANCE_NAME="your-instance-name" # The Bing Custom Search configuration name (from Azure portal)
|
||||
```
|
||||
|
||||
### Finding the connection ID and instance name
|
||||
|
||||
- **Connection ID** (`AZURE_AI_CUSTOM_SEARCH_CONNECTION_ID`): The full ARM resource URI including the `/projects/<name>/connections/<connection-name>` segment. Find the connection name in your Foundry project under **Management center** → **Connected resources**.
|
||||
- **Instance Name** (`AZURE_AI_CUSTOM_SEARCH_INSTANCE_NAME`): The **configuration name** from your Bing Custom Search resource (Azure portal → your Bing Custom Search resource → **Configurations**). This is _not_ the Azure resource name or the connection name — it's the name of the specific search configuration that defines which domains/sites to search against.
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,15 +1,13 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use SharePoint Grounding Tool with AI Agents.
|
||||
// This sample shows how to use SharePoint Grounding Tool with a ChatClientAgent.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using OpenAI.Responses;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_FOUNDRY_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
string sharepointConnectionId = Environment.GetEnvironmentVariable("SHAREPOINT_PROJECT_CONNECTION_ID") ?? throw new InvalidOperationException("SHAREPOINT_PROJECT_CONNECTION_ID is not set.");
|
||||
|
||||
const string AgentInstructions = """
|
||||
@@ -17,18 +15,23 @@ const string AgentInstructions = """
|
||||
Use the available SharePoint tools to answer questions and perform tasks.
|
||||
""";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
// Create SharePoint tool options with project connection
|
||||
var sharepointOptions = new SharePointGroundingToolOptions();
|
||||
sharepointOptions.ProjectConnections.Add(new ToolProjectConnection(sharepointConnectionId));
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create SharePoint tool options with project connection
|
||||
var sharepointOptions = new SharePointGroundingToolOptions();
|
||||
sharepointOptions.ProjectConnections.Add(new ToolProjectConnection(sharepointConnectionId));
|
||||
|
||||
AIAgent agent = await CreateAgentWithMEAIAsync();
|
||||
// AIAgent agent = await CreateAgentWithNativeSDKAsync();
|
||||
// Create a AIAgent with SharePoint tool.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: "SharePointAgent-RAPI",
|
||||
tools: [FoundryAITool.CreateSharepointTool(sharepointOptions)]);
|
||||
|
||||
Console.WriteLine($"Created agent: {agent.Name}");
|
||||
|
||||
@@ -52,33 +55,3 @@ foreach (var message in response.Messages)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup by agent name removes the agent version created.
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
Console.WriteLine($"\nDeleted agent: {agent.Name}");
|
||||
|
||||
// --- Agent Creation Options ---
|
||||
|
||||
// Option 1 - Using AgentTool.CreateSharepointTool + AsAITool() (MEAI + AgentFramework)
|
||||
async Task<AIAgent> CreateAgentWithMEAIAsync()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: "SharePointAgent-MEAI",
|
||||
instructions: AgentInstructions,
|
||||
tools: [((ResponseTool)AgentTool.CreateSharepointTool(sharepointOptions)).AsAITool()]);
|
||||
}
|
||||
|
||||
// Option 2 - Using PromptAgentDefinition SDK native type
|
||||
async Task<AIAgent> CreateAgentWithNativeSDKAsync()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
name: "SharePointAgent-NATIVE",
|
||||
creationOptions: new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = AgentInstructions,
|
||||
Tools = { AgentTool.CreateSharepointTool(sharepointOptions) }
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# SharePoint Grounding with the Responses API
|
||||
|
||||
This sample shows how to use the SharePoint Grounding tool with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Configuring `SharePointGroundingToolOptions` with project connections
|
||||
- Using `FoundryAITool.CreateSharepointTool()` with `ChatClientAgent`
|
||||
- Displaying grounding annotations from agent responses
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
- SharePoint connection configured in your Microsoft Foundry project
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
$env:SHAREPOINT_PROJECT_CONNECTION_ID="your-sharepoint-connection-id" # The full ARM resource URI, e.g., "/subscriptions/.../connections/SharepointTestTool"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use Microsoft Fabric Tool with a ChatClientAgent.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
|
||||
string fabricConnectionId = Environment.GetEnvironmentVariable("FABRIC_PROJECT_CONNECTION_ID") ?? throw new InvalidOperationException("FABRIC_PROJECT_CONNECTION_ID is not set.");
|
||||
|
||||
const string AgentInstructions = "You are a helpful assistant with access to Microsoft Fabric data. Answer questions based on data available through your Fabric connection.";
|
||||
|
||||
// Configure Microsoft Fabric tool options with project connection
|
||||
var fabricToolOptions = new FabricDataAgentToolOptions();
|
||||
fabricToolOptions.ProjectConnections.Add(new ToolProjectConnection(fabricConnectionId));
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create a AIAgent with Microsoft Fabric tool.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: "FabricAgent-RAPI",
|
||||
tools: [FoundryAITool.CreateMicrosoftFabricTool(fabricToolOptions)]);
|
||||
|
||||
Console.WriteLine($"Created agent: {agent.Name}");
|
||||
|
||||
// Run the agent with a sample query
|
||||
AgentResponse response = await agent.RunAsync("What data is available in the connected Fabric workspace?");
|
||||
|
||||
Console.WriteLine("\n=== Agent Response ===");
|
||||
foreach (var message in response.Messages)
|
||||
{
|
||||
Console.WriteLine(message.Text);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# Microsoft Fabric with the Responses API
|
||||
|
||||
This sample shows how to use the Microsoft Fabric tool with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Configuring `FabricDataAgentToolOptions` with project connections
|
||||
- Using `FoundryAITool.CreateMicrosoftFabricTool()` with `ChatClientAgent`
|
||||
- Querying data available through a Fabric connection
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
- Microsoft Fabric connection configured in your Microsoft Foundry project
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
$env:FABRIC_PROJECT_CONNECTION_ID="your-fabric-connection-id" # The full ARM resource URI, e.g., "/subscriptions/.../connections/FabricTestTool"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample shows how to use the Web Search Tool with a ChatClientAgent.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
const string AgentInstructions = "You are a helpful assistant that can search the web to find current information and answer questions accurately.";
|
||||
const string AgentName = "WebSearchAgent-RAPI";
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create a AIAgent with HostedWebSearchTool.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: AgentName,
|
||||
tools: [new HostedWebSearchTool()]);
|
||||
|
||||
AgentResponse response = await agent.RunAsync("What's the weather today in Seattle?");
|
||||
|
||||
// Get the text response
|
||||
Console.WriteLine($"Response: {response.Text}");
|
||||
|
||||
// Getting any annotations/citations generated by the web search tool
|
||||
foreach (AIAnnotation annotation in response.Messages.SelectMany(m => m.Contents).SelectMany(c => c.Annotations ?? []))
|
||||
{
|
||||
Console.WriteLine($"Annotation: {annotation}");
|
||||
if (annotation.RawRepresentation is UriCitationMessageAnnotation urlCitation)
|
||||
{
|
||||
Console.WriteLine($$"""
|
||||
Title: {{urlCitation.Title}}
|
||||
URL: {{urlCitation.Uri}}
|
||||
""");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# Web Search with the Responses API
|
||||
|
||||
This sample shows how to use the Web Search tool with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Using `HostedWebSearchTool` with `ChatClientAgent`
|
||||
- Processing web search citations and annotations
|
||||
- Extracting URL citation details (title, URL) from responses
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI\Microsoft.Agents.AI.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -9,6 +9,8 @@ using Azure.AI.Projects;
|
||||
using Azure.AI.Projects.Agents;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Agents.AI.AzureAI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using OpenAI.Responses;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
@@ -22,27 +24,25 @@ const string AgentInstructions = """
|
||||
When a user shares personal details or preferences, remember them for future conversations.
|
||||
""";
|
||||
|
||||
const string AgentNameMEAI = "MemorySearchAgent-MEAI";
|
||||
const string AgentNameNative = "MemorySearchAgent-NATIVE";
|
||||
const string AgentName = "MemorySearchAgent";
|
||||
|
||||
// Scope identifies the user or context for memory isolation.
|
||||
// Using a unique user identifier ensures memories are private to that user.
|
||||
string userScope = $"user_{Environment.MachineName}";
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
DefaultAzureCredential credential = new();
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), credential);
|
||||
MemorySearchPreviewTool memorySearchTool = new(memoryStoreName, userScope) { UpdateDelayInSecs = 0 };
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create agent using the RAPI path with the MemorySearch tool
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: AgentName,
|
||||
tools: [FoundryAITool.FromResponseTool(memorySearchTool)]);
|
||||
|
||||
// Ensure the memory store exists and has memories to retrieve.
|
||||
await EnsureMemoryStoreAsync();
|
||||
|
||||
// Create the Memory Search tool configuration
|
||||
MemorySearchPreviewTool memorySearchTool = new(memoryStoreName, userScope) { UpdateDelayInSecs = 0 };
|
||||
|
||||
// Create agent using Option 1 (MEAI) or Option 2 (Native SDK)
|
||||
AIAgent agent = await CreateAgentWithMEAI();
|
||||
// AIAgent agent = await CreateAgentWithNativeSDK();
|
||||
|
||||
try
|
||||
{
|
||||
Console.WriteLine("Agent created with Memory Search tool. Starting conversation...\n");
|
||||
@@ -73,41 +73,14 @@ try
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup: Delete the agent and memory store.
|
||||
// Cleanup: Delete the memory store (no server-side agent to clean up in RAPI path).
|
||||
Console.WriteLine("\nCleaning up...");
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
Console.WriteLine("Agent deleted.");
|
||||
await aiProjectClient.MemoryStores.DeleteMemoryStoreAsync(memoryStoreName);
|
||||
Console.WriteLine("Memory store deleted.");
|
||||
}
|
||||
|
||||
#pragma warning disable CS8321 // Local function is declared but never used
|
||||
|
||||
// Option 1 - Using MemorySearchTool wrapped as MEAI AITool
|
||||
async Task<AIAgent> CreateAgentWithMEAI()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: AgentNameMEAI,
|
||||
instructions: AgentInstructions,
|
||||
tools: [((ResponseTool)memorySearchTool).AsAITool()]);
|
||||
}
|
||||
|
||||
// Option 2 - Using PromptAgentDefinition with MemorySearchTool (Native SDK)
|
||||
async Task<AIAgent> CreateAgentWithNativeSDK()
|
||||
{
|
||||
return await aiProjectClient.CreateAIAgentAsync(
|
||||
name: AgentNameNative,
|
||||
creationOptions: new AgentVersionCreationOptions(
|
||||
new PromptAgentDefinition(model: deploymentName)
|
||||
{
|
||||
Instructions = AgentInstructions,
|
||||
Tools = { memorySearchTool }
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Helpers — kept at the bottom so the main agent flow above stays clean.
|
||||
|
||||
async Task EnsureMemoryStoreAsync()
|
||||
{
|
||||
Console.WriteLine($"Creating memory store '{memoryStoreName}'...");
|
||||
@@ -123,19 +96,37 @@ async Task EnsureMemoryStoreAsync()
|
||||
Console.WriteLine("Memory store created.");
|
||||
}
|
||||
|
||||
// Explicitly add memories from a simulated prior conversation.
|
||||
Console.WriteLine("Storing memories from a prior conversation...");
|
||||
MemoryUpdateOptions memoryOptions = new(userScope) { UpdateDelay = 0 };
|
||||
memoryOptions.Items.Add(ResponseItem.CreateUserMessageItem("My name is Alice and I love programming in C#."));
|
||||
memoryOptions.Items.Add(ResponseItem.CreateUserMessageItem("My name is Alice and I prefer C#."));
|
||||
|
||||
MemoryUpdateResult updateResult = await aiProjectClient.MemoryStores.WaitForMemoriesUpdateAsync(
|
||||
memoryStoreName: memoryStoreName,
|
||||
pollingInterval: 500,
|
||||
options: memoryOptions);
|
||||
options: memoryOptions,
|
||||
pollingInterval: 500);
|
||||
|
||||
if (updateResult.Status == MemoryStoreUpdateStatus.Failed)
|
||||
{
|
||||
throw new InvalidOperationException($"Memory update failed: {updateResult.ErrorDetails}");
|
||||
}
|
||||
|
||||
Console.WriteLine($"Memory update completed (status: {updateResult.Status}).\n");
|
||||
Console.WriteLine($"Memory update completed (status: {updateResult.Status}).");
|
||||
|
||||
// Quick verification that memories are searchable.
|
||||
Console.WriteLine("Verifying stored memories...");
|
||||
MemorySearchOptions searchOptions = new(userScope)
|
||||
{
|
||||
Items = { ResponseItem.CreateUserMessageItem("What are Alice's preferences?") }
|
||||
};
|
||||
MemoryStoreSearchResponse searchResult = await aiProjectClient.MemoryStores.SearchMemoriesAsync(
|
||||
memoryStoreName: memoryStoreName,
|
||||
options: searchOptions);
|
||||
|
||||
foreach (var memory in searchResult.Memories)
|
||||
{
|
||||
Console.WriteLine($" - {memory.MemoryItem.Content}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
# Memory Search with the Responses API
|
||||
|
||||
This sample demonstrates how to use the Memory Search tool with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Configuring `MemorySearchPreviewTool` with a memory store and user scope
|
||||
- Using memory search for cross-conversation recall
|
||||
- Inspecting `MemorySearchToolCallResponseItem` results
|
||||
- User profile persistence across conversations
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
- A memory store created beforehand via Azure Portal or Python SDK
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
$env:AZURE_AI_MEMORY_STORE_ID="your-memory-store-name"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Identity" />
|
||||
<PackageReference Include="ModelContextProtocol" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.AzureAI\Microsoft.Agents.AI.AzureAI.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,24 +1,20 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use a local MCP (Model Context Protocol) client with Azure Foundry Agents.
|
||||
// The MCP tools are resolved locally by connecting directly to the MCP server via HTTP,
|
||||
// and then passed to the Foundry agent as client-side tools.
|
||||
// This sample uses the Microsoft Learn MCP endpoint to search documentation.
|
||||
// This sample demonstrates how to wrap MCP tools with a DelegatingAIFunction to add custom behavior (e.g., logging).
|
||||
// Compare with Step09 which shows basic MCP tool usage without wrapping.
|
||||
// The LoggingMcpTool pattern is useful for diagnostics, metering, or adding approval logic around tool calls.
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
using Microsoft.Agents.AI;
|
||||
using Microsoft.Extensions.AI;
|
||||
using ModelContextProtocol.Client;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
using SampleApp;
|
||||
|
||||
const string AgentInstructions = "You are a helpful assistant that can help with Microsoft documentation questions. Use the Microsoft Learn MCP tool to search for documentation.";
|
||||
const string AgentName = "DocsAgent";
|
||||
const string AgentName = "DocsAgent-RAPI";
|
||||
|
||||
// Connect to the MCP server locally via HTTP (Streamable HTTP transport).
|
||||
// The MCP server is hosted at Microsoft Learn and provides documentation search capabilities.
|
||||
Console.WriteLine("Connecting to MCP server at https://learn.microsoft.com/api/mcp ...");
|
||||
|
||||
await using McpClient mcpClient = await McpClient.CreateAsync(new HttpClientTransport(new()
|
||||
@@ -34,53 +30,48 @@ Console.WriteLine($"MCP tools available: {string.Join(", ", mcpTools.Select(t =>
|
||||
// Wrap each MCP tool with a DelegatingAIFunction to log local invocations.
|
||||
List<AITool> wrappedTools = mcpTools.Select(tool => (AITool)new LoggingMcpTool(tool)).ToList();
|
||||
|
||||
// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
// Create the agent with the locally-resolved MCP tools.
|
||||
AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
|
||||
model: deploymentName,
|
||||
name: AgentName,
|
||||
// Create a AIAgent with the locally-resolved MCP tools.
|
||||
AIAgent agent = aiProjectClient.AsAIAgent(deploymentName,
|
||||
instructions: AgentInstructions,
|
||||
name: AgentName,
|
||||
tools: wrappedTools);
|
||||
|
||||
Console.WriteLine($"Agent '{agent.Name}' created successfully.");
|
||||
|
||||
try
|
||||
{
|
||||
// First query
|
||||
const string Prompt1 = "How does one create an Azure storage account using az cli?";
|
||||
Console.WriteLine($"\nUser: {Prompt1}\n");
|
||||
AgentResponse response1 = await agent.RunAsync(Prompt1);
|
||||
Console.WriteLine($"Agent: {response1}");
|
||||
// First query
|
||||
const string Prompt1 = "How does one create an Azure storage account using az cli?";
|
||||
Console.WriteLine($"\nUser: {Prompt1}\n");
|
||||
AgentResponse response1 = await agent.RunAsync(Prompt1);
|
||||
Console.WriteLine($"Agent: {response1}");
|
||||
|
||||
Console.WriteLine("\n=======================================\n");
|
||||
Console.WriteLine("\n=======================================\n");
|
||||
|
||||
// Second query
|
||||
const string Prompt2 = "What is Microsoft Agent Framework?";
|
||||
Console.WriteLine($"User: {Prompt2}\n");
|
||||
AgentResponse response2 = await agent.RunAsync(Prompt2);
|
||||
Console.WriteLine($"Agent: {response2}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup by removing the agent when done
|
||||
await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
|
||||
Console.WriteLine($"\nAgent '{agent.Name}' deleted.");
|
||||
}
|
||||
// Second query
|
||||
const string Prompt2 = "What is Microsoft Agent Framework?";
|
||||
Console.WriteLine($"User: {Prompt2}\n");
|
||||
AgentResponse response2 = await agent.RunAsync(Prompt2);
|
||||
Console.WriteLine($"Agent: {response2}");
|
||||
|
||||
/// <summary>
|
||||
/// Wraps an MCP tool to log when it is invoked locally,
|
||||
/// confirming that the MCP call is happening client-side.
|
||||
/// </summary>
|
||||
internal sealed class LoggingMcpTool(AIFunction innerFunction) : DelegatingAIFunction(innerFunction)
|
||||
namespace SampleApp
|
||||
{
|
||||
protected override ValueTask<object?> InvokeCoreAsync(AIFunctionArguments arguments, CancellationToken cancellationToken)
|
||||
/// <summary>
|
||||
/// Wraps an MCP tool to log when it is invoked locally,
|
||||
/// confirming that the MCP call is happening client-side.
|
||||
/// </summary>
|
||||
internal sealed class LoggingMcpTool(AIFunction innerFunction) : DelegatingAIFunction(innerFunction)
|
||||
{
|
||||
Console.WriteLine($" >> [LOCAL MCP] Invoking tool '{this.Name}' locally...");
|
||||
return base.InvokeCoreAsync(arguments, cancellationToken);
|
||||
protected override ValueTask<object?> InvokeCoreAsync(AIFunctionArguments arguments, CancellationToken cancellationToken)
|
||||
{
|
||||
Console.WriteLine($" >> [LOCAL MCP] Invoking tool '{this.Name}' locally...");
|
||||
return base.InvokeCoreAsync(arguments, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
# Local MCP with the Responses API
|
||||
|
||||
This sample demonstrates how to use a local MCP (Model Context Protocol) client with a `ChatClientAgent` using the Responses API directly.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Connecting to an MCP server via HTTP (Streamable HTTP transport)
|
||||
- Resolving MCP tools locally and wrapping them with logging
|
||||
- Using `DelegatingAIFunction` to add custom behavior to MCP tools
|
||||
- Passing locally-resolved MCP tools to `ChatClientAgent`
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Microsoft Foundry service endpoint and deployment configured
|
||||
- Azure CLI installed and authenticated (`az login`)
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
```powershell
|
||||
dotnet run
|
||||
```
|
||||
@@ -0,0 +1,81 @@
|
||||
# Getting started with Foundry Agents
|
||||
|
||||
These samples demonstrate how to use Azure AI Foundry with Agent Framework.
|
||||
|
||||
## Quick start
|
||||
|
||||
The simplest way to create a Foundry agent is using the `FoundryAgent` type directly:
|
||||
|
||||
```csharp
|
||||
FoundryAgent agent = new(
|
||||
new Uri(endpoint),
|
||||
new AzureCliCredential(),
|
||||
model: "gpt-4o-mini",
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "JokerAgent");
|
||||
|
||||
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate."));
|
||||
```
|
||||
|
||||
Or using the `AIProjectClient.AsAIAgent(...)` extensions:
|
||||
|
||||
```csharp
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
||||
|
||||
FoundryAgent agent = aiProjectClient.AsAIAgent(
|
||||
model: deploymentName,
|
||||
instructions: "You are good at telling jokes.",
|
||||
name: "JokerAgent");
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Foundry project endpoint
|
||||
- Azure CLI installed and authenticated
|
||||
|
||||
Set:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini"
|
||||
```
|
||||
|
||||
Some samples require extra tool-specific environment variables. See each sample for details.
|
||||
|
||||
## Samples
|
||||
|
||||
| Sample | Description |
|
||||
| --- | --- |
|
||||
| [FoundryAgent lifecycle](./Agent_Step00_FoundryAgentLifecycle/) | Create a FoundryAgent directly with endpoint and credentials |
|
||||
| [Basics (Responses API)](./Agent_Step01_Basics/) | Create and run an agent using AsAIAgent extensions |
|
||||
| [Multi-turn conversation](./Agent_Step02.1_MultiturnConversation/) | Multi-turn using sessions and response ID chaining |
|
||||
| [Multi-turn with server conversations](./Agent_Step02.2_MultiturnWithServerConversations/) | Server-side conversations visible in Foundry UI |
|
||||
| [Using function tools](./Agent_Step03_UsingFunctionTools/) | Function tools |
|
||||
| [Function tools with approvals](./Agent_Step04_UsingFunctionToolsWithApprovals/) | Human-in-the-loop approval |
|
||||
| [Structured output](./Agent_Step05_StructuredOutput/) | Structured output with JSON schema |
|
||||
| [Persisted conversations](./Agent_Step06_PersistedConversations/) | Persisting and resuming conversations |
|
||||
| [Observability](./Agent_Step07_Observability/) | OpenTelemetry observability |
|
||||
| [Dependency injection](./Agent_Step08_DependencyInjection/) | DI with a hosted service |
|
||||
| [Using MCP client as tools](./Agent_Step09_UsingMcpClientAsTools/) | MCP client tools |
|
||||
| [Using images](./Agent_Step10_UsingImages/) | Image multi-modality |
|
||||
| [Agent as function tool](./Agent_Step11_AsFunctionTool/) | Agent as a function tool for another |
|
||||
| [Middleware](./Agent_Step12_Middleware/) | Multiple middleware layers |
|
||||
| [Plugins](./Agent_Step13_Plugins/) | Plugins with dependency injection |
|
||||
| [Code interpreter](./Agent_Step14_CodeInterpreter/) | Code interpreter tool |
|
||||
| [Computer use](./Agent_Step15_ComputerUse/) | Computer use tool |
|
||||
| [File search](./Agent_Step16_FileSearch/) | File search tool |
|
||||
| [OpenAPI tools](./Agent_Step17_OpenAPITools/) | OpenAPI tools |
|
||||
| [Bing custom search](./Agent_Step18_BingCustomSearch/) | Bing Custom Search tool |
|
||||
| [SharePoint](./Agent_Step19_SharePoint/) | SharePoint grounding tool |
|
||||
| [Microsoft Fabric](./Agent_Step20_MicrosoftFabric/) | Microsoft Fabric tool |
|
||||
| [Web search](./Agent_Step21_WebSearch/) | Web search tool |
|
||||
| [Memory search](./Agent_Step22_MemorySearch/) | Memory search tool |
|
||||
| [Local MCP](./Agent_Step23_LocalMCP/) | Local MCP client with HTTP transport |
|
||||
|
||||
## Running the samples
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/AgentsWithFoundry
|
||||
dotnet run --project .\FoundryAgent_Step01
|
||||
```
|
||||
@@ -1,100 +0,0 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
// This sample demonstrates how to use Azure AI Foundry's Red Teaming service to assess
|
||||
// the safety and resilience of an AI model against adversarial attacks.
|
||||
//
|
||||
// It uses the RedTeam API from Azure.AI.Projects to run automated attack simulations
|
||||
// with various attack strategies (encoding, obfuscation, jailbreaks) across multiple
|
||||
// risk categories (Violence, HateUnfairness, Sexual, SelfHarm).
|
||||
//
|
||||
// For more details, see:
|
||||
// https://learn.microsoft.com/azure/ai-foundry/concepts/ai-red-teaming-agent
|
||||
|
||||
using Azure.AI.Projects;
|
||||
using Azure.Identity;
|
||||
|
||||
string endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
|
||||
string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
|
||||
|
||||
Console.WriteLine("=" + new string('=', 79));
|
||||
Console.WriteLine("RED TEAMING EVALUATION SAMPLE");
|
||||
Console.WriteLine("=" + new string('=', 79));
|
||||
Console.WriteLine();
|
||||
|
||||
// Initialize Azure credentials and clients
|
||||
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
||||
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
||||
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
||||
DefaultAzureCredential credential = new();
|
||||
AIProjectClient aiProjectClient = new(new Uri(endpoint), credential);
|
||||
|
||||
// Configure the target model for red teaming
|
||||
AzureOpenAIModelConfiguration targetConfig = new(deploymentName);
|
||||
|
||||
// Create the red team run configuration
|
||||
RedTeam redTeamConfig = new(targetConfig)
|
||||
{
|
||||
DisplayName = "FinancialAdvisor-RedTeam",
|
||||
ApplicationScenario = "A financial advisor assistant that provides general financial advice and information.",
|
||||
NumTurns = 3,
|
||||
RiskCategories =
|
||||
{
|
||||
RiskCategory.Violence,
|
||||
RiskCategory.HateUnfairness,
|
||||
RiskCategory.Sexual,
|
||||
RiskCategory.SelfHarm,
|
||||
},
|
||||
AttackStrategies =
|
||||
{
|
||||
AttackStrategy.Easy,
|
||||
AttackStrategy.Moderate,
|
||||
AttackStrategy.Jailbreak,
|
||||
},
|
||||
};
|
||||
|
||||
Console.WriteLine($"Target model: {deploymentName}");
|
||||
Console.WriteLine("Risk categories: Violence, HateUnfairness, Sexual, SelfHarm");
|
||||
Console.WriteLine("Attack strategies: Easy, Moderate, Jailbreak");
|
||||
Console.WriteLine($"Simulation turns: {redTeamConfig.NumTurns}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Submit the red team run to the service
|
||||
Console.WriteLine("Submitting red team run...");
|
||||
RedTeam redTeamRun = await aiProjectClient.RedTeams.CreateAsync(redTeamConfig, options: null);
|
||||
|
||||
Console.WriteLine($"Red team run created: {redTeamRun.Name}");
|
||||
Console.WriteLine($"Status: {redTeamRun.Status}");
|
||||
Console.WriteLine();
|
||||
|
||||
// Poll for completion
|
||||
Console.WriteLine("Waiting for red team run to complete (this may take several minutes)...");
|
||||
while (redTeamRun.Status != "Completed" && redTeamRun.Status != "Failed" && redTeamRun.Status != "Canceled")
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(15));
|
||||
redTeamRun = await aiProjectClient.RedTeams.GetAsync(redTeamRun.Name);
|
||||
Console.WriteLine($" Status: {redTeamRun.Status}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
if (redTeamRun.Status == "Completed")
|
||||
{
|
||||
Console.WriteLine("Red team run completed successfully!");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Results:");
|
||||
Console.WriteLine(new string('-', 80));
|
||||
Console.WriteLine($" Run name: {redTeamRun.Name}");
|
||||
Console.WriteLine($" Display name: {redTeamRun.DisplayName}");
|
||||
Console.WriteLine($" Status: {redTeamRun.Status}");
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Review the detailed results in the Azure AI Foundry portal:");
|
||||
Console.WriteLine($" {endpoint}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Red team run ended with status: {redTeamRun.Status}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(new string('=', 80));
|
||||
@@ -1,101 +0,0 @@
|
||||
# Red Teaming with Azure AI Foundry (Classic)
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This sample uses the **classic Azure AI Foundry** red teaming API (`/redTeams/runs`) via `Azure.AI.Projects`. Results are viewable in the classic Foundry portal experience. The **new Foundry** portal's red teaming feature uses a different evaluation-based API that is not yet available in the .NET SDK.
|
||||
|
||||
This sample demonstrates how to use Azure AI Foundry's Red Teaming service to assess the safety and resilience of an AI model against adversarial attacks.
|
||||
|
||||
## What this sample demonstrates
|
||||
|
||||
- Configuring a red team run targeting an Azure OpenAI model deployment
|
||||
- Using multiple `AttackStrategy` options (Easy, Moderate, Jailbreak)
|
||||
- Evaluating across `RiskCategory` categories (Violence, HateUnfairness, Sexual, SelfHarm)
|
||||
- Submitting a red team scan and polling for completion
|
||||
- Reviewing results in the Azure AI Foundry portal
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following prerequisites:
|
||||
|
||||
- .NET 10 SDK or later
|
||||
- Azure AI Foundry project (hub and project created)
|
||||
- Azure OpenAI deployment (e.g., gpt-4o or gpt-4o-mini)
|
||||
- Azure CLI installed and authenticated (for Azure credential authentication)
|
||||
|
||||
### Regional Requirements
|
||||
|
||||
Red teaming is only available in regions that support risk and safety evaluators:
|
||||
- **East US 2**, **Sweden Central**, **US North Central**, **France Central**, **Switzerland West**
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Set the following environment variables:
|
||||
|
||||
```powershell
|
||||
$env:AZURE_AI_PROJECT_ENDPOINT="https://your-project.services.ai.azure.com/api/projects/your-project" # Replace with your Azure Foundry project endpoint
|
||||
$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
|
||||
```
|
||||
|
||||
## Run the sample
|
||||
|
||||
Navigate to the sample directory and run:
|
||||
|
||||
```powershell
|
||||
cd dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming
|
||||
dotnet run
|
||||
```
|
||||
|
||||
## Expected behavior
|
||||
|
||||
The sample will:
|
||||
|
||||
1. Configure a `RedTeam` run targeting the specified model deployment
|
||||
2. Define risk categories and attack strategies
|
||||
3. Submit the scan to Azure AI Foundry's Red Teaming service
|
||||
4. Poll for completion (this may take several minutes)
|
||||
5. Display the run status and direct you to the Azure AI Foundry portal for detailed results
|
||||
|
||||
## Understanding Red Teaming
|
||||
|
||||
### Attack Strategies
|
||||
|
||||
| Strategy | Description |
|
||||
|----------|-------------|
|
||||
| Easy | Simple encoding/obfuscation attacks (ROT13, Leetspeak, etc.) |
|
||||
| Moderate | Moderate complexity attacks requiring an LLM for orchestration |
|
||||
| Jailbreak | Crafted prompts designed to bypass AI safeguards (UPIA) |
|
||||
|
||||
### Risk Categories
|
||||
|
||||
| Category | Description |
|
||||
|----------|-------------|
|
||||
| Violence | Content related to violence |
|
||||
| HateUnfairness | Hate speech or unfair content |
|
||||
| Sexual | Sexual content |
|
||||
| SelfHarm | Self-harm related content |
|
||||
|
||||
### Interpreting Results
|
||||
|
||||
- Results are available in the Azure AI Foundry portal (**classic view** — toggle at top-right) under the red teaming section
|
||||
- Lower Attack Success Rate (ASR) is better — target ASR < 5% for production
|
||||
- Review individual attack conversations to understand vulnerabilities
|
||||
|
||||
### Current Limitations
|
||||
|
||||
> [!NOTE]
|
||||
> - The .NET Red Teaming API (`Azure.AI.Projects`) currently supports targeting **model deployments only** via `AzureOpenAIModelConfiguration`. The `AzureAIAgentTarget` type exists in the SDK but is consumed by the **Evaluation Taxonomy** API (`/evaluationtaxonomies`), not by the Red Teaming API (`/redTeams/runs`).
|
||||
> - Agent-targeted red teaming with agent-specific risk categories (Prohibited actions, Sensitive data leakage, Task adherence) is documented in the [concept docs](https://learn.microsoft.com/azure/ai-foundry/concepts/ai-red-teaming-agent) but is not yet available via the public REST API or .NET SDK.
|
||||
> - Results from this API appear in the **classic** Azure AI Foundry portal view. The new Foundry portal uses a separate evaluation-based system with `eval_*` identifiers.
|
||||
|
||||
## Related Resources
|
||||
|
||||
- [Azure AI Red Teaming Agent](https://learn.microsoft.com/azure/ai-foundry/concepts/ai-red-teaming-agent)
|
||||
- [RedTeam .NET API Reference](https://learn.microsoft.com/dotnet/api/azure.ai.projects.redteam?view=azure-dotnet-preview)
|
||||
- [Risk and Safety Evaluations](https://learn.microsoft.com/azure/ai-foundry/concepts/evaluation-metrics-built-in#risk-and-safety-evaluators)
|
||||
|
||||
## Next Steps
|
||||
|
||||
After running red teaming:
|
||||
1. Review attack results and strengthen agent guardrails
|
||||
2. Explore the Self-Reflection sample (FoundryAgents_Evaluations_Step02_SelfReflection) for quality assessment
|
||||
3. Set up continuous red teaming in your CI/CD pipeline
|
||||