From ca02146ee4b454b5a3ae7ef0c35280ea31f501d6 Mon Sep 17 00:00:00 2001
From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Date: Mon, 30 Mar 2026 12:55:30 +0100
Subject: [PATCH 01/13] .NET: BugFix #3433 ChatClientAgent streaming responses
missing messageid (#4615)
* Changes
* Fix ChatClientAgent streaming responses missing MessageId
Generate fallback MessageId in ChatClientAgent.RunCoreStreamingAsync when
the underlying LLM provider does not set ChatResponseUpdate.MessageId.
Without a MessageId the AGUI converter's null==null check silently drops
all text content, causing CopilotKit Zod validation errors.
Changes:
- ChatClientAgent: generate msg_{Guid} fallback via ??= in streaming loop
- AgentResponseExtensions: sync wrapper MessageId back to RawRepresentation
in AsChatResponseUpdate() so downstream consumers see the value
- Add unit tests for both fixes and AGUI streaming MessageId scenarios
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR #4615 review comments
- Fix MessageId seeding: use first-seen provider MessageId (or generate
fallback) and apply consistently to all chunks in the stream, preventing
message splitting when providers set MessageId only on the first chunk
- Add test for mixed MessageId scenario (first chunk only)
- Fix skipped TextStreaming test: assert Empty (not NotEmpty) to match
actual null==null behavior
- Fix skipped ToolCalls test: assert empty ParentMessageId to match
actual empty-string passthrough behavior
* Handle empty MessageId in AsChatResponseUpdate sync
Treat empty/whitespace MessageId the same as null when syncing from
the AgentResponseUpdate wrapper back to RawRepresentation. Providers
that return empty string MessageId (e.g. tool call responses) now get
the wrapper value recovered correctly.
Add test for empty string MessageId recovery scenario.
* Move MessageId fallback generation to AGUI layer
Move fallback MessageId generation from ChatClientAgent to
AsAGUIEventStreamAsync, addressing the architectural concern that
MessageId is nullable in the AIAgent abstraction and the requirement
for non-null values is specific to the AGUI protocol.
The AGUI layer now generates a fallback MessageId for null or
empty/whitespace values, covering all agent types (not just
ChatClientAgent) including external implementations.
Changes:
- Revert MessageId generation from ChatClientAgent.RunCoreStreamingAsync
- Add fallback MessageId generation in AsAGUIEventStreamAsync for
null/empty MessageId values (handles both null and whitespace)
- Unskip and update AGUI tests to verify fallback generation
- Update ChatClientAgent tests to reflect passthrough behavior
* Revert AsChatResponseUpdate MessageId sync-back
Remove the MessageId sync-back logic from AsChatResponseUpdate() as it
is no longer needed. With fallback generation moved to the AGUI layer,
the abstraction layer should not mutate the RawRepresentation object.
Revert to the original passthrough behavior for AsChatResponseUpdate()
and update tests accordingly.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../ChatResponseUpdateAGUIExtensions.cs | 9 +
.../AGUIStreamingMessageIdTests.cs | 228 ++++++++++++++++++
.../AgentResponseUpdateExtensionsTests.cs | 39 +++
.../ChatClient/ChatClientAgentTests.cs | 69 ++++++
4 files changed, 345 insertions(+)
create mode 100644 dotnet/tests/Microsoft.Agents.AI.AGUI.UnitTests/AGUIStreamingMessageIdTests.cs
diff --git a/dotnet/src/Microsoft.Agents.AI.AGUI/Shared/ChatResponseUpdateAGUIExtensions.cs b/dotnet/src/Microsoft.Agents.AI.AGUI/Shared/ChatResponseUpdateAGUIExtensions.cs
index f5fb103bd4..b11475ddfc 100644
--- a/dotnet/src/Microsoft.Agents.AI.AGUI/Shared/ChatResponseUpdateAGUIExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.AGUI/Shared/ChatResponseUpdateAGUIExtensions.cs
@@ -341,8 +341,17 @@ internal static class ChatResponseUpdateAGUIExtensions
};
string? currentMessageId = null;
+ string? streamingMessageId = null;
await foreach (var chatResponse in updates.WithCancellation(cancellationToken).ConfigureAwait(false))
{
+ // Generate a fallback MessageId when the provider doesn't supply one.
+ // This ensures all AGUI events have a valid messageId regardless of agent type.
+ if (string.IsNullOrWhiteSpace(chatResponse.MessageId))
+ {
+ streamingMessageId ??= Guid.NewGuid().ToString("N");
+ chatResponse.MessageId = streamingMessageId;
+ }
+
if (chatResponse is { Contents.Count: > 0 } &&
chatResponse.Contents[0] is TextContent &&
!string.Equals(currentMessageId, chatResponse.MessageId, StringComparison.Ordinal))
diff --git a/dotnet/tests/Microsoft.Agents.AI.AGUI.UnitTests/AGUIStreamingMessageIdTests.cs b/dotnet/tests/Microsoft.Agents.AI.AGUI.UnitTests/AGUIStreamingMessageIdTests.cs
new file mode 100644
index 0000000000..5c55408ff8
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.AI.AGUI.UnitTests/AGUIStreamingMessageIdTests.cs
@@ -0,0 +1,228 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Agents.AI.AGUI.Shared;
+using Microsoft.Extensions.AI;
+
+namespace Microsoft.Agents.AI.AGUI.UnitTests;
+
+///
+/// Tests for AGUI streaming behavior when MessageId is null or missing from
+/// ChatResponseUpdate objects (e.g., providers like Google GenAI/Vertex AI
+/// that don't supply MessageId on streaming chunks).
+///
+public sealed class AGUIStreamingMessageIdTests
+{
+ ///
+ /// When ChatResponseUpdate objects with null MessageId are fed directly to
+ /// AsAGUIEventStreamAsync, the AGUI layer generates a fallback MessageId so
+ /// that events are valid regardless of agent type or provider.
+ ///
+ [Fact]
+ public async Task TextStreaming_NullMessageId_GeneratesFallbackInAGUILayerAsync()
+ {
+ // Arrange - Simulate a provider that does NOT set MessageId
+ List providerUpdates =
+ [
+ new ChatResponseUpdate(ChatRole.Assistant, "Hello"),
+ new ChatResponseUpdate(ChatRole.Assistant, " world"),
+ new ChatResponseUpdate(ChatRole.Assistant, "!")
+ ];
+
+ // Act
+ List aguiEvents = [];
+ await foreach (BaseEvent evt in providerUpdates.ToAsyncEnumerableAsync()
+ .AsAGUIEventStreamAsync("thread-1", "run-1", AGUIJsonSerializerContext.Default.Options))
+ {
+ aguiEvents.Add(evt);
+ }
+
+ // Assert - AGUI layer should generate a fallback MessageId
+ List startEvents = aguiEvents.OfType().ToList();
+ List contentEvents = aguiEvents.OfType().ToList();
+
+ Assert.Single(startEvents);
+ Assert.False(string.IsNullOrEmpty(startEvents[0].MessageId));
+
+ Assert.Equal(3, contentEvents.Count);
+ Assert.All(contentEvents, e => Assert.False(string.IsNullOrEmpty(e.MessageId)));
+
+ // All events should share the same generated MessageId
+ string?[] distinctIds = contentEvents.Select(e => e.MessageId).Distinct().ToArray();
+ Assert.Single(distinctIds);
+ Assert.Equal(startEvents[0].MessageId, distinctIds[0]);
+ }
+
+ ///
+ /// Full pipeline: ChatClientAgent → AsChatResponseUpdatesAsync → AsAGUIEventStreamAsync
+ /// with a provider that returns null MessageId. Verifies that fallback MessageId
+ /// generation ensures valid AGUI events.
+ ///
+ [Fact]
+ public async Task FullPipeline_NullProviderMessageId_ProducesValidAGUIEventsAsync()
+ {
+ // Arrange - ChatClientAgent with a mock client that omits MessageId
+ IChatClient mockChatClient = new NullMessageIdChatClient();
+ ChatClientAgent agent = new(mockChatClient, name: "test-agent");
+
+ ChatMessage userMessage = new(ChatRole.User, "tell me about agents");
+
+ // Act - Run the full pipeline exactly as MapAGUI does
+ List aguiEvents = [];
+ await foreach (BaseEvent evt in agent
+ .RunStreamingAsync([userMessage])
+ .AsChatResponseUpdatesAsync()
+ .AsAGUIEventStreamAsync("thread-1", "run-1", AGUIJsonSerializerContext.Default.Options))
+ {
+ aguiEvents.Add(evt);
+ }
+
+ // Assert — The pipeline should produce AGUI events with valid messageId
+ List startEvents = aguiEvents.OfType().ToList();
+ List contentEvents = aguiEvents.OfType().ToList();
+
+ Assert.NotEmpty(startEvents);
+ Assert.NotEmpty(contentEvents);
+
+ foreach (TextMessageStartEvent startEvent in startEvents)
+ {
+ Assert.False(
+ string.IsNullOrEmpty(startEvent.MessageId),
+ "TextMessageStartEvent.MessageId should not be null/empty when provider omits it");
+ }
+
+ foreach (TextMessageContentEvent contentEvent in contentEvents)
+ {
+ Assert.False(
+ string.IsNullOrEmpty(contentEvent.MessageId),
+ "TextMessageContentEvent.MessageId should not be null/empty when provider omits it");
+ }
+
+ // All content events should share the same messageId
+ string?[] distinctMessageIds = contentEvents.Select(e => e.MessageId).Distinct().ToArray();
+ Assert.Single(distinctMessageIds);
+ }
+
+ ///
+ /// When ChatResponseUpdate has empty string MessageId, the AGUI layer generates
+ /// a fallback so ToolCallStartEvent.ParentMessageId is valid.
+ ///
+ [Fact]
+ public async Task ToolCalls_EmptyMessageId_GeneratesFallbackParentMessageIdAsync()
+ {
+ // Arrange - ChatResponseUpdate with a tool call but empty MessageId
+ FunctionCallContent functionCall = new("call_abc123", "GetWeather")
+ {
+ Arguments = new Dictionary { ["location"] = "San Francisco" }
+ };
+
+ List providerUpdates =
+ [
+ new ChatResponseUpdate
+ {
+ Role = ChatRole.Assistant,
+ MessageId = "",
+ Contents = [functionCall]
+ }
+ ];
+
+ // Act
+ List aguiEvents = [];
+ await foreach (BaseEvent evt in providerUpdates.ToAsyncEnumerableAsync()
+ .AsAGUIEventStreamAsync("thread-1", "run-1", AGUIJsonSerializerContext.Default.Options))
+ {
+ aguiEvents.Add(evt);
+ }
+
+ // Assert — ParentMessageId should have a generated fallback
+ ToolCallStartEvent? toolCallStart = aguiEvents.OfType().FirstOrDefault();
+ Assert.NotNull(toolCallStart);
+ Assert.Equal("call_abc123", toolCallStart.ToolCallId);
+ Assert.Equal("GetWeather", toolCallStart.ToolCallName);
+ Assert.False(
+ string.IsNullOrEmpty(toolCallStart.ParentMessageId),
+ "ParentMessageId should have a generated fallback for empty provider MessageId");
+ }
+
+ ///
+ /// When a provider properly sets MessageId (e.g., OpenAI), the AGUI pipeline
+ /// produces valid events with correct messageId values.
+ ///
+ [Fact]
+ public async Task TextStreaming_WithProviderMessageId_ProducesValidAGUIEventsAsync()
+ {
+ // Arrange — Provider that properly sets MessageId
+ List providerUpdates =
+ [
+ new ChatResponseUpdate(ChatRole.Assistant, "Hello")
+ {
+ MessageId = "chatcmpl-abc123"
+ },
+ new ChatResponseUpdate(ChatRole.Assistant, " world")
+ {
+ MessageId = "chatcmpl-abc123"
+ }
+ ];
+
+ // Act
+ List aguiEvents = [];
+ await foreach (BaseEvent evt in providerUpdates.ToAsyncEnumerableAsync()
+ .AsAGUIEventStreamAsync("thread-1", "run-1", AGUIJsonSerializerContext.Default.Options))
+ {
+ aguiEvents.Add(evt);
+ }
+
+ // Assert
+ List startEvents = aguiEvents.OfType().ToList();
+ List contentEvents = aguiEvents.OfType().ToList();
+
+ Assert.Single(startEvents);
+ Assert.Equal("chatcmpl-abc123", startEvents[0].MessageId);
+
+ Assert.Equal(2, contentEvents.Count);
+ Assert.All(contentEvents, e => Assert.Equal("chatcmpl-abc123", e.MessageId));
+ }
+}
+
+///
+/// Mock IChatClient that simulates a provider not setting MessageId on streaming chunks
+/// (e.g., Google GenAI / Vertex AI).
+///
+internal sealed class NullMessageIdChatClient : IChatClient
+{
+ public void Dispose()
+ {
+ }
+
+ public object? GetService(Type serviceType, object? serviceKey = null) => null;
+
+ public Task GetResponseAsync(
+ IEnumerable messages,
+ ChatOptions? options = null,
+ CancellationToken cancellationToken = default)
+ {
+ return Task.FromResult(new ChatResponse([new(ChatRole.Assistant, "response")]));
+ }
+
+ public async IAsyncEnumerable GetStreamingResponseAsync(
+ IEnumerable messages,
+ ChatOptions? options = null,
+ [EnumeratorCancellation] CancellationToken cancellationToken = default)
+ {
+ foreach (string chunk in (string[])["Agents", " are", " autonomous", " programs."])
+ {
+ yield return new ChatResponseUpdate
+ {
+ Role = ChatRole.Assistant,
+ Contents = [new TextContent(chunk)]
+ };
+
+ await Task.Yield();
+ }
+ }
+}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateExtensionsTests.cs
index 89cff04de8..5cf0b75eef 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateExtensionsTests.cs
@@ -384,6 +384,45 @@ public class AgentResponseUpdateExtensionsTests
Assert.Same(originalChatResponseUpdate, result);
}
+ [Fact]
+ public void AsChatResponseUpdate_WithRawRepresentationNullMessageId_ReturnsRawDirectly()
+ {
+ // Arrange - RawRepresentation has null MessageId
+ ChatResponseUpdate originalChatResponseUpdate = new()
+ {
+ ResponseId = "original-update",
+ Contents = [new TextContent("Hello")]
+ };
+ AgentResponseUpdate agentResponseUpdate = new(originalChatResponseUpdate);
+
+ // Act
+ ChatResponseUpdate result = agentResponseUpdate.AsChatResponseUpdate();
+
+ // Assert - Returns the raw representation directly without mutation
+ Assert.Same(originalChatResponseUpdate, result);
+ Assert.Null(result.MessageId);
+ }
+
+ [Fact]
+ public void AsChatResponseUpdate_WithRawRepresentationExistingMessageId_PreservesOriginal()
+ {
+ // Arrange - RawRepresentation already has MessageId set by provider
+ ChatResponseUpdate originalChatResponseUpdate = new()
+ {
+ ResponseId = "original-update",
+ MessageId = "provider-message-id",
+ Contents = [new TextContent("Hello")]
+ };
+ AgentResponseUpdate agentResponseUpdate = new(originalChatResponseUpdate);
+
+ // Act
+ ChatResponseUpdate result = agentResponseUpdate.AsChatResponseUpdate();
+
+ // Assert - Provider's original MessageId should be preserved
+ Assert.Same(originalChatResponseUpdate, result);
+ Assert.Equal("provider-message-id", result.MessageId);
+ }
+
[Fact]
public void AsChatResponseUpdate_WithoutRawRepresentation_CreatesNewChatResponseUpdate()
{
diff --git a/dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgentTests.cs
index 7241ca763e..42b115c8bb 100644
--- a/dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgentTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.UnitTests/ChatClient/ChatClientAgentTests.cs
@@ -1793,6 +1793,75 @@ public partial class ChatClientAgentTests
Times.Once);
}
+ ///
+ /// Verify that RunStreamingAsync passes through null MessageId from provider without modification.
+ /// MessageId generation is handled by downstream consumers (e.g., AGUI layer), not ChatClientAgent.
+ ///
+ [Fact]
+ public async Task RunStreamingAsync_WithNullMessageId_PassesThroughNullAsync()
+ {
+ // Arrange - Provider returns updates WITHOUT MessageId
+ ChatResponseUpdate[] returnUpdates =
+ [
+ new ChatResponseUpdate(role: ChatRole.Assistant, content: "Hello"),
+ new ChatResponseUpdate(role: ChatRole.Assistant, content: " world"),
+ ];
+
+ Mock mockService = new();
+ mockService.Setup(
+ s => s.GetStreamingResponseAsync(
+ It.IsAny>(),
+ It.IsAny(),
+ It.IsAny())).Returns(ToAsyncEnumerableAsync(returnUpdates));
+
+ ChatClientAgent agent = new(mockService.Object);
+
+ // Act
+ List result = [];
+ await foreach (var update in agent.RunStreamingAsync([new ChatMessage(ChatRole.User, "Hi")]))
+ {
+ result.Add(update);
+ }
+
+ // Assert - MessageId should be null (ChatClientAgent does not generate fallback IDs)
+ Assert.Equal(2, result.Count);
+ Assert.All(result, u => Assert.Null(u.MessageId));
+ }
+
+ ///
+ /// Verify that RunStreamingAsync preserves provider-supplied MessageId when present.
+ ///
+ [Fact]
+ public async Task RunStreamingAsync_WithProviderMessageId_PreservesItAsync()
+ {
+ // Arrange - Provider returns updates WITH MessageId (like OpenAI)
+ ChatResponseUpdate[] returnUpdates =
+ [
+ new ChatResponseUpdate(role: ChatRole.Assistant, content: "Hello") { MessageId = "chatcmpl-abc123" },
+ new ChatResponseUpdate(role: ChatRole.Assistant, content: " world") { MessageId = "chatcmpl-abc123" },
+ ];
+
+ Mock mockService = new();
+ mockService.Setup(
+ s => s.GetStreamingResponseAsync(
+ It.IsAny>(),
+ It.IsAny(),
+ It.IsAny())).Returns(ToAsyncEnumerableAsync(returnUpdates));
+
+ ChatClientAgent agent = new(mockService.Object);
+
+ // Act
+ List result = [];
+ await foreach (var update in agent.RunStreamingAsync([new ChatMessage(ChatRole.User, "Hi")]))
+ {
+ result.Add(update);
+ }
+
+ // Assert - Provider's MessageId should be preserved, not overwritten
+ Assert.Equal(2, result.Count);
+ Assert.All(result, u => Assert.Equal("chatcmpl-abc123", u.MessageId));
+ }
+
///
/// Verify that RunStreamingAsync uses the ChatHistoryProvider factory when the chat client returns no conversation id.
///
From f45fc7d402023421987974d234e11f88ccf157ef Mon Sep 17 00:00:00 2001
From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com>
Date: Mon, 30 Mar 2026 13:09:02 +0100
Subject: [PATCH 02/13] .NET: [Breaking] Update Foundry Agents for Responses
API (#4502)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Stage
* Add FoundryAgentClient, model param, chatClientFactory, and RAPI samples
- Add model parameter to FoundryAgentClient simple constructor
- Add chatClientFactory parameter to both constructors
- Switch to OpenAI.GetProjectResponsesClientForModel for direct Responses API usage
- Add FoundryAgents-RAPI samples (Step01 Basics, Step02 Multiturn, Step03 FunctionTools)
- Add solution folder entry for FoundryAgents-RAPI samples
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add auto-discovery constructor and simplify RAPI samples
- Add FoundryAgentClient constructor that reads AZURE_AI_PROJECT_ENDPOINT and
AZURE_AI_MODEL_DEPLOYMENT_NAME from environment variables with DefaultAzureCredential
- Simplify RAPI samples to use auto-discovery (no env var or credential code)
- Remove Azure.Identity direct references from sample csproj files
- Update READMEs to document environment variable requirements
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add remaining RAPI samples (Step04-Step12)
- Step04: Function tools with human-in-the-loop approvals
- Step05: Structured output with typed responses
- Step06: Persisted conversations with session serialization
- Step07: Observability with OpenTelemetry
- Step08: Dependency injection with hosted service
- Step10: Image multi-modality
- Step11: Agent as function tool (agent composition)
- Step12: Middleware (PII, guardrails, function logging, HITL approval)
- Update solution file and folder README with all new samples
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add all RAPI samples (Step09-Step23) and switch to AzureCliCredential
- Step09: MCP client as tools (GitHub server via stdio)
- Step13: Plugins with dependency injection
- Step14: Code Interpreter tool
- Step15: Computer Use tool with screenshot simulation
- Step16: File Search with vector stores
- Step17: OpenAPI tools (REST Countries API)
- Step18: Bing Custom Search
- Step19: SharePoint grounding
- Step20: Microsoft Fabric
- Step21: Web Search with citations
- Step22: Memory Search with multi-turn conversations
- Step23: Local MCP via HTTP (Microsoft Learn)
- Switch all samples (Step04-Step12) to use AzureCliCredential with env vars
- Update solution file and README with all 23 samples
- All 23 samples build successfully, tested Step05/06/11/13/21
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Switch Step01-03 samples to AzureCliCredential for consistency
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Clarify connection ID format in SharePoint and Fabric READMEs
Document that SHAREPOINT_PROJECT_CONNECTION_ID and FABRIC_PROJECT_CONNECTION_ID
should use the connection name (e.g., 'SharepointTestTool'), not the full ARM
resource URI.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Normalize env vars, fix structured output, update READMEs with connection ID formats
- Normalize AZURE_FOUNDRY_PROJECT_* env vars to AZURE_AI_PROJECT_ENDPOINT / AZURE_AI_MODEL_DEPLOYMENT_NAME across all samples (Steps 18-22 READMEs + Steps 19-20 Program.cs)
- Fix RAPI Step05 StructuredOutput to use full constructor with ResponseFormat for streaming JSON
- Update Deep Research sample to use AzureCliCredential
- Enrich Bing Grounding README with full ARM resource URI format
- Fix Bing Custom Search README env var mismatch (BING_CUSTOM_SEARCH_* -> AZURE_AI_CUSTOM_SEARCH_*)
- Add finding instructions for connection ID and instance name in Bing Custom Search READMEs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Refactor memory samples and switch to DefaultAzureCredential
- Refactor RAPI Step22 MemorySearch: extract store setup to EnsureMemoryStoreAsync local function
- Refactor non-RAPI Step22 MemorySearch: same pattern with explicit memory lifecycle
- Set UpdateDelay=0 on MemoryUpdateOptions and MemorySearchPreviewTool for faster ingestion
- Use WaitForMemoriesUpdateAsync with 500ms polling interval
- Switch Step19 SharePoint, Step20 Fabric, Step22 MemorySearch (both) to DefaultAzureCredential
- Remove SearchOptions from MemorySearchPreviewTool (causes unknown parameter error)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Switch all RAPI samples to DefaultAzureCredential and format
- Replace AzureCliCredential with DefaultAzureCredential across all 20 RAPI samples
- Run dotnet format on all RAPI and non-RAPI Foundry samples
- AzureAI unit tests: 341 passed (net10.0 + net472)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Rename to Microsoft Foundry, add metadata, rename RAPI folder
- Replace 'Azure AI Foundry' / 'Azure Foundry' with 'Microsoft Foundry' in all docs, comments, and XML docs
- Update FoundryAgentClient metadata provider name to 'microsoft.foundry'
- Rename FoundryAgents-RAPI folder to FoundryResponseAgents
- Rewrite FoundryResponseAgents README with comparison table vs Foundry Agents
- Update slnx and parent README with new folder references
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR review: simplify sample comments and fix DeepResearch credential
- Remove 'no server-side agent' and 'Responses API directly' phrasing from comments
- Simplify to 'Create a FoundryAgentClient' per review feedback
- Switch Agent_Step15_DeepResearch to DefaultAzureCredential
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Restore full DefaultAzureCredential warning comment in DeepResearch sample
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add ADR 0020: Foundry agent type naming convention
Proposes naming options for a new MAF type wrapping versioned
Foundry agents (Prompt, ContainerApp, Hosted, Workflow) to
distinguish from the existing FoundryResponsesAgent (RAPI path).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Simplify FoundryResponsesAgent samples with env-var constructors and rename folders
- Add env-var constructors to FoundryResponsesAgent (simple + options-based)
- Fix Constructor 1 model optionality (no longer throws on missing AZURE_AI_MODEL_DEPLOYMENT_NAME)
- Add ApplyModelDeploymentFallback helper for options-based constructor
- Update all 23 FoundryResponseAgents samples to remove Environment.GetEnvironmentVariable boilerplate
- Condense 6 simple samples to one-liner constructor calls
- Add XML doc remarks about auto-resolved parameters on all constructors
- Rename FoundryAgents -> FoundryVersionedAgents (server-side, versioned)
- Rename FoundryResponseAgents -> FoundryAgents (now the default path forward)
- Update .slnx and README cross-references for new folder names
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add FoundryAITool factory, rename RAPI folders, and clean up references
- Create FoundryAITool static factory class with 17 methods wrapping AgentTool.Create* and ResponseTool.Create* into AITool returns
- Rename 23 FoundryAgentsRAPI_* subfolders to FoundryAgents_* (drop RAPI prefix)
- Rename .csproj files and update .slnx references accordingly
- Update 12 samples (6 FoundryAgents + 6 FoundryVersionedAgents) to use FoundryAITool
- Replace all FoundryResponsesAgent references with FoundryAgent in comments and READMEs
- Update sample READMEs to reference FoundryAITool methods
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Rename FoundryVersionedAgents subfolders from FoundryAgents_* to FoundryVersionedAgents_*
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add FoundryVersionedAgent class and refactor extension method internals
- Create FoundryVersionedAgent with private ctor and async static factory methods
(CreateAIAgentAsync/GetAIAgentAsync) with env-var and explicit endpoint tiers
- Extract shared internal helpers from AzureAIProjectChatClientExtensions:
CreateChatClientAgent, CreateAgentVersionFromOptionsAsync,
CreateAgentVersionWithProtocolAsync (tools overload),
CreateChatClientAgentOptions, GetAgentRecordByNameAsync, ThrowIfInvalidAgentName
- Extension methods now delegate to shared internal helpers
- All 49 existing samples continue to build successfully
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add CreateConversationSessionAsync, DeleteAIAgentAsync, auto-resolve model, simplify samples
- Add CreateConversationSessionAsync to FoundryAgent and FoundryVersionedAgent
(returns ChatClientAgentSession, creates server-side conversation + session in one call)
- Add DeleteAIAgentAsync static method to FoundryVersionedAgent
- Make model parameter optional in env-var factory overloads (auto-resolves from
AZURE_AI_MODEL_DEPLOYMENT_NAME)
- Update all FoundryVersionedAgents samples to use DeleteAIAgentAsync
- Remove deploymentName env var from samples where only used for model parameter
- Use CreateConversationSessionAsync in Step02_MultiturnConversation
- Use explicit types instead of var for agent/session variables
- All 49 samples build successfully
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove manual AIProjectClient construction from FoundryVersionedAgents samples
- Replace manual AIProjectClient construction with GetService()
from the FoundryVersionedAgent in all dual-option and tool-specific samples
- Remove AZURE_AI_PROJECT_ENDPOINT env var reads from updated samples
- Remove Azure.Identity usings where no longer needed
- Only Step01.1, Step01.2, Eval_Step01 retain manual construction (pedagogical samples)
- All 49 samples build successfully
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Replace aiProjectClient extension calls with FoundryVersionedAgent factories in all samples
- Replace aiProjectClient.CreateAIAgentAsync with FoundryVersionedAgent.CreateAIAgentAsync
in Option 2 (Native SDK) paths across Steps 14-21
- Replace aiProjectClient.Agents.DeleteAgentAsync with FoundryVersionedAgent.DeleteAIAgentAsync
- Remove unused AIProjectClient variables and using directives
- Only Step01.1, Step01.2, Eval_Step01 retain direct AIProjectClient usage (pedagogical)
- Step16, Step22 use GetService() for file/memory operations
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove unused using directives from Step01.2, Step09, Eval_Step02
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update ADR 0020 with accepted decision: Option 6
- Add Option 6 detailing FoundryAgent, FoundryVersionedAgent, FoundryAITool,
env-var auto-discovery, and self-contained factory patterns
- Mark decision as accepted with rationale
- Update current state and metadata sections
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update Step01 basics samples to use FoundryVersionedAgent factories
- Step01.1: Replace manual AIProjectClient/AsAIAgent with FoundryVersionedAgent.CreateAIAgentAsync/GetAIAgentAsync/DeleteAIAgentAsync
- Step01.2: Replace manual AIProjectClient with FoundryVersionedAgent.CreateAIAgentAsync/DeleteAIAgentAsync
- Remove env var boilerplate and Azure.Identity dependency
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add DeleteAIAgentVersionAsync to FoundryVersionedAgent
- DeleteAIAgentAsync: deletes the agent and all its versions (existing)
- DeleteAIAgentVersionAsync: deletes only the specific version associated with the agent instance
- Internally delegates to Agents.DeleteAgentAsync vs Agents.DeleteAgentVersionAsync
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix cleanup comments: DeleteAIAgentAsync deletes the agent and all its versions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update all FoundryVersionedAgents READMEs for FoundryVersionedAgent and auto-discovery
- Rewrite main README with FoundryVersionedAgent usage, auto-discovery table, code example
- Fix sample table links from FoundryAgents_Step* to FoundryVersionedAgents_Step*
- Add FoundryAITool references in tool-specific sample descriptions
- Update individual READMEs: fix stale paths, add auto-discovery note after env var blocks
- Update tool references: AgentTool/ResponseTool -> FoundryAITool
- Update parent 02-agents/README.md with FoundryVersionedAgent description
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert unrelated AGUI and Hosting.OpenAI formatting changes to main
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Remove env-var auto-discovery, add AsAIAgent, mark extensions Obsolete
- Remove 2 env-var constructors from FoundryAgent (keep explicit endpoint ctors)
- Remove 5 env-var factory methods from FoundryVersionedAgent (keep explicit ones)
- Add 3 AsAIAgent static methods to FoundryVersionedAgent (AgentVersion/AgentRecord/AgentReference)
- Mark all 8 AIProjectClient extension methods as [Obsolete] pointing to FoundryVersionedAgent
- Remove ApplyModelDeploymentFallback, env var constants, Azure.Identity usings from source
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update all samples to use explicit endpoint, credential, and model parameters
- Add explicit Environment.GetEnvironmentVariable reads for AZURE_AI_PROJECT_ENDPOINT
and AZURE_AI_MODEL_DEPLOYMENT_NAME to all 48 sample files
- Pass new Uri(endpoint), new DefaultAzureCredential(), deploymentName to
FoundryAgent constructors and FoundryVersionedAgent factory methods
- Add using Azure.Identity where missing
- Matches repo-wide pattern used by other non-Foundry samples
- All 49 samples build successfully
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Migrate remaining samples and source from obsoleted extension methods
- Migrate AgentProviders, AgentWithRAG, AgentWithMemory, HostedWorkflow samples to FoundryVersionedAgent
- Migrate AzureAgentProvider.cs to FoundryVersionedAgent.AsAIAgent
- Migrate AzureAIProjectChatClientTests.cs to FoundryVersionedAgent.GetAIAgentAsync
- Remove pragma suppressions from migrated files
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add unit tests for FoundryAgent and FoundryVersionedAgent
- FoundryAgentTests.cs: 14 tests covering constructors, validation,
properties, metadata, GetService, chat client factory, user-agent header
- FoundryVersionedAgentTests.cs: 31 tests covering CreateAIAgentAsync,
GetAIAgentAsync, AsAIAgent (3 overloads), DeleteAIAgentAsync,
DeleteAIAgentVersionAsync, validation, invalid names, metadata, GetService
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Finalize Foundry agent migration
Align FoundryAgent and FoundryVersionedAgent samples, docs, and tests with the explicit configuration model, clean up stale README guidance, and fix AzureAI unit test validation/build issues.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Apply formatter cleanup after validation
Capture the dotnet format follow-up changes produced during branch validation so the committed state matches the successfully built and tested branch.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add integration tests for FoundryAgent and FoundryVersionedAgent
Mark old AIProjectClient extension-method integration tests as obsolete and add new integration test suites for both FoundryAgent (Responses API) and FoundryVersionedAgent (versioned agents). All 71 non-skipped tests pass against the live Foundry service.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update ADR 0020 with test coverage details
Add integration test coverage note to the Current State section of ADR 0020.
* Simplify Foundry agents and validate moved samples
* Rename FoundryAgent integration tests to ResponsesAgent
The test classes exercise the non-versioned Responses path via
AIProjectClient.AsAIAgent(), not the removed FoundryAgent wrapper type.
Rename files and class names to reflect the actual test surface.
* Update documentation for ChatClientAgent usage
Added example usage of ChatClientAgent with JokerAgent.
* Refactor ChatClientAgent instantiation for clarity
* Revise agent type naming and usage examples
Updated documentation to reflect changes in agent creation methods and added examples for using `ChatClientAgent`.
* Fix Azure SDK namespace migration after rebase
Update Azure.AI.Projects.OpenAI references to Azure.AI.Projects.Agents
and Azure.AI.Extensions.OpenAI to match Azure.AI.Projects 2.0.0-beta.2.
- Replace deprecated namespace across samples, tests, and src
- Fix renamed types: OpenAPIFunctionDefinition -> OpenApiFunctionDefinition,
BingCustomSearchToolParameters -> BingCustomSearchToolOptions,
BrowserAutomationToolParameters -> BrowserAutomationToolOptions
- Fix API changes: AgentRecord.Versions -> GetLatestVersion(),
ResponsesClient constructor, FunctionApprovalRequestContent ->
ToolApprovalRequestContent
- Apply dotnet format
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address merge markers
* Replace obsolete GetAIAgentAsync with AsAIAgent in samples
Switch Agent_Step07_AsMcpTool and A2AServer to use the non-obsolete
PersistentAgentsClient.AsAIAgent(PersistentAgent) extension instead
of the deprecated GetAIAgentAsync, fixing CS0618 build errors.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix broken markdown links in Responses sample READMEs
Replace stale ChatClientAgents_Step* folder references with the
correct Agent_Step* names across all Responses sample READMEs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix format errors and address PR review comments
- Fix charset and remove unused using in AzureAIProjectResponsesChatClient
- Fix doc comment tags (code -> c) in FoundryAITool
- Fix stray period in LocalMCP sample comment
- Fix grammar in FoundryMemoryProvider xmldoc
- Fix AIProjectClientAgentRunStreamingConversationTests base class
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Apply dotnet format fixes to PR-changed files
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix build errors from format pass and apply naming conventions
- Fix static call to CreateSessionAsync in Step02 samples and extension tests
- Use expression-bodied lambda in FoundryMemoryProvider (RCS1021)
- Apply PascalCase naming to const fields in ResponsesAgentExtensionCreateTests (IDE1006)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Introduce FoundryAgent sealed type and update AsAIAgent extensions
- Add FoundryAgent sealed class wrapping ChatClientAgent with:
- Public ctors: (projectEndpoint, credential, model, instructions) and (agentEndpoint, credential)
- Internal ctor: (AIProjectClient, ChatClientAgent) for extension use
- CreateConversationSessionAsync() for server-side conversations
- GetService() and GetService()
- MEAI user-agent policy on internally-created AIProjectClient
- Change all AsAIAgent extension return types from ChatClientAgent to FoundryAgent
- Update all samples and tests to use FoundryAgent type
- Add 16 FoundryAgentTests covering ctors, GetService, UserAgent, RunAsync
- Fix pre-existing Agent_Step12_Plugins build error
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Collapse sample folders and add FoundryAgent_Step01 sample
- Move all Responses/* samples up to AgentsWithFoundry/ (flat structure)
- Remove entire Versioned/ folder (26 samples)
- Add FoundryAgent_Step01 sample showing direct FoundryAgent ctor usage
- Update slnx to reflect flat folder structure
- Fix csproj ProjectReference paths for new depth
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update READMEs for flat AgentsWithFoundry structure
- Rewrite AgentsWithFoundry/README.md with FoundryAgent quick start
- Fix cd commands and paths in 11 sample READMEs
- Update 02-agents/README.md to single Foundry link
- Update AGENTS.md tree to flat structure
- Fix AgentWithMemory cross-reference
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix FoundryAgent_Step01 sample with full create/run/delete lifecycle
Show the complete server-side agent lifecycle: create version with
native SDK, wrap as FoundryAgent via AsAIAgent, run, then delete.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Revert RAPI samples to use AIAgent instead of FoundryAgent
RAPI samples should not reference FoundryAgent directly. Restored
original sample code with only ChatClientAgent -> AIAgent type change
to accommodate the AsAIAgent return type.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Convert versioned-pattern samples to pure RAPI
Step09, Step13, Step17, Step22 were using CreateAgentVersionAsync +
PromptAgentDefinition which is the versioned pattern. Converted to
use AsAIAgent(model, instructions, tools) which is the RAPI path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix format issues from Docker CI check
- FoundryAgent_Step01: CRLF -> LF
- Agent_Step09: missing final newline
- Agent_Step11_Middleware: add internal modifier, final newline
- Agent_Step02: remove redundant cast (IDE0004)
- Agent_Step08: simplify name (IDE0001)
- FoundryAgentTests: s_ prefix, Async suffix naming conventions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Switch Step09 MCP sample to Microsoft Learn HTTP endpoint
Replace npx stdio GitHub MCP server with the public Microsoft Learn
MCP endpoint (https://learn.microsoft.com/api/mcp) using HTTP transport.
No external tooling required to run.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix missing final newline in Step09 MCP sample
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR review: use DelegatingAIAgent, clean up Step01 sample
- FoundryAgent now inherits DelegatingAIAgent instead of AIAgent,
removing manual delegation boilerplate (westey-m feedback)
- Simplified Agent_Step01_Basics to single agent creation path,
moved composable IChatClient approach to README (westey-m feedback)
- Fixed FoundryAgentTests param name assertion
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Update sample using Project specialized type instead
* Address PR review feedback: DefaultAzureCredential warnings, sample simplifications, format fixes
- Add DefaultAzureCredential production warning comments to ~25 samples
- Simplify Anthropic and OpenAI Step01 samples to single agent
- Convert Step11 Middleware regex patterns to [GeneratedRegex]
- Remove unnecessary cleanup comment from Step06
- Fix Step09 README MCP transport description
- Enhance FoundryAgent xmldoc with non-persistent agent comparison
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Split Step02, simplify RAG Step04, sharpen Step23 differentiation
- Split Step02 into 02.1 (simple multi-turn via sessions) and 02.2 (server-side conversations via CreateConversationSessionAsync)
- RAG Step04: replace HostedFileSearchTool + MEAI wrapping with native OpenAI FileSearchTool
- Step23: clarify DelegatingAIFunction wrapping pattern vs Step09 basic MCP
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix Hosted MCP sample: use ResponseTool.CreateMcpTool and move tool to PromptAgentDefinition
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix broken README link after Step02 split
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address Sergey round 3 feedback: branding, README nav, sample rename
- Replace 'Azure AI Foundry' with 'Microsoft Foundry' in ADR 0020
- Fix 3 READMEs: 'ChatClientAgents' → 'AgentsWithFoundry' sample directory
- Rename FoundryAgent_Step01 → Agent_Step00_FoundryAgentLifecycle for naming consistency
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../0020-foundry-agent-type-naming.md | 125 +++++++
dotnet/agent-framework-dotnet.slnx | 61 ++--
.../AGUI/Step04_HumanInLoop/Client/Program.cs | 2 +-
.../ServerFunctionApprovalClientAgent.cs | 8 +-
.../ServerFunctionApprovalServerAgent.cs | 28 +-
.../Client/StatefulAgent.cs | 5 +-
.../Agent_With_AzureAIProject/Program.cs | 13 +-
.../Agent_Anthropic_Step01_Running/Program.cs | 13 +-
.../Program.cs | 14 +-
.../02-agents/AgentWithMemory/README.md | 4 +-
.../Agent_OpenAI_Step01_Running/Program.cs | 26 +-
.../Program.cs | 24 +-
.../Agents/Agent_Step07_AsMcpTool/Program.cs | 17 +-
.../Agents/Agent_Step11_Middleware/Program.cs | 18 +-
.../Agent_Step15_DeepResearch/Program.cs | 2 +-
.../Agent_Step15_DeepResearch/README.md | 10 +-
.../Program.cs | 8 +-
...Agent_Step00_FoundryAgentLifecycle.csproj} | 2 +-
.../Program.cs | 36 ++
.../README.md | 23 ++
.../Agent_Step01_Basics.csproj | 15 +
.../Agent_Step01_Basics/Program.cs | 20 ++
.../Agent_Step01_Basics/README.md | 55 +++
...ent_Step02.1_MultiturnConversation.csproj} | 3 +-
.../Program.cs | 26 ++
.../README.md | 36 ++
....2_MultiturnWithServerConversations.csproj | 15 +
.../Program.cs | 34 ++
.../README.md | 36 ++
.../Agent_Step03_UsingFunctionTools.csproj | 15 +
.../Program.cs | 41 +++
.../Agent_Step03_UsingFunctionTools/README.md | 37 ++
...p04_UsingFunctionToolsWithApprovals.csproj | 15 +
.../Program.cs | 25 +-
.../README.md | 30 ++
.../Agent_Step05_StructuredOutput.csproj | 15 +
.../Agent_Step05_StructuredOutput}/Program.cs | 52 +--
.../Agent_Step05_StructuredOutput/README.md | 29 ++
...Agent_Step06_PersistedConversations.csproj | 15 +
.../Program.cs | 13 +-
.../README.md | 30 ++
.../Agent_Step07_Observability.csproj} | 2 -
.../Agent_Step07_Observability}/Program.cs | 23 +-
.../Agent_Step07_Observability/README.md | 31 ++
.../Agent_Step08_DependencyInjection.csproj} | 2 -
.../Program.cs | 83 +++++
.../README.md | 30 ++
...Agent_Step09_UsingMcpClientAsTools.csproj} | 3 +-
.../Program.cs | 44 +++
.../README.md | 29 ++
.../Agent_Step10_UsingImages.csproj | 21 ++
.../Agent_Step10_UsingImages}/Program.cs | 18 +-
.../Agent_Step10_UsingImages/README.md | 30 ++
.../assets}/walkway.jpg | Bin
.../Agent_Step11_AsFunctionTool.csproj | 15 +
.../Agent_Step11_AsFunctionTool}/Program.cs | 34 +-
.../Agent_Step11_AsFunctionTool/README.md | 30 ++
.../Agent_Step12_Middleware.csproj} | 4 +-
.../Agent_Step12_Middleware}/Program.cs | 95 +++---
.../Agent_Step12_Middleware/README.md | 31 ++
.../Agent_Step13_Plugins.csproj} | 5 +-
.../Agent_Step13_Plugins/Program.cs | 153 +++++++++
.../Agent_Step13_Plugins/README.md | 29 ++
.../Agent_Step14_CodeInterpreter.csproj} | 1 -
.../Agent_Step14_CodeInterpreter}/Program.cs | 50 +--
.../Agent_Step14_CodeInterpreter/README.md | 28 ++
.../Agent_Step15_ComputerUse.csproj} | 2 +-
.../Assets/cua_browser_search.png | Bin
.../Assets/cua_search_results.png | Bin
.../Assets/cua_search_typed.png | Bin
.../ComputerUseUtil.cs | 0
.../Agent_Step15_ComputerUse}/Program.cs | 85 ++---
.../Agent_Step15_ComputerUse/README.md | 29 ++
.../Agent_Step16_FileSearch.csproj} | 1 -
.../Agent_Step16_FileSearch}/Program.cs | 45 +--
.../Agent_Step16_FileSearch/README.md | 29 ++
.../Agent_Step17_OpenAPITools.csproj} | 3 +-
.../Agent_Step17_OpenAPITools}/Program.cs | 77 ++---
.../Agent_Step17_OpenAPITools/README.md | 29 ++
.../Agent_Step18_BingCustomSearch.csproj} | 1 -
.../Agent_Step18_BingCustomSearch}/Program.cs | 59 +---
.../Agent_Step18_BingCustomSearch/README.md | 36 ++
.../Agent_Step19_SharePoint.csproj | 19 ++
.../Agent_Step19_SharePoint}/Program.cs | 55 +--
.../Agent_Step19_SharePoint/README.md | 30 ++
.../Agent_Step20_MicrosoftFabric.csproj | 19 ++
.../Agent_Step20_MicrosoftFabric/Program.cs | 42 +++
.../Agent_Step20_MicrosoftFabric/README.md | 30 ++
.../Agent_Step21_WebSearch.csproj | 19 ++
.../Agent_Step21_WebSearch/Program.cs | 44 +++
.../Agent_Step21_WebSearch/README.md | 28 ++
.../Agent_Step22_MemorySearch.csproj | 20 ++
.../Agent_Step22_MemorySearch}/Program.cs | 85 +++--
.../Agent_Step22_MemorySearch/README.md | 31 ++
.../Agent_Step23_LocalMCP.csproj | 20 ++
.../Agent_Step23_LocalMCP}/Program.cs | 75 ++---
.../Agent_Step23_LocalMCP/README.md | 29 ++
.../02-agents/AgentsWithFoundry/README.md | 81 +++++
.../Program.cs | 100 ------
.../README.md | 101 ------
...s_Evaluations_Step02_SelfReflection.csproj | 25 --
.../Program.cs | 292 ----------------
.../README.md | 118 -------
.../FoundryAgents_Step01.1_Basics/Program.cs | 50 ---
.../FoundryAgents_Step01.1_Basics/README.md | 40 ---
.../FoundryAgents_Step01.2_Running/Program.cs | 39 ---
.../FoundryAgents_Step01.2_Running/README.md | 46 ---
.../Program.cs | 56 ----
.../README.md | 59 ----
.../Program.cs | 54 ---
.../README.md | 48 ---
.../README.md | 51 ---
...undryAgents_Step05_StructuredOutput.csproj | 20 --
.../README.md | 49 ---
...gents_Step06_PersistedConversations.csproj | 20 --
.../README.md | 50 ---
.../README.md | 51 ---
.../Program.cs | 97 ------
.../README.md | 51 ---
...Agents_Step09_UsingMcpClientAsTools.csproj | 23 --
.../Program.cs | 50 ---
.../README.md | 50 ---
.../FoundryAgents_Step10_UsingImages.csproj | 26 --
.../README.md | 53 ---
...FoundryAgents_Step11_AsFunctionTool.csproj | 21 --
.../README.md | 49 ---
.../FoundryAgents_Step12_Middleware/README.md | 58 ----
.../FoundryAgents_Step13_Plugins.csproj | 22 --
.../FoundryAgents_Step13_Plugins/Program.cs | 142 --------
.../FoundryAgents_Step13_Plugins/README.md | 49 ---
...oundryAgents_Step14_CodeInterpreter.csproj | 22 --
.../README.md | 53 ---
.../README.md | 66 ----
.../FoundryAgents_Step16_FileSearch/README.md | 52 ---
.../FoundryAgents_Step17_OpenAPITools.csproj | 22 --
.../README.md | 47 ---
...undryAgents_Step18_BingCustomSearch.csproj | 22 --
.../README.md | 63 ----
.../FoundryAgents_Step19_SharePoint.csproj | 22 --
.../FoundryAgents_Step19_SharePoint/README.md | 50 ---
...oundryAgents_Step20_MicrosoftFabric.csproj | 22 --
.../Program.cs | 72 ----
.../README.md | 57 ----
.../FoundryAgents_Step21_WebSearch.csproj | 22 --
.../FoundryAgents_Step21_WebSearch/Program.cs | 65 ----
.../FoundryAgents_Step21_WebSearch/README.md | 52 ---
.../FoundryAgents_Step22_MemorySearch.csproj | 22 --
.../README.md | 92 -----
.../FoundryAgents_Step23_LocalMCP/README.md | 48 ---
.../samples/02-agents/FoundryAgents/README.md | 121 -------
.../FoundryAgent_Hosted_MCP/Program.cs | 59 ++--
dotnet/samples/02-agents/README.md | 35 +-
.../Agents/FoundryAgent/Program.cs | 18 +-
.../Declarative/HostedWorkflow/Program.cs | 3 +-
dotnet/samples/03-workflows/README.md | 32 +-
.../A2AServer/HostAgentFactory.cs | 5 +-
dotnet/samples/AGENTS.md | 2 +-
.../AzureAIProjectChatClient.cs | 2 +-
.../AzureAIProjectChatClientExtensions.cs | 254 ++++++++++----
.../AzureAIProjectResponsesChatClient.cs | 34 ++
.../FoundryAITool.cs | 210 ++++++++++++
.../FoundryAgent.cs | 208 ++++++++++++
.../RequestOptionsExtensions.cs | 3 +
.../FoundryMemoryProvider.cs | 18 +-
.../FoundryMemoryProviderScope.cs | 2 +-
.../AzureAgentProvider.cs | 2 +-
.../AIProjectClientAgentRunStreamingTests.cs | 5 +-
.../AIProjectClientAgentRunTests.cs | 3 +
...jectClientAgentStructuredOutputRunTests.cs | 4 +
...tClientChatClientAgentRunStreamingTests.cs | 3 +
.../AIProjectClientChatClientAgentRunTests.cs | 3 +
.../AIProjectClientCreateTests.cs | 10 +-
.../AIProjectClientFixture.cs | 17 +-
...sponsesAgentChatClientRunStreamingTests.cs | 15 +
.../ResponsesAgentChatClientRunTests.cs | 15 +
.../ResponsesAgentExtensionCreateTests.cs | 122 +++++++
.../ResponsesAgentFixture.cs | 187 +++++++++++
.../ResponsesAgentRunStreamingTests.cs | 32 ++
.../ResponsesAgentRunTests.cs | 32 ++
.../ResponsesAgentStructuredOutputRunTests.cs | 100 ++++++
...AzureAIProjectChatClientExtensionsTests.cs | 295 ++++++++++++----
.../AzureAIProjectChatClientTests.cs | 31 +-
.../FoundryAgentTests.cs | 316 ++++++++++++++++++
.../TestDataUtil.cs | 8 +-
.../FoundryMemoryProviderTests.cs | 2 +
.../MessageMergerTests.cs | 4 +-
186 files changed, 3961 insertions(+), 3892 deletions(-)
create mode 100644 docs/decisions/0020-foundry-agent-type-naming.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj => AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Agent_Step00_FoundryAgentLifecycle.csproj} (92%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Agent_Step01_Basics.csproj
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/FoundryAgents_Evaluations_Step01_RedTeaming.csproj => AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Agent_Step02.1_MultiturnConversation.csproj} (70%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Agent_Step02.2_MultiturnWithServerConversations.csproj
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals => AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals}/Program.cs (69%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step05_StructuredOutput => AgentsWithFoundry/Agent_Step05_StructuredOutput}/Program.cs (53%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step06_PersistedConversations => AgentsWithFoundry/Agent_Step06_PersistedConversations}/Program.cs (78%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj => AgentsWithFoundry/Agent_Step07_Observability/Agent_Step07_Observability.csproj} (85%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step07_Observability => AgentsWithFoundry/Agent_Step07_Observability}/Program.cs (71%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj => AgentsWithFoundry/Agent_Step08_DependencyInjection/Agent_Step08_DependencyInjection.csproj} (83%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step23_LocalMCP/FoundryAgents_Step23_LocalMCP.csproj => AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Agent_Step09_UsingMcpClientAsTools.csproj} (84%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/Agent_Step10_UsingImages.csproj
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step10_UsingImages => AgentsWithFoundry/Agent_Step10_UsingImages}/Program.cs (61%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step10_UsingImages/Assets => AgentsWithFoundry/Agent_Step10_UsingImages/assets}/walkway.jpg (100%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/Agent_Step11_AsFunctionTool.csproj
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step11_AsFunctionTool => AgentsWithFoundry/Agent_Step11_AsFunctionTool}/Program.cs (57%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj => AgentsWithFoundry/Agent_Step12_Middleware/Agent_Step12_Middleware.csproj} (81%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step12_Middleware => AgentsWithFoundry/Agent_Step12_Middleware}/Program.cs (70%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step12_Middleware/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step16_FileSearch/FoundryAgents_Step16_FileSearch.csproj => AgentsWithFoundry/Agent_Step13_Plugins/Agent_Step13_Plugins.csproj} (91%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj => AgentsWithFoundry/Agent_Step14_CodeInterpreter/Agent_Step14_CodeInterpreter.csproj} (89%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step14_CodeInterpreter => AgentsWithFoundry/Agent_Step14_CodeInterpreter}/Program.cs (59%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj => AgentsWithFoundry/Agent_Step15_ComputerUse/Agent_Step15_ComputerUse.csproj} (99%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step15_ComputerUse => AgentsWithFoundry/Agent_Step15_ComputerUse}/Assets/cua_browser_search.png (100%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step15_ComputerUse => AgentsWithFoundry/Agent_Step15_ComputerUse}/Assets/cua_search_results.png (100%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step15_ComputerUse => AgentsWithFoundry/Agent_Step15_ComputerUse}/Assets/cua_search_typed.png (100%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step15_ComputerUse => AgentsWithFoundry/Agent_Step15_ComputerUse}/ComputerUseUtil.cs (100%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step15_ComputerUse => AgentsWithFoundry/Agent_Step15_ComputerUse}/Program.cs (61%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj => AgentsWithFoundry/Agent_Step16_FileSearch/Agent_Step16_FileSearch.csproj} (89%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step16_FileSearch => AgentsWithFoundry/Agent_Step16_FileSearch}/Program.cs (69%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj => AgentsWithFoundry/Agent_Step17_OpenAPITools/Agent_Step17_OpenAPITools.csproj} (82%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step17_OpenAPITools => AgentsWithFoundry/Agent_Step17_OpenAPITools}/Program.cs (55%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/README.md
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj => AgentsWithFoundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj} (89%)
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step18_BingCustomSearch => AgentsWithFoundry/Agent_Step18_BingCustomSearch}/Program.cs (54%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step19_SharePoint => AgentsWithFoundry/Agent_Step19_SharePoint}/Program.cs (53%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Agent_Step21_WebSearch.csproj
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Program.cs
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step22_MemorySearch => AgentsWithFoundry/Agent_Step22_MemorySearch}/Program.cs (70%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/Agent_Step23_LocalMCP.csproj
rename dotnet/samples/02-agents/{FoundryAgents/FoundryAgents_Step23_LocalMCP => AgentsWithFoundry/Agent_Step23_LocalMCP}/Program.cs (50%)
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/README.md
create mode 100644 dotnet/samples/02-agents/AgentsWithFoundry/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/FoundryAgents_Evaluations_Step02_SelfReflection.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step16_FileSearch/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/FoundryAgents_Step17_OpenAPITools.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/FoundryAgents_Step18_BingCustomSearch.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/FoundryAgents_Step19_SharePoint.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/FoundryAgents_Step20_MicrosoftFabric.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/FoundryAgents_Step21_WebSearch.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/Program.cs
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/FoundryAgents_Step22_MemorySearch.csproj
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/README.md
delete mode 100644 dotnet/samples/02-agents/FoundryAgents/README.md
create mode 100644 dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectResponsesChatClient.cs
create mode 100644 dotnet/src/Microsoft.Agents.AI.AzureAI/FoundryAITool.cs
create mode 100644 dotnet/src/Microsoft.Agents.AI.AzureAI/FoundryAgent.cs
create mode 100644 dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentChatClientRunStreamingTests.cs
create mode 100644 dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentChatClientRunTests.cs
create mode 100644 dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentExtensionCreateTests.cs
create mode 100644 dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentFixture.cs
create mode 100644 dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentRunStreamingTests.cs
create mode 100644 dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentRunTests.cs
create mode 100644 dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentStructuredOutputRunTests.cs
create mode 100644 dotnet/tests/Microsoft.Agents.AI.AzureAI.UnitTests/FoundryAgentTests.cs
diff --git a/docs/decisions/0020-foundry-agent-type-naming.md b/docs/decisions/0020-foundry-agent-type-naming.md
new file mode 100644
index 0000000000..03d43f64ac
--- /dev/null
+++ b/docs/decisions/0020-foundry-agent-type-naming.md
@@ -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.
diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx
index a5b93487b3..1d0178e615 100644
--- a/dotnet/agent-framework-dotnet.slnx
+++ b/dotnet/agent-framework-dotnet.slnx
@@ -1,4 +1,4 @@
-
+
@@ -121,6 +121,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -143,35 +171,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -318,8 +317,8 @@
-
+
diff --git a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/Program.cs b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/Program.cs
index 5d770ff3fd..0c3e75cf96 100644
--- a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/Program.cs
+++ b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/Program.cs
@@ -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;
diff --git a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs
index 866bbfad31..135d87bffd 100644
--- a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs
+++ b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Client/ServerFunctionApprovalClientAgent.cs
@@ -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
}
diff --git a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs
index ff3e6ffbb1..8c1f27eea9 100644
--- a/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs
+++ b/dotnet/samples/02-agents/AGUI/Step04_HumanInLoop/Server/ServerFunctionApprovalServerAgent.cs
@@ -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();
#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 trackedRequestApprovalToolCalls = new(); // Remote approvals
+ Dictionary 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);
}
}
}
diff --git a/dotnet/samples/02-agents/AGUI/Step05_StateManagement/Client/StatefulAgent.cs b/dotnet/samples/02-agents/AGUI/Step05_StateManagement/Client/StatefulAgent.cs
index 41c94d5686..8a8062befe 100644
--- a/dotnet/samples/02-agents/AGUI/Step05_StateManagement/Client/StatefulAgent.cs
+++ b/dotnet/samples/02-agents/AGUI/Step05_StateManagement/Client/StatefulAgent.cs
@@ -72,10 +72,9 @@ internal sealed class StatefulAgent : 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;
}
diff --git a/dotnet/samples/02-agents/AgentProviders/Agent_With_AzureAIProject/Program.cs b/dotnet/samples/02-agents/AgentProviders/Agent_With_AzureAIProject/Program.cs
index aab95d5b38..b2cd14f68a 100644
--- a/dotnet/samples/02-agents/AgentProviders/Agent_With_AzureAIProject/Program.cs
+++ b/dotnet/samples/02-agents/AgentProviders/Agent_With_AzureAIProject/Program.cs
@@ -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 =
// 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()!;
+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}");
diff --git a/dotnet/samples/02-agents/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs b/dotnet/samples/02-agents/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs
index 3d9c715588..04df345cd6 100644
--- a/dotnet/samples/02-agents/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs
+++ b/dotnet/samples/02-agents/AgentWithAnthropic/Agent_Anthropic_Step01_Running/Program.cs
@@ -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."));
diff --git a/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step04_MemoryUsingFoundry/Program.cs b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step04_MemoryUsingFoundry/Program.cs
index 914eda330a..d6410d3308 100644
--- a/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step04_MemoryUsingFoundry/Program.cs
+++ b/dotnet/samples/02-agents/AgentWithMemory/AgentWithMemory_Step04_MemoryUsingFoundry/Program.cs
@@ -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]
});
diff --git a/dotnet/samples/02-agents/AgentWithMemory/README.md b/dotnet/samples/02-agents/AgentWithMemory/README.md
index 87818c77d6..aa95012f68 100644
--- a/dotnet/samples/02-agents/AgentWithMemory/README.md
+++ b/dotnet/samples/02-agents/AgentWithMemory/README.md
@@ -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.
diff --git a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs
index e2bd31055a..e82f420105 100644
--- a/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs
+++ b/dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step01_Running/Program.cs
@@ -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 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."));
diff --git a/dotnet/samples/02-agents/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs b/dotnet/samples/02-agents/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs
index c356bccbd9..e049618a72 100644
--- a/dotnet/samples/02-agents/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs
+++ b/dotnet/samples/02-agents/AgentWithRAG/AgentWithRAG_Step04_FoundryServiceRAG/Program.cs
@@ -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 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();
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step07_AsMcpTool/Program.cs b/dotnet/samples/02-agents/Agents/Agent_Step07_AsMcpTool/Program.cs
index 7bc6478968..a63063b6a5 100644
--- a/dotnet/samples/02-agents/Agents/Agent_Step07_AsMcpTool/Program.cs
+++ b/dotnet/samples/02-agents/Agents/Agent_Step07_AsMcpTool/Program.cs
@@ -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.
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Program.cs b/dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Program.cs
index 18969ed66e..bab09bc886 100644
--- a/dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Program.cs
+++ b/dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Program.cs
@@ -189,9 +189,9 @@ async Task PIIMiddleware(IEnumerable 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();
+}
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step15_DeepResearch/Program.cs b/dotnet/samples/02-agents/Agents/Agent_Step15_DeepResearch/Program.cs
index 7a76f73455..11d3f561f4 100644
--- a/dotnet/samples/02-agents/Agents/Agent_Step15_DeepResearch/Program.cs
+++ b/dotnet/samples/02-agents/Agents/Agent_Step15_DeepResearch/Program.cs
@@ -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.
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step15_DeepResearch/README.md b/dotnet/samples/02-agents/Agents/Agent_Step15_DeepResearch/README.md
index dc24ba4554..1848b10826 100644
--- a/dotnet/samples/02-agents/Agents/Agent_Step15_DeepResearch/README.md
+++ b/dotnet/samples/02-agents/Agents/Agent_Step15_DeepResearch/README.md
@@ -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//resourceGroups//providers//accounts//projects//connections/
+/subscriptions//resourceGroups//providers/Microsoft.CognitiveServices/accounts//projects//connections/
```
+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//resourceGroups//providers/Microsoft.CognitiveServices/accounts//projects//connections/"
# Optional, defaults to o3-deep-research
$env:AZURE_AI_REASONING_DEPLOYMENT_NAME="o3-deep-research"
diff --git a/dotnet/samples/02-agents/Agents/Agent_Step17_AdditionalAIContext/Program.cs b/dotnet/samples/02-agents/Agents/Agent_Step17_AdditionalAIContext/Program.cs
index e3913c9f0e..0fd21833e1 100644
--- a/dotnet/samples/02-agents/Agents/Agent_Step17_AdditionalAIContext/Program.cs
+++ b/dotnet/samples/02-agents/Agents/Agent_Step17_AdditionalAIContext/Program.cs
@@ -24,12 +24,12 @@ var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT
Func> 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 GetTodoItems(AgentSession? session)
- => session?.StateBag.GetValue>(nameof(TodoListAIContextProvider)) ?? new List();
+ => session?.StateBag.GetValue>(nameof(TodoListAIContextProvider)) ?? [];
private static void SetTodoItems(AgentSession? session, List items)
=> session?.StateBag.SetValue(nameof(TodoListAIContextProvider), items);
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Agent_Step00_FoundryAgentLifecycle.csproj
similarity index 92%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Agent_Step00_FoundryAgentLifecycle.csproj
index daf7e24494..d861331d9f 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/FoundryAgents_Step03_UsingFunctionTools.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Agent_Step00_FoundryAgentLifecycle.csproj
@@ -1,4 +1,4 @@
-
+Exe
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Program.cs
new file mode 100644
index 0000000000..c6b2d5c764
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/Program.cs
@@ -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);
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/README.md
new file mode 100644
index 0000000000..738a1d2e42
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step00_FoundryAgentLifecycle/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Agent_Step01_Basics.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Agent_Step01_Basics.csproj
new file mode 100644
index 0000000000..7367c1d2f8
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Agent_Step01_Basics.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Program.cs
new file mode 100644
index 0000000000..cd89116db7
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/Program.cs
@@ -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."));
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/README.md
new file mode 100644
index 0000000000..88eebb2a82
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step01_Basics/README.md
@@ -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.
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/FoundryAgents_Evaluations_Step01_RedTeaming.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Agent_Step02.1_MultiturnConversation.csproj
similarity index 70%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/FoundryAgents_Evaluations_Step01_RedTeaming.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Agent_Step02.1_MultiturnConversation.csproj
index d77c0bb0d3..5e73fd236a 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/FoundryAgents_Evaluations_Step01_RedTeaming.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Agent_Step02.1_MultiturnConversation.csproj
@@ -9,8 +9,7 @@
-
-
+
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Program.cs
new file mode 100644
index 0000000000..15b880102f
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/Program.cs
@@ -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));
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/README.md
new file mode 100644
index 0000000000..a895981952
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.1_MultiturnConversation/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Agent_Step02.2_MultiturnWithServerConversations.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Agent_Step02.2_MultiturnWithServerConversations.csproj
new file mode 100644
index 0000000000..7367c1d2f8
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Agent_Step02.2_MultiturnWithServerConversations.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Program.cs
new file mode 100644
index 0000000000..7a66555c18
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/Program.cs
@@ -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();
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/README.md
new file mode 100644
index 0000000000..9d35133b39
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step02.2_MultiturnWithServerConversations/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj
new file mode 100644
index 0000000000..7367c1d2f8
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Agent_Step03_UsingFunctionTools.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Program.cs
new file mode 100644
index 0000000000..7935835a24
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/Program.cs
@@ -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);
+}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/README.md
new file mode 100644
index 0000000000..9aa2a4ee69
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step03_UsingFunctionTools/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj
new file mode 100644
index 0000000000..7367c1d2f8
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/Agent_Step04_UsingFunctionToolsWithApprovals.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/Program.cs
similarity index 69%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/Program.cs
index 08051a500e..9a85dba83b 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/Program.cs
@@ -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 approvalRequests = response.Messages.SelectMany(m => m.Contents).OfType().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().ToList();
}
Console.WriteLine($"\nAgent: {response}");
-
-// Cleanup by agent name removes the agent version created.
-await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/README.md
new file mode 100644
index 0000000000..430c57548d
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step04_UsingFunctionToolsWithApprovals/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj
new file mode 100644
index 0000000000..7367c1d2f8
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/Agent_Step05_StructuredOutput.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/Program.cs
similarity index 53%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/Program.cs
index 3c02a4cec2..28cd4cf6bc 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/Program.cs
@@ -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()
- }
- });
+ ModelId = deploymentName,
+ Instructions = "You are a helpful assistant that extracts structured information about people.",
+ ResponseFormat = Microsoft.Extensions.AI.ChatResponseFormat.ForJsonSchema()
+ }
+});
-// 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 response = await agent.RunAsync("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()
- }
- });
+// Invoke the agent with streaming support, then deserialize the assembled response.
+IAsyncEnumerable 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 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((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
{
///
- /// 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.
///
[Description("Information about a person including their name, age, and occupation")]
public class PersonInfo
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/README.md
new file mode 100644
index 0000000000..f5421b3f64
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step05_StructuredOutput/README.md
@@ -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()` 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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj
new file mode 100644
index 0000000000..7367c1d2f8
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/Agent_Step06_PersistedConversations.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/Program.cs
similarity index 78%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/Program.cs
index d8a5a7cd35..c9774cb1bf 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/Program.cs
@@ -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);
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/README.md
new file mode 100644
index 0000000000..a8cfda07ca
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step06_PersistedConversations/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/Agent_Step07_Observability.csproj
similarity index 85%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/Agent_Step07_Observability.csproj
index 5ceeabb204..1189939bc0 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/FoundryAgents_Step07_Observability.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/Agent_Step07_Observability.csproj
@@ -9,8 +9,6 @@
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/Program.cs
similarity index 71%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/Program.cs
index 257e24859f..68bfb91af0 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/Program.cs
@@ -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();
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/README.md
new file mode 100644
index 0000000000..cb3bb729ff
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step07_Observability/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/Agent_Step08_DependencyInjection.csproj
similarity index 83%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/Agent_Step08_DependencyInjection.csproj
index f1812befeb..72af634725 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/FoundryAgents_Step08_DependencyInjection.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/Agent_Step08_DependencyInjection.csproj
@@ -11,8 +11,6 @@
-
-
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/Program.cs
new file mode 100644
index 0000000000..52a7d73132
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/Program.cs
@@ -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();
+
+// Build and run the host.
+using IHost host = builder.Build();
+await host.RunAsync().ConfigureAwait(false);
+
+namespace SampleApp
+{
+ ///
+ /// A sample service that uses an AI agent to respond to user input.
+ ///
+ 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;
+ }
+ }
+}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/README.md
new file mode 100644
index 0000000000..c9ad936fd6
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step08_DependencyInjection/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/FoundryAgents_Step23_LocalMCP.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Agent_Step09_UsingMcpClientAsTools.csproj
similarity index 84%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/FoundryAgents_Step23_LocalMCP.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Agent_Step09_UsingMcpClientAsTools.csproj
index 1e3e6f57e3..96cdf948fe 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/FoundryAgents_Step23_LocalMCP.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Agent_Step09_UsingMcpClientAsTools.csproj
@@ -6,16 +6,15 @@
enableenable
- $(NoWarn);CA1812
-
+
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Program.cs
new file mode 100644
index 0000000000..87f80297af
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/Program.cs
@@ -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 mcpTools = await mcpClient.ListToolsAsync();
+Console.WriteLine($"MCP tools available: {string.Join(", ", mcpTools.Select(t => t.Name))}");
+
+List agentTools = [.. mcpTools.Cast()];
+
+// 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)}");
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/README.md
new file mode 100644
index 0000000000..72437e0802
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step09_UsingMcpClientAsTools/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/Agent_Step10_UsingImages.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/Agent_Step10_UsingImages.csproj
new file mode 100644
index 0000000000..6064cf9334
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/Agent_Step10_UsingImages.csproj
@@ -0,0 +1,21 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/Program.cs
similarity index 61%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/Program.cs
index d810c8046a..2fdc150be9 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/Program.cs
@@ -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();
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/README.md
new file mode 100644
index 0000000000..370bf896cf
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/Assets/walkway.jpg b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/assets/walkway.jpg
similarity index 100%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/Assets/walkway.jpg
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step10_UsingImages/assets/walkway.jpg
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/Agent_Step11_AsFunctionTool.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/Agent_Step11_AsFunctionTool.csproj
new file mode 100644
index 0000000000..7367c1d2f8
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/Agent_Step11_AsFunctionTool.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/Program.cs
similarity index 57%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/Program.cs
index 585725322e..3715ab194f 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/Program.cs
@@ -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);
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/README.md
new file mode 100644
index 0000000000..7d361305b9
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step11_AsFunctionTool/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step12_Middleware/Agent_Step12_Middleware.csproj
similarity index 81%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step12_Middleware/Agent_Step12_Middleware.csproj
index 9f29a8d7e6..b30baccd54 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/FoundryAgents_Step12_Middleware.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step12_Middleware/Agent_Step12_Middleware.csproj
@@ -3,15 +3,13 @@
Exenet10.0
-
+
enableenable
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step12_Middleware/Program.cs
similarity index 70%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step12_Middleware/Program.cs
index 824e1507b3..e37bf89639 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step12_Middleware/Program.cs
@@ -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
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/Program.cs
new file mode 100644
index 0000000000..3af63090c5
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/Program.cs
@@ -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();
+services.AddSingleton();
+services.AddSingleton(); // 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().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
+{
+ ///
+ /// The agent plugin that provides weather and current time information.
+ ///
+ internal sealed class AgentPlugin
+ {
+ private readonly WeatherProvider _weatherProvider;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The weather provider to get weather information.
+ public AgentPlugin(WeatherProvider weatherProvider)
+ {
+ this._weatherProvider = weatherProvider;
+ }
+
+ ///
+ /// Gets the weather information for the specified location.
+ ///
+ ///
+ /// This method demonstrates how to use the dependency that was injected into the plugin class.
+ ///
+ /// The location to get the weather for.
+ /// The weather information for the specified location.
+ public string GetWeather(string location)
+ {
+ return this._weatherProvider.GetWeather(location);
+ }
+
+ ///
+ /// Gets the current date and time for the specified location.
+ ///
+ ///
+ /// This method demonstrates how to resolve a dependency using the service provider passed to the method.
+ ///
+ /// The service provider to resolve the .
+ /// The location to get the current time for.
+ /// The current date and time as a .
+ public DateTimeOffset GetCurrentTime(IServiceProvider sp, string location)
+ {
+ CurrentTimeProvider currentTimeProvider = sp.GetRequiredService();
+ return currentTimeProvider.GetCurrentTime(location);
+ }
+
+ ///
+ /// Returns the functions provided by this plugin.
+ ///
+ ///
+ /// 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.
+ ///
+ /// The functions provided by this plugin.
+ public IEnumerable 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";
+
+ ///
+ /// The weather provider that returns weather information.
+ ///
+ ///
+ /// Gets the weather information for the specified location.
+ ///
+ ///
+ /// The weather information is hardcoded for demonstration purposes.
+ /// In a real application, this could call a weather API to get actual weather data.
+ ///
+ /// The location to get the weather for.
+ /// The weather information for the specified location.
+ public string GetWeather(string location)
+ {
+ return $"The weather in {location} is {this._weatherSummary}.";
+ }
+ }
+
+ internal sealed class CurrentTimeProvider
+ {
+ private readonly TimeProvider _timeProvider = TimeProvider.System;
+
+ ///
+ /// Provides the current date and time.
+ ///
+ ///
+ /// This class returns the current date and time using the system's clock.
+ ///
+ ///
+ /// Gets the current date and time.
+ ///
+ /// The location to get the current time for (not used in this implementation).
+ /// The current date and time as a .
+ public DateTimeOffset GetCurrentTime(string location)
+ {
+ return this._timeProvider.GetLocalNow();
+ }
+ }
+}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/README.md
new file mode 100644
index 0000000000..8cc2f59116
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step13_Plugins/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/Agent_Step14_CodeInterpreter.csproj
similarity index 89%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/Agent_Step14_CodeInterpreter.csproj
index daf7e24494..e11688b6ba 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/FoundryAgents_Step04_UsingFunctionToolsWithApprovals.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/Agent_Step14_CodeInterpreter.csproj
@@ -9,7 +9,6 @@
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/Program.cs
similarity index 59%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/Program.cs
index 5a27daed12..8d7f598a4a 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/Program.cs
@@ -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().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);
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/README.md
new file mode 100644
index 0000000000..1a8cfc8aae
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step14_CodeInterpreter/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Agent_Step15_ComputerUse.csproj
similarity index 99%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Agent_Step15_ComputerUse.csproj
index 041c72c43e..f739f56123 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/FoundryAgents_Step15_ComputerUse.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Agent_Step15_ComputerUse.csproj
@@ -29,5 +29,5 @@
Always
-
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_browser_search.png b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Assets/cua_browser_search.png
similarity index 100%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_browser_search.png
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Assets/cua_browser_search.png
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_results.png b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Assets/cua_search_results.png
similarity index 100%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_results.png
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Assets/cua_search_results.png
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_typed.png b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Assets/cua_search_typed.png
similarity index 100%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Assets/cua_search_typed.png
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Assets/cua_search_typed.png
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/ComputerUseUtil.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/ComputerUseUtil.cs
similarity index 100%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/ComputerUseUtil.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/ComputerUseUtil.cs
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Program.cs
similarity index 61%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Program.cs
index 7f6382d085..22f03e27b3 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/Program.cs
@@ -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 followUpMessages = [];
-
- // Re-send all response output items as an assistant message so the API has full context
- List 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);
}
}
}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/README.md
new file mode 100644
index 0000000000..ecaa18e10f
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step15_ComputerUse/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/Agent_Step16_FileSearch.csproj
similarity index 89%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/Agent_Step16_FileSearch.csproj
index daf7e24494..e11688b6ba 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/FoundryAgents_Step01.2_Running.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/Agent_Step16_FileSearch.csproj
@@ -9,7 +9,6 @@
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step16_FileSearch/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/Program.cs
similarity index 69%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step16_FileSearch/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/Program.cs
index 5371903a9f..c01a951df4 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step16_FileSearch/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/Program.cs
@@ -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 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 CreateAgentWithNativeSDK()
-{
- return await aiProjectClient.CreateAIAgentAsync(
- name: "FileSearchAgent-NATIVE",
- creationOptions: new AgentVersionCreationOptions(
- new PromptAgentDefinition(model: deploymentName)
- {
- Instructions = AgentInstructions,
- Tools = {
- ResponseTool.CreateFileSearchTool(vectorStoreIds: [vectorStoreId])
- }
- })
- );
-}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/README.md
new file mode 100644
index 0000000000..5ce7f11cda
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step16_FileSearch/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/Agent_Step17_OpenAPITools.csproj
similarity index 82%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/Agent_Step17_OpenAPITools.csproj
index 89b9d8ddc0..4602e9c9e0 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/FoundryAgents_Step01.1_Basics.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/Agent_Step17_OpenAPITools.csproj
@@ -6,15 +6,14 @@
enableenable
- $(NoWarn);IDE0059
-
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/Program.cs
similarity index 55%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/Program.cs
index ebf66e6c2c..5cc2720dd9 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/Program.cs
@@ -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 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 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"
+ };
}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/README.md
new file mode 100644
index 0000000000..52a11ec1dd
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step17_OpenAPITools/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj
similarity index 89%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj
index daf7e24494..e11688b6ba 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/FoundryAgents_Step02_MultiturnConversation.csproj
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/Agent_Step18_BingCustomSearch.csproj
@@ -9,7 +9,6 @@
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/Program.cs
similarity index 54%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/Program.cs
index 98ea576226..4ab548403d 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/Program.cs
@@ -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 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 CreateAgentWithNativeSDKAsync()
-{
- return await aiProjectClient.CreateAIAgentAsync(
- name: "BingCustomSearchAgent-NATIVE",
- creationOptions: new AgentVersionCreationOptions(
- new PromptAgentDefinition(model: deploymentName)
- {
- Instructions = AgentInstructions,
- Tools = {
- (ResponseTool)AgentTool.CreateBingCustomSearchTool(bingCustomSearchToolParameters),
- }
- })
- );
-}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/README.md
new file mode 100644
index 0000000000..fc48fd8744
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step18_BingCustomSearch/README.md
@@ -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//connections/` 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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj
new file mode 100644
index 0000000000..e11688b6ba
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/Agent_Step19_SharePoint.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/Program.cs
similarity index 53%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/Program.cs
index ad6a08abaa..aafca6b8bd 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/Program.cs
@@ -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 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 CreateAgentWithNativeSDKAsync()
-{
- return await aiProjectClient.CreateAIAgentAsync(
- name: "SharePointAgent-NATIVE",
- creationOptions: new AgentVersionCreationOptions(
- new PromptAgentDefinition(model: deploymentName)
- {
- Instructions = AgentInstructions,
- Tools = { AgentTool.CreateSharepointTool(sharepointOptions) }
- })
- );
-}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/README.md
new file mode 100644
index 0000000000..bfaacee860
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step19_SharePoint/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj
new file mode 100644
index 0000000000..e11688b6ba
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Agent_Step20_MicrosoftFabric.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Program.cs
new file mode 100644
index 0000000000..7c49afa7ee
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/Program.cs
@@ -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);
+}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/README.md
new file mode 100644
index 0000000000..4a4d31e151
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step20_MicrosoftFabric/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Agent_Step21_WebSearch.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Agent_Step21_WebSearch.csproj
new file mode 100644
index 0000000000..e11688b6ba
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Agent_Step21_WebSearch.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Program.cs
new file mode 100644
index 0000000000..20d74b0401
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/Program.cs
@@ -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}}
+ """);
+ }
+}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/README.md
new file mode 100644
index 0000000000..1a9d80106d
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step21_WebSearch/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj
new file mode 100644
index 0000000000..4602e9c9e0
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/Agent_Step22_MemorySearch.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/Program.cs
similarity index 70%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/Program.cs
index 60452b7d19..9e1a902f29 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/Program.cs
@@ -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 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 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();
}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/README.md
new file mode 100644
index 0000000000..b8020553af
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step22_MemorySearch/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/Agent_Step23_LocalMCP.csproj b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/Agent_Step23_LocalMCP.csproj
new file mode 100644
index 0000000000..e51f57c439
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/Agent_Step23_LocalMCP.csproj
@@ -0,0 +1,20 @@
+
+
+
+ Exe
+ net10.0
+
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/Program.cs b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/Program.cs
similarity index 50%
rename from dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/Program.cs
rename to dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/Program.cs
index d41771ef37..c9f8c0060b 100644
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/Program.cs
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/Program.cs
@@ -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 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}");
-///
-/// Wraps an MCP tool to log when it is invoked locally,
-/// confirming that the MCP call is happening client-side.
-///
-internal sealed class LoggingMcpTool(AIFunction innerFunction) : DelegatingAIFunction(innerFunction)
+namespace SampleApp
{
- protected override ValueTask InvokeCoreAsync(AIFunctionArguments arguments, CancellationToken cancellationToken)
+ ///
+ /// Wraps an MCP tool to log when it is invoked locally,
+ /// confirming that the MCP call is happening client-side.
+ ///
+ 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 InvokeCoreAsync(AIFunctionArguments arguments, CancellationToken cancellationToken)
+ {
+ Console.WriteLine($" >> [LOCAL MCP] Invoking tool '{this.Name}' locally...");
+ return base.InvokeCoreAsync(arguments, cancellationToken);
+ }
}
}
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/README.md
new file mode 100644
index 0000000000..84456df2b7
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/Agent_Step23_LocalMCP/README.md
@@ -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
+```
diff --git a/dotnet/samples/02-agents/AgentsWithFoundry/README.md b/dotnet/samples/02-agents/AgentsWithFoundry/README.md
new file mode 100644
index 0000000000..b5802053b3
--- /dev/null
+++ b/dotnet/samples/02-agents/AgentsWithFoundry/README.md
@@ -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
+```
\ No newline at end of file
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/Program.cs
deleted file mode 100644
index 1e1e48d54b..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/Program.cs
+++ /dev/null
@@ -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));
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/README.md
deleted file mode 100644
index 24e4a62b35..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step01_RedTeaming/README.md
+++ /dev/null
@@ -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
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/FoundryAgents_Evaluations_Step02_SelfReflection.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/FoundryAgents_Evaluations_Step02_SelfReflection.csproj
deleted file mode 100644
index 646cd75532..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/FoundryAgents_Evaluations_Step02_SelfReflection.csproj
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/Program.cs
deleted file mode 100644
index 8f8c9fa4ee..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/Program.cs
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample demonstrates how to use Microsoft.Extensions.AI.Evaluation.Quality to evaluate
-// an Agent Framework agent's response quality with a self-reflection loop.
-//
-// It uses GroundednessEvaluator, RelevanceEvaluator, and CoherenceEvaluator to score responses,
-// then iteratively asks the agent to improve based on evaluation feedback.
-//
-// Based on: Reflexion: Language Agents with Verbal Reinforcement Learning (NeurIPS 2023)
-// Reference: https://arxiv.org/abs/2303.11366
-//
-// For more details, see:
-// https://learn.microsoft.com/dotnet/ai/evaluation/libraries
-
-using Azure.AI.OpenAI;
-using Azure.AI.Projects;
-using Azure.Identity;
-using Microsoft.Agents.AI;
-using Microsoft.Extensions.AI;
-using Microsoft.Extensions.AI.Evaluation;
-using Microsoft.Extensions.AI.Evaluation.Quality;
-using Microsoft.Extensions.AI.Evaluation.Safety;
-
-using ChatMessage = Microsoft.Extensions.AI.ChatMessage;
-using ChatRole = Microsoft.Extensions.AI.ChatRole;
-
-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 openAiEndpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set.");
-string evaluatorDeploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? deploymentName;
-
-Console.WriteLine("=" + new string('=', 79));
-Console.WriteLine("SELF-REFLECTION EVALUATION SAMPLE");
-Console.WriteLine("=" + new string('=', 79));
-Console.WriteLine();
-
-// Initialize Azure credentials and client
-// 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);
-
-// Set up the LLM-based chat client for quality evaluators
-IChatClient chatClient = new AzureOpenAIClient(new Uri(openAiEndpoint), credential)
- .GetChatClient(evaluatorDeploymentName)
- .AsIChatClient();
-
-// Configure evaluation: quality evaluators use the LLM, safety evaluators use Azure AI Foundry
-ContentSafetyServiceConfiguration safetyConfig = new(
- credential: credential,
- endpoint: new Uri(endpoint));
-
-ChatConfiguration chatConfiguration = safetyConfig.ToChatConfiguration(
- originalChatConfiguration: new ChatConfiguration(chatClient));
-
-// Create a test agent
-AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
- name: "KnowledgeAgent",
- model: deploymentName,
- instructions: "You are a helpful assistant. Answer questions accurately based on the provided context.");
-Console.WriteLine($"Created agent: {agent.Name}");
-Console.WriteLine();
-
-// Example question and grounding context
-const string Question = """
- What are the main benefits of using Azure AI Foundry for building AI applications?
- """;
-
-const string Context = """
- Azure AI Foundry is a comprehensive platform for building, deploying, and managing AI applications.
- Key benefits include:
- 1. Unified development environment with support for multiple AI frameworks and models
- 2. Built-in safety and security features including content filtering and red teaming tools
- 3. Scalable infrastructure that handles deployment and monitoring automatically
- 4. Integration with Azure services like Azure OpenAI, Cognitive Services, and Machine Learning
- 5. Evaluation tools for assessing model quality, safety, and performance
- 6. Support for RAG (Retrieval-Augmented Generation) patterns with vector search
- 7. Enterprise-grade compliance and governance features
- """;
-
-Console.WriteLine("Question:");
-Console.WriteLine(Question);
-Console.WriteLine();
-
-// Run evaluations
-try
-{
- await RunSelfReflectionWithGroundedness(agent, Question, Context, chatConfiguration);
- await RunQualityEvaluation(agent, Question, Context, chatConfiguration);
- await RunCombinedQualityAndSafetyEvaluation(agent, Question, chatConfiguration);
-}
-finally
-{
- // Cleanup
- await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
- Console.WriteLine();
- Console.WriteLine("Cleanup: Agent deleted.");
-}
-
-// ============================================================================
-// Implementation Functions
-// ============================================================================
-
-static async Task RunSelfReflectionWithGroundedness(
- AIAgent agent, string question, string context, ChatConfiguration chatConfiguration)
-{
- Console.WriteLine("Running Self-Reflection with Groundedness Evaluation...");
- Console.WriteLine();
-
- GroundednessEvaluator groundednessEvaluator = new();
- GroundednessEvaluatorContext groundingContext = new(context);
-
- const int MaxReflections = 3;
- double bestScore = 0;
-
- string currentPrompt = $"Context: {context}\n\nQuestion: {question}";
-
- for (int i = 0; i < MaxReflections; i++)
- {
- Console.WriteLine($"Iteration {i + 1}/{MaxReflections}:");
- Console.WriteLine(new string('-', 40));
-
- // Create a new session for each reflection iteration so that
- // conversation context does not carry over between runs. This keeps
- // each evaluation independent and avoids biasing groundedness scores.
- AgentSession session = await agent.CreateSessionAsync();
- AgentResponse agentResponse = await agent.RunAsync(currentPrompt, session);
- string responseText = agentResponse.Text;
-
- Console.WriteLine($"Response: {responseText[..Math.Min(150, responseText.Length)]}...");
-
- List messages =
- [
- new(ChatRole.User, currentPrompt),
- ];
- ChatResponse chatResponse = new(new ChatMessage(ChatRole.Assistant, responseText));
-
- EvaluationResult result = await groundednessEvaluator.EvaluateAsync(
- messages,
- chatResponse,
- chatConfiguration,
- additionalContext: [groundingContext]);
-
- NumericMetric groundedness = result.Get(GroundednessEvaluator.GroundednessMetricName);
- double score = groundedness.Value ?? 0;
- string rating = groundedness.Interpretation?.Rating.ToString() ?? "N/A";
-
- Console.WriteLine($"Groundedness score: {score:F1}/5 (Rating: {rating})");
- Console.WriteLine();
-
- if (score > bestScore)
- {
- bestScore = score;
- }
-
- if (score >= 4.0 || i == MaxReflections - 1)
- {
- if (score >= 4.0)
- {
- Console.WriteLine("Good groundedness achieved!");
- }
-
- break;
- }
-
- // Ask for improvement in the next iteration, including the previous response
- // so the LLM knows what to improve on (each iteration uses a new session).
- currentPrompt = $"""
- Context: {context}
-
- Your previous answer scored {score}/5 on groundedness.
- Your previous answer was:
- {responseText}
-
- Please improve your answer to be more grounded in the provided context.
- Only include information that is directly supported by the context.
-
- Question: {question}
- """;
- Console.WriteLine("Requesting improvement...");
- Console.WriteLine();
- }
-
- Console.WriteLine($"Best groundedness score: {bestScore:F1}/5");
- Console.WriteLine(new string('=', 80));
- Console.WriteLine();
-}
-
-static async Task RunQualityEvaluation(
- AIAgent agent, string question, string context, ChatConfiguration chatConfiguration)
-{
- Console.WriteLine("Running Quality Evaluation (Relevance, Coherence, Groundedness)...");
- Console.WriteLine();
-
- IEvaluator[] evaluators =
- [
- new RelevanceEvaluator(),
- new CoherenceEvaluator(),
- new GroundednessEvaluator(),
- ];
-
- CompositeEvaluator compositeEvaluator = new(evaluators);
- GroundednessEvaluatorContext groundingContext = new(context);
-
- string prompt = $"Context: {context}\n\nQuestion: {question}";
-
- AgentSession session = await agent.CreateSessionAsync();
- AgentResponse agentResponse = await agent.RunAsync(prompt, session);
- string responseText = agentResponse.Text;
-
- Console.WriteLine($"Response: {responseText[..Math.Min(150, responseText.Length)]}...");
- Console.WriteLine();
-
- List messages =
- [
- new(ChatRole.User, prompt),
- ];
- ChatResponse chatResponse = new(new ChatMessage(ChatRole.Assistant, responseText));
-
- EvaluationResult result = await compositeEvaluator.EvaluateAsync(
- messages,
- chatResponse,
- chatConfiguration,
- additionalContext: [groundingContext]);
-
- foreach (EvaluationMetric metric in result.Metrics.Values)
- {
- if (metric is NumericMetric n)
- {
- string rating = n.Interpretation?.Rating.ToString() ?? "N/A";
- Console.WriteLine($" {n.Name,-20} Score: {n.Value:F1}/5 Rating: {rating}");
- }
- }
-
- Console.WriteLine(new string('=', 80));
- Console.WriteLine();
-}
-
-static async Task RunCombinedQualityAndSafetyEvaluation(
- AIAgent agent, string question, ChatConfiguration chatConfiguration)
-{
- Console.WriteLine("Running Combined Quality + Safety Evaluation...");
- Console.WriteLine();
-
- IEvaluator[] evaluators =
- [
- new RelevanceEvaluator(),
- new CoherenceEvaluator(),
- new ContentHarmEvaluator(),
- new ProtectedMaterialEvaluator(),
- ];
-
- CompositeEvaluator compositeEvaluator = new(evaluators);
-
- AgentSession session = await agent.CreateSessionAsync();
- AgentResponse agentResponse = await agent.RunAsync(question, session);
- string responseText = agentResponse.Text;
-
- Console.WriteLine($"Response: {responseText[..Math.Min(150, responseText.Length)]}...");
- Console.WriteLine();
-
- List messages =
- [
- new(ChatRole.User, question), // No context in this evaluation — testing quality and safety on raw question
- ];
- ChatResponse chatResponse = new(new ChatMessage(ChatRole.Assistant, responseText));
-
- EvaluationResult result = await compositeEvaluator.EvaluateAsync(
- messages,
- chatResponse,
- chatConfiguration);
-
- Console.WriteLine("Quality Metrics:");
- foreach (EvaluationMetric metric in result.Metrics.Values)
- {
- if (metric is NumericMetric n)
- {
- string rating = n.Interpretation?.Rating.ToString() ?? "N/A";
- bool failed = n.Interpretation?.Failed ?? false;
- Console.WriteLine($" {n.Name,-25} Score: {n.Value:F1,-6} Rating: {rating,-15} Failed: {failed}");
- }
- else if (metric is BooleanMetric b)
- {
- string rating = b.Interpretation?.Rating.ToString() ?? "N/A";
- bool failed = b.Interpretation?.Failed ?? false;
- Console.WriteLine($" {b.Name,-25} Value: {b.Value,-6} Rating: {rating,-15} Failed: {failed}");
- }
- }
-
- Console.WriteLine(new string('=', 80));
-}
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/README.md
deleted file mode 100644
index d71eeca6af..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection/README.md
+++ /dev/null
@@ -1,118 +0,0 @@
-# Self-Reflection Evaluation with Groundedness Assessment
-
-This sample demonstrates the self-reflection pattern using Agent Framework with `Microsoft.Extensions.AI.Evaluation.Quality` evaluators. The agent iteratively improves its responses based on real groundedness evaluation scores.
-
-For details on the self-reflection approach, see [Reflexion: Language Agents with Verbal Reinforcement Learning](https://arxiv.org/abs/2303.11366) (NeurIPS 2023).
-
-## What this sample demonstrates
-
-- Self-reflection loop that improves responses using real `GroundednessEvaluator` scores
-- Using `RelevanceEvaluator` and `CoherenceEvaluator` for multi-metric quality assessment
-- Combining quality and safety evaluators with `CompositeEvaluator`
-- Configuring `ContentSafetyServiceConfiguration` for safety evaluators alongside LLM-based quality evaluators
-- Tracking improvement across iterations
-
-## 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)
-
-**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
-
-### Azure Resources Required
-
-1. **Azure AI Hub and Project**: Create these in the Azure Portal
- - Follow: https://learn.microsoft.com/azure/ai-foundry/how-to/create-projects
-2. **Azure OpenAI Deployment**: Deploy a model (e.g., gpt-4o or gpt-4o-mini)
- - Agent model: Used to generate responses
- - Evaluator model: Quality evaluators use an LLM; best results with GPT-4o
-3. **Azure CLI**: Install and authenticate with `az login`
-
-### Environment Variables
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_AI_PROJECT_ENDPOINT="https://your-project.api.azureml.ms" # Azure Foundry project endpoint
-$env:AZURE_OPENAI_ENDPOINT="https://your-openai.openai.azure.com/" # Azure OpenAI endpoint (for quality evaluators)
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Model deployment name
-```
-
-**Note**: For best evaluation results, use GPT-4o or GPT-4o-mini as the evaluator model. The groundedness evaluator has been tested and tuned for these models.
-
-## Run the sample
-
-Navigate to the sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Evaluations_Step02_SelfReflection
-dotnet run
-```
-
-## Expected behavior
-
-The sample runs three evaluation scenarios:
-
-### 1. Self-Reflection with Groundedness
-- Asks a question with grounding context
-- Evaluates response groundedness using `GroundednessEvaluator`
-- If score is below 4/5, asks the agent to improve with feedback
-- Repeats up to 3 iterations
-- Tracks and reports the best score achieved
-
-### 2. Quality Evaluation
-- Evaluates a single response with multiple quality evaluators:
- - `RelevanceEvaluator` — is the response relevant to the question?
- - `CoherenceEvaluator` — is the response logically coherent?
- - `GroundednessEvaluator` — is the response grounded in the provided context?
-
-### 3. Combined Quality + Safety Evaluation
-- Runs both quality and safety evaluators together:
- - `RelevanceEvaluator`, `CoherenceEvaluator` (quality)
- - `ContentHarmEvaluator` (safety — violence, hate, sexual, self-harm)
- - `ProtectedMaterialEvaluator` (safety — copyrighted content detection)
-
-## Understanding the Evaluation
-
-### Groundedness Score (1-5 scale)
-
-The `GroundednessEvaluator` measures how well the agent's response is grounded in the provided context:
-
-- **5** = Excellent - Response is fully grounded in context
-- **4** = Good - Mostly grounded with minor deviations
-- **3** = Fair - Partially grounded but includes unsupported claims
-- **2** = Poor - Significant amount of ungrounded content
-- **1** = Very Poor - Response is largely unsupported by context
-
-### Self-Reflection Process
-
-1. **Initial Response**: Agent generates answer based on question + context
-2. **Evaluation**: `GroundednessEvaluator` scores the response (1-5)
-3. **Feedback**: If score < 4, agent receives the score and is asked to improve
-4. **Iteration**: Process repeats until good score or max iterations
-
-## Best Practices
-
-1. **Provide Complete Context**: Ensure grounding context contains all information needed to answer the question
-2. **Clear Instructions**: Give the agent clear instructions about staying grounded in context
-3. **Use Quality Models**: GPT-4o recommended for evaluation tasks
-4. **Multiple Evaluators**: Use combination of evaluators (groundedness + relevance + coherence)
-5. **Batch Processing**: For production, process multiple questions in batch
-
-## Related Resources
-
-- [Reflexion Paper (NeurIPS 2023)](https://arxiv.org/abs/2303.11366)
-- [Microsoft.Extensions.AI.Evaluation Libraries](https://learn.microsoft.com/dotnet/ai/evaluation/libraries)
-- [GroundednessEvaluator API Reference](https://learn.microsoft.com/dotnet/api/microsoft.extensions.ai.evaluation.quality.groundednessevaluator)
-- [Azure AI Foundry Evaluation Service](https://learn.microsoft.com/azure/ai-foundry/how-to/develop/evaluate-sdk)
-
-## Next Steps
-
-After running self-reflection evaluation:
-1. Implement similar patterns for other quality metrics (relevance, coherence, fluency)
-2. Integrate into CI/CD pipeline for continuous quality assurance
-3. Explore the Safety Evaluation sample (FoundryAgents_Evaluations_Step01_RedTeaming) for content safety assessment
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs
deleted file mode 100644
index f4521d8898..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/Program.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample shows how to create and use AI agents with Azure Foundry Agents as the backend.
-
-using Azure.AI.Projects;
-using Azure.AI.Projects.Agents;
-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";
-
-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());
-
-// Define the agent you want to create. (Prompt Agent in this case)
-AgentVersionCreationOptions options = new(new PromptAgentDefinition(model: deploymentName) { Instructions = "You are good at telling jokes." });
-
-// Azure.AI.Agents SDK creates and manages agent by name and versions.
-// You can create a server side agent version with the Azure.AI.Agents SDK client below.
-AgentVersion createdAgentVersion = aiProjectClient.Agents.CreateAgentVersion(agentName: JokerName, options);
-
-// Note:
-// agentVersion.Id = ":",
-// agentVersion.Version = ,
-// agentVersion.Name =
-
-// You can use an AIAgent with an already created server side agent version.
-AIAgent existingJokerAgent = aiProjectClient.AsAIAgent(createdAgentVersion);
-
-// You can also create another AIAgent version by providing the same name with a different definition/instruction.
-AIAgent newJokerAgent = await aiProjectClient.CreateAIAgentAsync(name: JokerName, model: deploymentName, instructions: "You are extremely hilarious at telling jokes.");
-
-// You can also get the AIAgent latest version by just providing its name.
-AIAgent jokerAgentLatest = await aiProjectClient.GetAIAgentAsync(name: JokerName);
-AgentVersion latestAgentVersion = jokerAgentLatest.GetService()!;
-
-// The AIAgent version can be accessed via the GetService method.
-Console.WriteLine($"Latest agent version id: {latestAgentVersion.Id}");
-
-// Once you have the AIAgent, you can invoke it like any other AIAgent.
-Console.WriteLine(await jokerAgentLatest.RunAsync("Tell me a joke about a pirate."));
-
-// Cleanup by agent name removes both agent versions created.
-await aiProjectClient.Agents.DeleteAgentAsync(existingJokerAgent.Name);
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md
deleted file mode 100644
index ce5eca8277..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.1_Basics/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-# Creating and Managing AI Agents with Versioning
-
-This sample demonstrates how to create and manage AI agents with Azure Foundry Agents, including:
-- Creating agents with different versions
-- Retrieving agents by version or latest version
-- Running multi-turn conversations with agents
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step01.1_Basics
-```
-
-## What this sample demonstrates
-
-1. **Creating agents with versions**: Shows how to create multiple versions of the same agent with different instructions
-2. **Retrieving agents**: Demonstrates retrieving agents by specific version or getting the latest version
-3. **Multi-turn conversations**: Shows how to use threads to maintain conversation context across multiple agent runs
-4. **Agent cleanup**: Demonstrates proper resource cleanup by deleting agents
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs
deleted file mode 100644
index 0bc17aff0a..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/Program.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample shows how to create and use a simple AI agent with Azure Foundry Agents as the backend.
-
-using Azure.AI.Projects;
-using Azure.AI.Projects.Agents;
-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";
-
-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());
-
-// Define the agent you want to create. (Prompt Agent in this case)
-AgentVersionCreationOptions options = new(new PromptAgentDefinition(model: deploymentName) { Instructions = JokerInstructions });
-
-// Azure.AI.Agents SDK creates and manages agent by name and versions.
-// You can create a server side agent version with the Azure.AI.Agents SDK client below.
-AgentVersion agentVersion = aiProjectClient.Agents.CreateAgentVersion(agentName: JokerName, options);
-
-// You can use an AIAgent with an already created server side agent version.
-AIAgent jokerAgent = aiProjectClient.AsAIAgent(agentVersion);
-
-// Invoke the agent with streaming support.
-await foreach (AgentResponseUpdate update in jokerAgent.RunStreamingAsync("Tell me a joke about a pirate."))
-{
- Console.WriteLine(update);
-}
-
-// Cleanup by agent name removes the agent version created.
-await aiProjectClient.Agents.DeleteAgentAsync(jokerAgent.Name);
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/README.md
deleted file mode 100644
index 40cb5e107d..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step01.2_Running/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# Running a Simple AI Agent with Streaming
-
-This sample demonstrates how to create and run a simple AI agent with Azure Foundry Agents, including both text and streaming responses.
-
-## What this sample demonstrates
-
-- Creating a simple AI agent with instructions
-- Running an agent with text output
-- Running an agent with streaming output
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step01.2_Running
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent named "JokerAgent" with instructions to tell jokes
-2. Run the agent with a text prompt and display the response
-3. Run the agent again with streaming to display the response as it's generated
-4. Clean up resources by deleting the agent
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs
deleted file mode 100644
index 7bf12094fc..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/Program.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample shows how to create and use a simple AI agent with a multi-turn conversation.
-
-using Azure.AI.Extensions.OpenAI;
-using Azure.AI.Projects;
-using Azure.AI.Projects.Agents;
-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";
-
-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());
-
-// Define the agent you want to create. (Prompt Agent in this case)
-AgentVersionCreationOptions options = new(new PromptAgentDefinition(model: deploymentName) { Instructions = JokerInstructions });
-
-// Retrieve an AIAgent for the created server side agent version.
-ChatClientAgent jokerAgent = await aiProjectClient.CreateAIAgentAsync(name: JokerName, options);
-
-// Invoke the agent with a multi-turn conversation, where the context is preserved in the session object.
-// Create a conversation in the server
-ProjectConversationsClient conversationsClient = aiProjectClient.GetProjectOpenAIClient().GetProjectConversationsClient();
-ProjectConversation conversation = await conversationsClient.CreateProjectConversationAsync();
-
-// Providing the conversation Id is not strictly necessary, but by not providing it no information will show up in the Foundry Project UI as conversations.
-// Sessions that don't have a conversation Id will work based on the `PreviousResponseId`.
-AgentSession session = await jokerAgent.CreateSessionAsync(conversation.Id);
-
-Console.WriteLine(await jokerAgent.RunAsync("Tell me a joke about a pirate.", session));
-Console.WriteLine(await jokerAgent.RunAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", session));
-
-// Invoke the agent with a multi-turn conversation and streaming, where the context is preserved in the session object.
-session = await jokerAgent.CreateSessionAsync(conversation.Id);
-await foreach (AgentResponseUpdate update in jokerAgent.RunStreamingAsync("Tell me a joke about a pirate.", session))
-{
- Console.WriteLine(update);
-}
-await foreach (AgentResponseUpdate update in jokerAgent.RunStreamingAsync("Now add some emojis to the joke and tell it in the voice of a pirate's parrot.", session))
-{
- Console.WriteLine(update);
-}
-
-// Cleanup by agent name removes the agent version created.
-await aiProjectClient.Agents.DeleteAgentAsync(jokerAgent.Name);
-
-// Cleanup the conversation created.
-await conversationsClient.DeleteConversationAsync(conversation.Id);
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md
deleted file mode 100644
index 86721bf960..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step02_MultiturnConversation/README.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Multi-turn Conversation with AI Agents
-
-This sample demonstrates how to implement multi-turn conversations with AI agents, where context is preserved across multiple agent runs using threads and conversation IDs.
-
-## What this sample demonstrates
-
-- Creating an AI agent with instructions
-- Creating a project conversation to track conversations in the Foundry UI
-- Using threads with conversation IDs to maintain conversation context
-- Running multi-turn conversations with text output
-- Running multi-turn conversations with streaming output
-- Managing agent and conversation lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step02_MultiturnConversation
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent named "JokerAgent" with instructions to tell jokes
-2. Create a project conversation to enable visibility in the Azure Foundry UI
-3. Create a thread linked to the conversation ID for context tracking
-4. Run the agent with a text prompt and display the response
-5. Send a follow-up message to the same thread, demonstrating context preservation
-6. Create a new thread sharing the same conversation ID and run the agent with streaming
-7. Send a follow-up streaming message to demonstrate multi-turn streaming
-8. Clean up resources by deleting the agent and conversation
-
-## Conversation ID vs PreviousResponseId
-
-When working with multi-turn conversations, there are two approaches:
-
-- **With Conversation ID**: By passing a `conversation.Id` to `CreateSessionAsync()`, the conversation will be visible in the Azure Foundry Project UI. This is useful for tracking and debugging conversations.
-- **Without Conversation ID**: Sessions created without a conversation ID still work correctly, maintaining context via `PreviousResponseId`. However, these conversations may not appear in the Foundry UI.
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs
deleted file mode 100644
index cfd74000a6..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/Program.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample demonstrates how to use an agent with function tools.
-// It shows both non-streaming and streaming agent interactions using weather-related tools.
-
-using System.ComponentModel;
-using Azure.AI.Projects;
-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";
-
-[Description("Get the weather for a given location.")]
-static string GetWeather([Description("The location to get the weather for.")] string location)
- => $"The weather in {location} is cloudy with a high of 15°C.";
-
-const string AssistantInstructions = "You are a helpful assistant that can get weather information.";
-const string AssistantName = "WeatherAssistant";
-
-// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
-// 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 with function tools.
-AITool tool = AIFunctionFactory.Create(GetWeather);
-
-// Create AIAgent directly
-var newAgent = await aiProjectClient.CreateAIAgentAsync(name: AssistantName, model: deploymentName, instructions: AssistantInstructions, tools: [tool]);
-
-// Getting an already existing agent by name with tools.
-/*
- * IMPORTANT: Since agents that are stored in the server only know the definition of the function tools (JSON Schema),
- * you need to provided all invocable function tools when retrieving the agent so it can invoke them automatically.
- * If no invocable tools are provided, the function calling needs to handled manually.
- */
-var existingAgent = await aiProjectClient.GetAIAgentAsync(name: AssistantName, tools: [tool]);
-
-// Non-streaming agent interaction with function tools.
-AgentSession session = await existingAgent.CreateSessionAsync();
-Console.WriteLine(await existingAgent.RunAsync("What is the weather like in Amsterdam?", session));
-
-// Streaming agent interaction with function tools.
-session = await existingAgent.CreateSessionAsync();
-await foreach (AgentResponseUpdate update in existingAgent.RunStreamingAsync("What is the weather like in Amsterdam?", session))
-{
- Console.WriteLine(update);
-}
-
-// Cleanup by agent name removes the agent version created.
-await aiProjectClient.Agents.DeleteAgentAsync(existingAgent.Name);
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md
deleted file mode 100644
index fa9b5baf21..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step03_UsingFunctionTools/README.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Using Function Tools with AI Agents
-
-This sample demonstrates how to use function tools with AI agents, allowing agents to call custom functions to retrieve information.
-
-## What this sample demonstrates
-
-- Creating function tools using AIFunctionFactory
-- Passing function tools to an AI agent
-- Running agents with function tools (text output)
-- Running agents with function tools (streaming output)
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step03.1_UsingFunctionTools
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent named "WeatherAssistant" with a GetWeather function tool
-2. Run the agent with a text prompt asking about weather
-3. The agent will invoke the GetWeather function tool to retrieve weather information
-4. Run the agent again with streaming to display the response as it's generated
-5. Clean up resources by deleting the agent
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md
deleted file mode 100644
index 42cbd6ba32..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step04_UsingFunctionToolsWithApprovals/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Using Function Tools with Approvals (Human-in-the-Loop)
-
-This sample demonstrates how to use function tools that require human approval before execution, implementing a human-in-the-loop workflow.
-
-## What this sample demonstrates
-
-- Creating approval-required function tools using ApprovalRequiredAIFunction
-- Handling user input requests for function approvals
-- Implementing human-in-the-loop approval workflows
-- Processing agent responses with pending approvals
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step04_UsingFunctionToolsWithApprovals
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent named "WeatherAssistant" with an approval-required GetWeather function tool
-2. Run the agent with a prompt asking about weather
-3. The agent will request approval before invoking the GetWeather function
-4. The sample will prompt the user to approve or deny the function call (enter 'Y' to approve)
-5. After approval, the function will be executed and the result returned to the agent
-6. Clean up resources by deleting the agent
-
-**Note**: For hosted agents with remote users, combine this sample with the Persisted Conversations sample to persist chat history while waiting for user approval.
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj
deleted file mode 100644
index daf7e24494..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/FoundryAgents_Step05_StructuredOutput.csproj
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md
deleted file mode 100644
index 4c44230e18..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step05_StructuredOutput/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# Structured Output with AI Agents
-
-This sample demonstrates how to configure AI agents to produce structured output in JSON format using JSON schemas.
-
-## What this sample demonstrates
-
-- Configuring agents with JSON schema response formats
-- Using generic RunAsync method for structured output
-- Deserializing structured responses into typed objects
-- Running agents with streaming and structured output
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step05_StructuredOutput
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent named "StructuredOutputAssistant" configured to produce JSON output
-2. Run the agent with a prompt to extract person information
-3. Deserialize the JSON response into a PersonInfo object
-4. Display the structured data (Name, Age, Occupation)
-5. Run the agent again with streaming and deserialize the streamed JSON response
-6. Clean up resources by deleting the agent
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj
deleted file mode 100644
index daf7e24494..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/FoundryAgents_Step06_PersistedConversations.csproj
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md
deleted file mode 100644
index 57a032e9ec..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step06_PersistedConversations/README.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# Persisted Conversations with AI Agents
-
-This sample demonstrates how to serialize and persist agent conversation threads to storage, allowing conversations to be resumed later.
-
-## What this sample demonstrates
-
-- Serializing agent threads to JSON
-- Persisting thread state to disk
-- Loading and deserializing thread state from storage
-- Resuming conversations with persisted threads
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step06_PersistedConversations
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent named "JokerAgent" with instructions to tell jokes
-2. Create a thread and run the agent with an initial prompt
-3. Serialize the thread state to JSON
-4. Save the serialized thread to a temporary file
-5. Load the thread from the file and deserialize it
-6. Resume the conversation with the same thread using a follow-up prompt
-7. Clean up resources by deleting the agent
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/README.md
deleted file mode 100644
index 459434bce2..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step07_Observability/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Observability with OpenTelemetry
-
-This sample demonstrates how to add observability to AI agents using OpenTelemetry for tracing and monitoring.
-
-## What this sample demonstrates
-
-- Setting up OpenTelemetry TracerProvider
-- Configuring console exporter for telemetry output
-- Configuring Azure Monitor exporter for Application Insights
-- Adding OpenTelemetry middleware to agents
-- Running agents with telemetry collection (text and streaming)
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure CLI installed and authenticated (for Azure credential authentication)
-- (Optional) Application Insights connection string for Azure Monitor integration
-
-**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-$env:APPLICATIONINSIGHTS_CONNECTION_STRING="your-connection-string" # Optional, for Azure Monitor integration
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step07_Observability
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create a TracerProvider with console exporter (and optionally Azure Monitor exporter)
-2. Create an agent named "JokerAgent" with OpenTelemetry middleware
-3. Run the agent with a text prompt and display telemetry traces to console
-4. Run the agent again with streaming and display telemetry traces
-5. Clean up resources by deleting the agent
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs
deleted file mode 100644
index b7a9874e7b..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/Program.cs
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample shows how to use dependency injection to register an AIAgent and use it from a hosted service with a user input chat loop.
-
-using System.ClientModel;
-using Azure.AI.Projects;
-using Azure.Identity;
-using Microsoft.Agents.AI;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-
-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";
-
-// 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 new agent if one doesn't exist already.
-ChatClientAgent agent;
-try
-{
- agent = await aIProjectClient.GetAIAgentAsync(name: JokerName);
-}
-catch (ClientResultException ex) when (ex.Status == 404)
-{
- agent = await aIProjectClient.CreateAIAgentAsync(name: JokerName, model: deploymentName, instructions: JokerInstructions);
-}
-
-// Create a host builder that we will register services with and then run.
-HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
-
-// Add the agents client to the service collection.
-builder.Services.AddSingleton((sp) => aIProjectClient);
-
-// Add the AI agent to the service collection.
-builder.Services.AddSingleton((sp) => agent);
-
-// Add a sample service that will use the agent to respond to user input.
-builder.Services.AddHostedService();
-
-// Build and run the host.
-using IHost host = builder.Build();
-await host.RunAsync().ConfigureAwait(false);
-
-///
-/// A sample service that uses an AI agent to respond to user input.
-///
-internal sealed class SampleService(AIProjectClient client, AIAgent agent, IHostApplicationLifetime appLifetime) : IHostedService
-{
- private AgentSession? _session;
-
- public async Task StartAsync(CancellationToken cancellationToken)
- {
- // Create a session that will be used for the entirety of the service lifetime so that the user can ask follow up questions.
- this._session = await agent.CreateSessionAsync(cancellationToken);
- _ = this.RunAsync(appLifetime.ApplicationStopping);
- }
-
- public async Task RunAsync(CancellationToken cancellationToken)
- {
- // Delay a little to allow the service to finish starting.
- await Task.Delay(100, cancellationToken);
-
- while (!cancellationToken.IsCancellationRequested)
- {
- Console.WriteLine("\nAgent: Ask me to tell you a joke about a specific topic. To exit just press Ctrl+C or enter without any input.\n");
- Console.Write("> ");
- string? input = Console.ReadLine();
-
- // If the user enters no input, signal the application to shut down.
- if (string.IsNullOrWhiteSpace(input))
- {
- appLifetime.StopApplication();
- break;
- }
-
- // Stream the output to the console as it is generated.
- await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(input, this._session, cancellationToken: cancellationToken))
- {
- Console.Write(update);
- }
-
- Console.WriteLine();
- }
- }
-
- public async Task StopAsync(CancellationToken cancellationToken)
- {
- Console.WriteLine("\nDeleting agent ...");
- await client.Agents.DeleteAgentAsync(agent.Name, cancellationToken).ConfigureAwait(false);
- }
-}
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md
deleted file mode 100644
index 12760e736f..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step08_DependencyInjection/README.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Dependency Injection with AI Agents
-
-This sample demonstrates how to use dependency injection to register and manage AI agents within a hosted service application.
-
-## What this sample demonstrates
-
-- Setting up dependency injection with HostApplicationBuilder
-- Registering AIProjectClient as a singleton service
-- Registering AIAgent as a singleton service
-- Using agents in hosted services
-- Interactive chat loop with streaming responses
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step08_DependencyInjection
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create a host with dependency injection configured
-2. Register AIProjectClient and AIAgent as services
-3. Create an agent named "JokerAgent" with instructions to tell jokes
-4. Start an interactive chat loop where you can ask the agent questions
-5. The agent will respond with streaming output
-6. Enter an empty line or press Ctrl+C to exit
-7. Clean up resources by deleting the agent
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj
deleted file mode 100644
index a6d96cb3db..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/FoundryAgents_Step09_UsingMcpClientAsTools.csproj
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- 3afc9b74-af74-4d8e-ae96-fa1c511d11ac
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs
deleted file mode 100644
index e1968122a4..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/Program.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample shows how to expose an AI agent as an MCP tool.
-
-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";
-
-Console.WriteLine("Starting MCP Stdio for @modelcontextprotocol/server-github ... ");
-
-// Create an MCPClient for the GitHub server
-await using var mcpClient = await McpClient.CreateAsync(new StdioClientTransport(new()
-{
- Name = "MCPServer",
- Command = "npx",
- Arguments = ["-y", "--verbose", "@modelcontextprotocol/server-github"],
-}));
-
-// Retrieve the list of tools available on the GitHub server
-IList mcpTools = await mcpClient.ListToolsAsync();
-string agentName = "AgentWithMCP";
-// 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());
-
-Console.WriteLine($"Creating the agent '{agentName}' ...");
-
-// Define the agent you want to create. (Prompt Agent in this case)
-AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
- name: agentName,
- model: deploymentName,
- instructions: "You answer questions related to GitHub repositories only.",
- tools: [.. mcpTools.Cast()]);
-
-string prompt = "Summarize the last four commits to the microsoft/semantic-kernel repository?";
-
-Console.WriteLine($"Invoking agent '{agent.Name}' with prompt: {prompt} ...");
-
-// Invoke the agent and output the text result.
-Console.WriteLine(await agent.RunAsync(prompt));
-
-// Clean up the agent after use.
-await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md
deleted file mode 100644
index e4e3fe537a..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step09_UsingMcpClientAsTools/README.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# Using MCP Client Tools with AI Agents
-
-This sample demonstrates how to use Model Context Protocol (MCP) client tools with AI agents, allowing agents to access tools provided by MCP servers. This sample uses the GitHub MCP server to provide tools for querying GitHub repositories.
-
-## What this sample demonstrates
-
-- Creating MCP clients to connect to MCP servers (GitHub server)
-- Retrieving tools from MCP servers
-- Using MCP tools with AI agents
-- Running agents with MCP-provided function tools
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure CLI installed and authenticated (for Azure credential authentication)
-- Node.js and npm installed (for running the GitHub MCP server)
-
-**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step09_UsingMcpClientAsTools
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Start the GitHub MCP server using `@modelcontextprotocol/server-github`
-2. Create an MCP client to connect to the GitHub server
-3. Retrieve the available tools from the GitHub MCP server
-4. Create an agent named "AgentWithMCP" with the GitHub tools
-5. Run the agent with a prompt to summarize the last four commits to the microsoft/semantic-kernel repository
-6. The agent will use the GitHub MCP tools to query the repository information
-7. Clean up resources by deleting the agent
\ No newline at end of file
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj
deleted file mode 100644
index 53661ff199..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/FoundryAgents_Step10_UsingImages.csproj
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
- Always
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md
deleted file mode 100644
index 220104a291..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step10_UsingImages/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Using Images with AI Agents
-
-This sample demonstrates how to use image multi-modality with an AI agent. It shows how to create a vision-enabled agent that can analyze and describe images using Azure Foundry Agents.
-
-## What this sample demonstrates
-
-- Creating a vision-enabled AI agent with image analysis capabilities
-- Sending both text and image content to an agent in a single message
-- Using `UriContent` for URI-referenced images
-- Processing multimodal input (text + image) with an AI agent
-- Managing agent lifecycle (creation and deletion)
-
-## Key features
-
-- **Vision Agent**: Creates an agent specifically instructed to analyze images
-- **Multimodal Input**: Combines text questions with image URI in a single message
-- **Azure Foundry Agents Integration**: Uses Azure Foundry Agents with vision capabilities
-
-## Prerequisites
-
-Before running this sample, ensure you have:
-
-1. An Azure OpenAI project set up
-2. A compatible model deployment (e.g., gpt-4o)
-3. Azure CLI installed and authenticated
-
-## Environment Variables
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_AI_PROJECT_ENDPOINT="https://your-resource.openai.azure.com/" # Replace with your Azure Foundry Project endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o" # Replace with your model deployment name (optional, defaults to gpt-4o)
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step10_UsingImages
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create a vision-enabled agent named "VisionAgent"
-2. Send a message containing both text ("What do you see in this image?") and a URI-referenced image of a green walkway (nature boardwalk)
-3. The agent will analyze the image and provide a description
-4. Clean up resources by deleting the agent
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj
deleted file mode 100644
index 54f37f1aa6..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/FoundryAgents_Step11_AsFunctionTool.csproj
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- 3afc9b74-af74-4d8e-ae96-fa1c511d11ac
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md
deleted file mode 100644
index 5da59b6edb..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step11_AsFunctionTool/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# Using AI Agents as Function Tools (Nested Agents)
-
-This sample demonstrates how to expose an AI agent as a function tool, enabling nested agent scenarios where one agent can invoke another agent as a tool.
-
-## What this sample demonstrates
-
-- Creating an AI agent that can be used as a function tool
-- Wrapping an agent as an AIFunction
-- Using nested agents where one agent calls another
-- Managing multiple agent instances
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step11_AsFunctionTool
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create a "JokerAgent" that tells jokes
-2. Wrap the JokerAgent as a function tool
-3. Create a "CoordinatorAgent" that has the JokerAgent as a function tool
-4. Run the CoordinatorAgent with a prompt that triggers it to call the JokerAgent
-5. The CoordinatorAgent will invoke the JokerAgent as a function tool
-6. Clean up resources by deleting both agents
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/README.md
deleted file mode 100644
index 96d12d9828..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step12_Middleware/README.md
+++ /dev/null
@@ -1,58 +0,0 @@
-# Agent Middleware
-
-This sample demonstrates how to add middleware to intercept agent runs and function calls to implement cross-cutting concerns like logging, validation, and guardrails.
-
-## What This Sample Shows
-
-1. Azure Foundry Agents integration via `AIProjectClient` and `DefaultAzureCredential`
-2. Agent run middleware (logging and monitoring)
-3. Function invocation middleware (logging and overriding tool results)
-4. Per-request agent run middleware
-5. Per-request function pipeline with approval
-6. Combining agent-level and per-request middleware
-
-## Function Invocation Middleware
-
-Not all agents support function invocation middleware.
-
-Attempting to use function middleware on agents that do not wrap a ChatClientAgent or derives from it will throw an InvalidOperationException.
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Running the Sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step12_Middleware
-```
-
-## Expected Behavior
-
-When you run this sample, you will see the following demonstrations:
-
-1. **Example 1: Wording Guardrail** - The agent receives a request for harmful content. The guardrail middleware intercepts the request and prevents the agent from responding to harmful prompts, returning a safe response instead.
-
-2. **Example 2: PII Detection** - The agent receives a message containing personally identifiable information (name, phone number, email). The PII middleware detects and filters this sensitive information before processing.
-
-3. **Example 3: Agent Function Middleware** - The agent uses function tools (GetDateTime and GetWeather) to answer a question about the current time and weather in Seattle. The function middleware logs the function calls and can override results if needed.
-
-4. **Example 4: Human-in-the-Loop Function Approval** - The agent attempts to call a weather function, but the approval middleware intercepts the call and prompts the user to approve or deny the function invocation before it executes. The user can respond with "Y" to approve or any other input to deny.
-
-Each example demonstrates how middleware can be used to implement cross-cutting concerns and control agent behavior at different levels (agent-level and per-request).
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj
deleted file mode 100644
index 4a34560946..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/FoundryAgents_Step13_Plugins.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- $(NoWarn);CA1812
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs
deleted file mode 100644
index 244d83d632..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/Program.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-// 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;
-
-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();
-services.AddSingleton();
-services.AddSingleton(); // The plugin depends on WeatherProvider and CurrentTimeProvider registered above.
-
-IServiceProvider serviceProvider = services.BuildServiceProvider();
-
-// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
-// 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 with plugin tools
-// Define the agent you want to create. (Prompt Agent in this case)
-AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
- name: AssistantName,
- model: deploymentName,
- instructions: AssistantInstructions,
- tools: serviceProvider.GetRequiredService().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));
-
-// Cleanup by agent name removes the agent version created.
-await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
-
-///
-/// The agent plugin that provides weather and current time information.
-///
-/// The weather provider to get weather information.
-internal sealed class AgentPlugin(WeatherProvider weatherProvider)
-{
- ///
- /// Gets the weather information for the specified location.
- ///
- ///
- /// This method demonstrates how to use the dependency that was injected into the plugin class.
- ///
- /// The location to get the weather for.
- /// The weather information for the specified location.
- public string GetWeather(string location)
- {
- return weatherProvider.GetWeather(location);
- }
-
- ///
- /// Gets the current date and time for the specified location.
- ///
- ///
- /// This method demonstrates how to resolve a dependency using the service provider passed to the method.
- ///
- /// The service provider to resolve the .
- /// The location to get the current time for.
- /// The current date and time as a .
- public DateTimeOffset GetCurrentTime(IServiceProvider sp, string location)
- {
- // Resolve the CurrentTimeProvider from the service provider
- CurrentTimeProvider currentTimeProvider = sp.GetRequiredService();
-
- return currentTimeProvider.GetCurrentTime(location);
- }
-
- ///
- /// Returns the functions provided by this plugin.
- ///
- ///
- /// 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.
- ///
- /// The functions provided by this plugin.
- public IEnumerable AsAITools()
- {
- yield return AIFunctionFactory.Create(this.GetWeather);
- yield return AIFunctionFactory.Create(this.GetCurrentTime);
- }
-}
-
-///
-/// The weather provider that returns weather information.
-///
-internal sealed class WeatherProvider
-{
- ///
- /// Gets the weather information for the specified location.
- ///
- ///
- /// The weather information is hardcoded for demonstration purposes.
- /// In a real application, this could call a weather API to get actual weather data.
- ///
- /// The location to get the weather for.
- /// The weather information for the specified location.
- public string GetWeather(string location)
- {
- return $"The weather in {location} is cloudy with a high of 15°C.";
- }
-}
-
-///
-/// Provides the current date and time.
-///
-///
-/// This class returns the current date and time using the system's clock.
-///
-internal sealed class CurrentTimeProvider
-{
- ///
- /// Gets the current date and time.
- ///
- /// The location to get the current time for (not used in this implementation).
- /// The current date and time as a .
- public DateTimeOffset GetCurrentTime(string location)
- {
- return DateTimeOffset.Now;
- }
-}
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/README.md
deleted file mode 100644
index 5c52ffcd1c..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step13_Plugins/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# Using Plugins with AI Agents
-
-This sample demonstrates how to use plugins with AI agents, where plugins are services registered in dependency injection that expose methods as AI function tools.
-
-## What this sample demonstrates
-
-- Creating plugin services with methods to expose as tools
-- Using AsAITools() to selectively expose plugin methods
-- Registering plugins in dependency injection
-- Using plugins with AI agents
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step13_Plugins
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create a plugin service with methods to expose as tools
-2. Register the plugin in dependency injection
-3. Create an agent named "PluginAgent" with the plugin methods as function tools
-4. Run the agent with a prompt that triggers it to call plugin methods
-5. The agent will invoke the plugin methods to retrieve information
-6. Clean up resources by deleting the agent
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj
deleted file mode 100644
index 4a34560946..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/FoundryAgents_Step14_CodeInterpreter.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- $(NoWarn);CA1812
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md
deleted file mode 100644
index 34fa18c94c..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step14_CodeInterpreter/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Using Code Interpreter with AI Agents
-
-This sample demonstrates how to use the code interpreter tool with AI agents. The code interpreter allows agents to write and execute Python code to solve problems, perform calculations, and analyze data.
-
-## What this sample demonstrates
-
-- Creating agents with code interpreter capabilities
-- Using HostedCodeInterpreterTool (MEAI abstraction)
-- Using native SDK code interpreter tools (ResponseTool.CreateCodeInterpreterTool)
-- Extracting code inputs and results from agent responses
-- Handling code interpreter annotations
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step14_CodeInterpreter
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create two agents with code interpreter capabilities:
- - Option 1: Using HostedCodeInterpreterTool (MEAI abstraction)
- - Option 2: Using native SDK code interpreter tools
-2. Run the agent with a mathematical problem: "I need to solve the equation sin(x) + x^2 = 42"
-3. The agent will use the code interpreter to write and execute Python code to solve the equation
-4. Extract and display the code that was executed
-5. Display the results from the code execution
-6. Display any annotations generated by the code interpreter tool
-7. Clean up resources by deleting both agents
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md
deleted file mode 100644
index 092f2bd1cf..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step15_ComputerUse/README.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Using Computer Use Tool with AI Agents
-
-This sample demonstrates how to use the computer use tool with AI agents. The computer use tool allows agents to interact with a computer environment by viewing the screen, controlling the mouse and keyboard, and performing various actions to help complete tasks.
-
-> [!NOTE]
-> **Azure Agents API vs. vanilla OpenAI Responses API behavior:**
-> The Azure Agents API rejects requests that include `previous_response_id` alongside
-> `computer_call_output` items — unlike the vanilla OpenAI Responses API, which accepts them.
-> This sample works around the limitation by creating a **fresh session for each follow-up call**
-> (so no `previous_response_id` is carried over) and re-sending all prior response output items
-> (reasoning, computer_call, etc.) as input items to preserve full conversation context.
-> Additionally, the sample uses the **current** `CallId` from each computer call response
-> (not the initial one) and clears the `ContinuationToken` after polling completes to prevent
-> stale tokens from affecting subsequent requests.
-
-## What this sample demonstrates
-
-- Creating agents with computer use capabilities
-- Using HostedComputerTool (MEAI abstraction)
-- Using native SDK computer use tools (ResponseTool.CreateComputerTool)
-- Extracting computer action information from agent responses
-- Handling computer tool results (text output and screenshots)
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="computer-use-preview" # Optional, defaults to computer-use-preview
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step15_ComputerUse
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create two agents with computer use capabilities:
- - Option 1: Using HostedComputerTool (MEAI abstraction)
- - Option 2: Using native SDK computer use tools
-2. Run the agent with a task: "I need you to help me search for 'OpenAI news'. Please type 'OpenAI news' and submit the search. Once you see search results, the task is complete."
-3. The agent will use the computer use tool to:
- - Interpret the screenshots
- - Issue action requests based on the task
- - Analyze the search results for "OpenAI news" from the screenshots.
-4. Extract and display the computer actions performed
-5. Display the results from the computer tool execution
-6. Display the final response from the agent
-7. Clean up resources by deleting both agents
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step16_FileSearch/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step16_FileSearch/README.md
deleted file mode 100644
index db74868d3d..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step16_FileSearch/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# Using File Search with AI Agents
-
-This sample demonstrates how to use the file search tool with AI agents. The file search tool allows agents to search through uploaded files stored in vector stores to answer user questions.
-
-## What this sample demonstrates
-
-- Uploading files and creating vector stores
-- Creating agents with file search capabilities
-- Using HostedFileSearchTool (MEAI abstraction)
-- Using native SDK file search tools (ResponseTool.CreateFileSearchTool)
-- Handling file citation annotations
-- Managing agent and resource lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure CLI installed and authenticated (for Azure credential authentication)
-
-**Note**: This demo uses `DefaultAzureCredential` for authentication. For local development, make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure Identity documentation](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential).
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step16_FileSearch
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create a temporary text file with employee directory information
-2. Upload the file to Azure Foundry
-3. Create a vector store with the uploaded file
-4. Create an agent with file search capabilities using one of:
- - Option 1: Using HostedFileSearchTool (MEAI abstraction)
- - Option 2: Using native SDK file search tools
-5. Run a query against the agent to search through the uploaded file
-6. Display file citation annotations from responses
-7. Clean up resources (agent, vector store, and uploaded file)
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/FoundryAgents_Step17_OpenAPITools.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/FoundryAgents_Step17_OpenAPITools.csproj
deleted file mode 100644
index 77b76acfa0..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/FoundryAgents_Step17_OpenAPITools.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- $(NoWarn);CA1812;CS8321
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/README.md
deleted file mode 100644
index a859f6b963..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step17_OpenAPITools/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Using OpenAPI Tools with AI Agents
-
-This sample demonstrates how to use OpenAPI tools with AI agents. OpenAPI tools allow agents to call external REST APIs defined by OpenAPI specifications.
-
-## What this sample demonstrates
-
-- Creating agents with OpenAPI tool capabilities
-- Using AgentTool.CreateOpenApiTool with an embedded OpenAPI specification
-- Anonymous authentication for public APIs
-- Running an agent that can call external REST APIs
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure CLI installed and authenticated (for Azure credential authentication)
-
-**Note**: This demo uses `DefaultAzureCredential` for authentication, which supports multiple authentication methods including Azure CLI, managed identity, and more. Make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure Identity documentation](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential).
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step17_OpenAPITools
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent with an OpenAPI tool configured to call the REST Countries API
-2. Ask the agent: "What countries use the Euro (EUR) as their currency?"
-3. The agent will use the OpenAPI tool to call the REST Countries API
-4. Display the response containing the list of countries that use EUR
-5. Clean up resources by deleting the agent
\ No newline at end of file
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/FoundryAgents_Step18_BingCustomSearch.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/FoundryAgents_Step18_BingCustomSearch.csproj
deleted file mode 100644
index 730d284bd9..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/FoundryAgents_Step18_BingCustomSearch.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- $(NoWarn);CA1812;CS8321
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/README.md
deleted file mode 100644
index ccc1873a04..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step18_BingCustomSearch/README.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# Using Bing Custom Search with AI Agents
-
-This sample demonstrates how to use the Bing Custom Search tool with AI agents to perform customized web searches.
-
-## What this sample demonstrates
-
-- Creating agents with Bing Custom Search capabilities
-- Configuring custom search instances via connection ID and instance name
-- Two agent creation approaches: MEAI abstraction (Option 1) and Native SDK (Option 2)
-- Running search queries through the agent
-- Managing agent lifecycle (creation and deletion)
-
-## Agent creation options
-
-This sample provides two approaches for creating agents with Bing Custom Search:
-
-- **Option 1 - MEAI + AgentFramework**: Uses the Agent Framework `ResponseTool` wrapped with `AsAITool()` to call the `CreateAIAgentAsync` overload that accepts `tools:[]`, while still relying on the same underlying Azure AI Projects SDK types as Option 2.
-- **Option 2 - Native SDK**: Uses `PromptAgentDefinition` with `AgentVersionCreationOptions` to create the agent directly with the Azure AI Projects SDK types.
-
-Both options produce the same result. Toggle between them by commenting/uncommenting the corresponding `CreateAgentWith*Async` call in `Program.cs`.
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure CLI installed and authenticated (for Azure credential authentication)
-- A Bing Custom Search resource configured in Azure and connected to your Foundry project
-
-**Note**: This demo uses Azure Default credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure Foundry resource.
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
-$env:AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-$env:BING_CUSTOM_SEARCH_PROJECT_CONNECTION_ID="/subscriptions//resourceGroups//providers/Microsoft.CognitiveServices/accounts//projects//connections/"
-$env:BING_CUSTOM_SEARCH_INSTANCE_NAME="your-configuration-name"
-```
-
-### Finding the connection ID and instance name
-
-- **Connection ID**: The full ARM resource path including the `/projects//connections/` segment. Find the connection name in your Foundry project under **Management center** → **Connected resources**.
-- **Instance Name**: The **configuration name** from the Bing Custom Search resource (Azure portal → your Bing Custom Search resource → **Configurations**). This is _not_ the Azure resource name.
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step18_BingCustomSearch
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent with Bing Custom Search tool capabilities
-2. Run the agent with a search query about Microsoft AI
-3. Display the search results returned by the agent
-4. Clean up resources by deleting the agent
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/FoundryAgents_Step19_SharePoint.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/FoundryAgents_Step19_SharePoint.csproj
deleted file mode 100644
index 4d17fe06bb..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/FoundryAgents_Step19_SharePoint.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- $(NoWarn);CA1812;CS8321
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/README.md
deleted file mode 100644
index ccbd699011..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step19_SharePoint/README.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# Using SharePoint Grounding with AI Agents
-
-This sample demonstrates how to use the SharePoint grounding tool with AI agents. The SharePoint grounding tool enables agents to search and retrieve information from SharePoint sites.
-
-## What this sample demonstrates
-
-- Creating agents with SharePoint grounding capabilities
-- Using AgentTool.CreateSharepointTool (MEAI abstraction)
-- Using native SDK SharePoint tools (PromptAgentDefinition)
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure authentication configured for `DefaultAzureCredential` (for example, Azure CLI logged in with `az login`, environment variables, managed identity, or IDE sign-in)
-- A SharePoint project connection configured in Azure Foundry
-
-**Note**: This demo uses `DefaultAzureCredential` for authentication. This credential will try multiple authentication mechanisms in order (such as environment variables, managed identity, Azure CLI login, and IDE sign-in) and use the first one that works. A common option for local development is to sign in with the Azure CLI using `az login` and ensure you have access to the Azure Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively) and the [DefaultAzureCredential documentation](https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential).
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-$env:SHAREPOINT_PROJECT_CONNECTION_ID="your-sharepoint-connection-id" # Required: SharePoint project connection ID
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step19_SharePoint
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create two agents with SharePoint grounding capabilities:
- - Option 1: Using AgentTool.CreateSharepointTool (MEAI abstraction)
- - Option 2: Using native SDK SharePoint tools
-2. Run the agent with a query: "List the documents available in SharePoint"
-3. The agent will use SharePoint grounding to search and retrieve relevant documents
-4. Display the response and any grounding annotations
-5. Clean up resources by deleting both agents
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/FoundryAgents_Step20_MicrosoftFabric.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/FoundryAgents_Step20_MicrosoftFabric.csproj
deleted file mode 100644
index 4d17fe06bb..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/FoundryAgents_Step20_MicrosoftFabric.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- $(NoWarn);CA1812;CS8321
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/Program.cs
deleted file mode 100644
index e5ab205f68..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/Program.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample shows how to use Microsoft Fabric Tool with AI Agents.
-
-using Azure.AI.Projects;
-using Azure.AI.Projects.Agents;
-using Azure.Identity;
-using Microsoft.Agents.AI;
-using OpenAI.Responses;
-
-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 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.";
-
-// 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());
-
-// Configure Microsoft Fabric tool options with project connection
-var fabricToolOptions = new FabricDataAgentToolOptions();
-fabricToolOptions.ProjectConnections.Add(new ToolProjectConnection(fabricConnectionId));
-
-AIAgent agent = await CreateAgentWithMEAIAsync();
-// AIAgent agent = await CreateAgentWithNativeSDKAsync();
-
-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);
-}
-
-// 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.CreateMicrosoftFabricTool (MEAI + AgentFramework)
-async Task CreateAgentWithMEAIAsync()
-{
- return await aiProjectClient.CreateAIAgentAsync(
- model: deploymentName,
- name: "FabricAgent-MEAI",
- instructions: AgentInstructions,
- tools: [((ResponseTool)AgentTool.CreateMicrosoftFabricTool(fabricToolOptions)).AsAITool()]);
-}
-
-// Option 2 - Using PromptAgentDefinition with AgentTool.CreateMicrosoftFabricTool (Native SDK)
-async Task CreateAgentWithNativeSDKAsync()
-{
- return await aiProjectClient.CreateAIAgentAsync(
- name: "FabricAgent-NATIVE",
- creationOptions: new AgentVersionCreationOptions(
- new PromptAgentDefinition(model: deploymentName)
- {
- Instructions = AgentInstructions,
- Tools =
- {
- AgentTool.CreateMicrosoftFabricTool(fabricToolOptions),
- }
- })
- );
-}
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/README.md
deleted file mode 100644
index a5faf79d9d..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step20_MicrosoftFabric/README.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Using Microsoft Fabric Tool with AI Agents
-
-This sample demonstrates how to use the Microsoft Fabric tool with AI Agents, allowing agents to query and interact with data in Microsoft Fabric workspaces.
-
-## What this sample demonstrates
-
-- Creating agents with Microsoft Fabric data access capabilities
-- Using FabricDataAgentToolOptions to configure Fabric connections
-- Two agent creation approaches: MEAI abstraction (Option 1) and Native SDK (Option 2)
-- Managing agent lifecycle (creation and deletion)
-
-## Agent creation options
-
-This sample provides two approaches for creating agents with Microsoft Fabric:
-
-- **Option 1 - MEAI + AgentFramework**: Uses the Agent Framework `ResponseTool` wrapped with `AsAITool()` to call the `CreateAIAgentAsync` overload that accepts `tools:[]`, while still relying on the same underlying Azure AI Projects SDK types as Option 2.
-- **Option 2 - Native SDK**: Uses `PromptAgentDefinition` with `AgentVersionCreationOptions` to create the agent directly with the Azure AI Projects SDK types.
-
-Both options produce the same result. Toggle between them by commenting/uncommenting the corresponding `CreateAgentWith*Async` call in `Program.cs`.
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure CLI installed and authenticated (for Azure credential authentication)
-- A Microsoft Fabric workspace with a configured project connection in Azure Foundry
-
-**Note**: This demo uses Azure Default credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure Foundry resource.
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
-$env:AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-$env:FABRIC_PROJECT_CONNECTION_ID="your-fabric-connection-id" # The Fabric project connection ID from Azure Foundry
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step20_MicrosoftFabric
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent with Microsoft Fabric tool capabilities
-2. Configure the agent with a Fabric project connection
-3. Run the agent with a query about available Fabric data
-4. Display the agent's response
-5. Clean up resources by deleting the agent
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/FoundryAgents_Step21_WebSearch.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/FoundryAgents_Step21_WebSearch.csproj
deleted file mode 100644
index 4d17fe06bb..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/FoundryAgents_Step21_WebSearch.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- $(NoWarn);CA1812;CS8321
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/Program.cs b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/Program.cs
deleted file mode 100644
index c116a975e1..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/Program.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-// This sample shows how to use the Responses API Web Search Tool with AI Agents.
-
-using Azure.AI.Projects;
-using Azure.AI.Projects.Agents;
-using Azure.Identity;
-using Microsoft.Agents.AI;
-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.");
-string deploymentName = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4o-mini";
-
-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";
-
-// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents.
-AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
-
-// Option 1 - Using HostedWebSearchTool (MEAI + AgentFramework)
-AIAgent agent = await CreateAgentWithMEAIAsync();
-
-// Option 2 - Using PromptAgentDefinition with the Responses API native type
-// AIAgent agent = await CreateAgentWithNativeSDKAsync();
-
-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}}
- """);
- }
-}
-
-// Cleanup by agent name removes the agent version created.
-await aiProjectClient.Agents.DeleteAgentAsync(agent.Name);
-
-// Creates the agent using the HostedWebSearchTool MEAI abstraction that maps to the built-in Responses API web search tool.
-async Task CreateAgentWithMEAIAsync()
- => await aiProjectClient.CreateAIAgentAsync(
- name: AgentName,
- model: deploymentName,
- instructions: AgentInstructions,
- tools: [new HostedWebSearchTool()]);
-
-// Creates the agent using the PromptAgentDefinition with the Responses API native ResponseTool.CreateWebSearchTool().
-async Task CreateAgentWithNativeSDKAsync()
- => await aiProjectClient.CreateAIAgentAsync(
- AgentName,
- new AgentVersionCreationOptions(
- new PromptAgentDefinition(model: deploymentName)
- {
- Instructions = AgentInstructions,
- Tools = { ResponseTool.CreateWebSearchTool() }
- }));
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/README.md
deleted file mode 100644
index 8da390878c..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step21_WebSearch/README.md
+++ /dev/null
@@ -1,52 +0,0 @@
-# Using Web Search with AI Agents
-
-This sample demonstrates how to use the Responses API web search tool with AI agents. The web search tool allows agents to search the web for current information to answer questions accurately.
-
-## What this sample demonstrates
-
-- Creating agents with web search capabilities
-- Using HostedWebSearchTool (MEAI abstraction)
-- Using native SDK web search tools (ResponseTool.CreateWebSearchTool)
-- Extracting text responses and URL citations from agent responses
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure authentication configured for `DefaultAzureCredential` (for example, Azure CLI logged in with `az login`, environment variables, managed identity, or IDE sign-in)
-
-**Note**: This sample authenticates using `DefaultAzureCredential` from the Azure Identity library, which will try several credential sources (including Azure CLI, environment variables, managed identity, and IDE sign-in). Ensure at least one supported credential source is available. For more information, see the [Azure Identity documentation](https://learn.microsoft.com/dotnet/api/overview/azure/identity-readme).
-
-**Note**: The web search tool uses the built-in web search capability from the OpenAI Responses API.
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step21_WebSearch
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent with web search capabilities using HostedWebSearchTool (MEAI abstraction)
- - Alternative: Using native SDK web search tools (commented out in code)
- - Alternative: Retrieving an existing agent by name (commented out in code)
-2. Run the agent with a query: "What's the weather today in Seattle?"
-3. The agent will use the web search tool to find current information
-4. Display the text response from the agent
-5. Display any URL citations from web search results
-6. Clean up resources by deleting the agent
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/FoundryAgents_Step22_MemorySearch.csproj b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/FoundryAgents_Step22_MemorySearch.csproj
deleted file mode 100644
index d83a9d9202..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/FoundryAgents_Step22_MemorySearch.csproj
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
- Exe
- net10.0
-
- enable
- enable
- $(NoWarn);CA1812
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/README.md
deleted file mode 100644
index 9e6d79d579..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step22_MemorySearch/README.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Using Memory Search with AI Agents
-
-This sample demonstrates how to use the Memory Search tool with AI agents. The Memory Search tool enables agents to recall information from previous conversations, supporting user profile persistence and chat summaries across sessions.
-
-## What this sample demonstrates
-
-- Creating an agent with Memory Search tool capabilities
-- Configuring memory scope for user isolation
-- Having conversations where the agent remembers past information
-- Inspecting memory search results from agent responses
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and deployment configured
-- Azure CLI installed and authenticated (for Azure credential authentication)
-- **A pre-created Memory Store** (see below)
-
-**Note**: This demo uses Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
-
-### Creating a Memory Store
-
-Memory stores must be created before running this sample. The .NET SDK currently only supports **using** existing memory stores with agents. To create a memory store, use one of these methods:
-
-**Option 1: Azure Portal**
-1. Navigate to your Azure AI Foundry project
-2. Go to the Memory section
-3. Create a new memory store with your desired settings
-
-**Option 2: Python SDK**
-```python
-from azure.ai.projects import AIProjectClient
-from azure.ai.projects.models import MemoryStoreDefaultDefinition, MemoryStoreDefaultOptions
-from azure.identity import DefaultAzureCredential
-
-project_client = AIProjectClient(
- endpoint="https://your-endpoint.openai.azure.com/",
- credential=DefaultAzureCredential()
-)
-
-memory_store = await project_client.memory_stores.create(
- name="my-memory-store",
- description="Memory store for Agent Framework conversations",
- definition=MemoryStoreDefaultDefinition(
- chat_model=os.environ["AZURE_AI_CHAT_MODEL_DEPLOYMENT_NAME"],
- embedding_model=os.environ["AZURE_AI_EMBEDDING_MODEL_DEPLOYMENT_NAME"],
- options=MemoryStoreDefaultOptions(
- user_profile_enabled=True,
- chat_summary_enabled=True
- )
- )
-)
-```
-
-## Environment Variables
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_FOUNDRY_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project"
-$env:AZURE_FOUNDRY_PROJECT_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-$env:AZURE_AI_MEMORY_STORE_NAME="your-memory-store-name" # Required - name of pre-created memory store
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step22_MemorySearch
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Create an agent with Memory Search tool configured
-2. Send a message with personal information ("My name is Alice and I love programming in C#")
-3. Wait for memory indexing
-4. Ask the agent to recall the previously shared information
-5. Display memory search results if available in the response
-6. Clean up by deleting the agent (note: memory store persists)
-
-## Important notes
-
-- **Memory Store Lifecycle**: Memory stores are long-lived resources and are NOT deleted when the agent is deleted. Clean them up separately via Azure Portal or Python SDK.
-- **Scope**: The `scope` parameter isolates memories per user/context. Use unique identifiers for different users.
-- **Update Delay**: The `UpdateDelay` parameter controls how quickly new memories are indexed.
diff --git a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/README.md b/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/README.md
deleted file mode 100644
index 8651108987..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/FoundryAgents_Step23_LocalMCP/README.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Using Local MCP Client with Azure Foundry Agents
-
-This sample demonstrates how to use a local MCP (Model Context Protocol) client with Azure Foundry Agents. Unlike the hosted MCP approach where Azure Foundry invokes the MCP server on the service side, this sample connects to the MCP server directly from the client via HTTP (Streamable HTTP transport) and passes the resolved tools to the agent.
-
-## What this sample demonstrates
-
-- Connecting to an MCP server locally using `HttpClientTransport`
-- Discovering available tools from the MCP server client-side
-- Passing locally-resolved MCP tools to a Foundry agent
-- Using the Microsoft Learn MCP endpoint for documentation search
-- Managing agent lifecycle (creation and deletion)
-
-## Prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure 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 Azure 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" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-## Run the sample
-
-Navigate to the FoundryAgents sample directory and run:
-
-```powershell
-cd dotnet/samples/02-agents/FoundryAgents
-dotnet run --project .\FoundryAgents_Step23_LocalMCP
-```
-
-## Expected behavior
-
-The sample will:
-
-1. Connect to the Microsoft Learn MCP server via HTTP and list available tools
-2. Create an agent with the locally-resolved MCP tools
-3. Ask two questions about Microsoft documentation
-4. The agent will use the MCP tools (invoked locally) to search Microsoft Learn documentation
-5. Display the agent's responses with information from the documentation
-6. Clean up resources by deleting the agent
diff --git a/dotnet/samples/02-agents/FoundryAgents/README.md b/dotnet/samples/02-agents/FoundryAgents/README.md
deleted file mode 100644
index 426a8cdad5..0000000000
--- a/dotnet/samples/02-agents/FoundryAgents/README.md
+++ /dev/null
@@ -1,121 +0,0 @@
-# Getting started with Foundry Agents
-
-The getting started with Foundry Agents samples demonstrate the fundamental concepts and functionalities
-of Azure Foundry Agents and can be used with Azure Foundry as the AI provider.
-
-These samples showcase how to work with agents managed through Azure Foundry, including agent creation,
-versioning, multi-turn conversations, and advanced features like code interpretation and computer use.
-
-## Classic vs New Foundry Agents
-
-> [!NOTE]
-> Recently, Azure Foundry introduced a new and improved experience for creating and managing AI agents, which is the target of these samples.
-
-For more information about the previous classic agents and for what's new in Foundry Agents, see the [Foundry Agents migration documentation](https://learn.microsoft.com/en-us/azure/ai-foundry/agents/how-to/migrate?view=foundry).
-
-For a sample demonstrating how to use classic Foundry Agents, see the following: [Agent with Azure AI Persistent](../AgentProviders/Agent_With_AzureAIAgentsPersistent/README.md).
-
-## Agent Versioning and Static Definitions
-
-One of the key architectural changes in the new Foundry Agents compared to the classic experience is how agent definitions are handled. In the new architecture, agents have **versions** and their definitions are established at creation time. This means that the agent's configuration—including instructions, tools, and options—is fixed when the agent version is created.
-
-> [!IMPORTANT]
-> Agent versions are static and strictly adhere to their original definition. Any attempt to provide or override tools, instructions, or options during an agent run or request will be ignored by the agent, as the API does not support runtime configuration changes. All agent behavior must be defined at agent creation time.
-
-This design ensures consistency and predictability in agent behavior across all interactions with a specific agent version.
-
-The Agent Framework intentionally ignores unsupported runtime parameters rather than throwing exceptions. This abstraction-first approach ensures that code written against the unified agent abstraction remains portable across providers (OpenAI, Azure OpenAI, Foundry Agents). It removes the need for provider-specific conditional logic. Teams can adopt Foundry Agents without rewriting existing orchestration code. Configurations that work with other providers will gracefully degrade, rather than fail, when the underlying API does not support them.
-
-## Getting started with Foundry Agents prerequisites
-
-Before you begin, ensure you have the following prerequisites:
-
-- .NET 10 SDK or later
-- Azure Foundry service endpoint and project configured
-- Azure CLI installed and authenticated (for Azure credential authentication)
-
-**Note**: These samples use Azure Foundry Agents. For more information, see [Azure AI Foundry documentation](https://learn.microsoft.com/en-us/azure/ai-foundry/).
-
-**Note**: These samples use Azure CLI credentials for authentication. Make sure you're logged in with `az login` and have access to the Azure Foundry resource. For more information, see the [Azure CLI documentation](https://learn.microsoft.com/cli/azure/authenticate-azure-cli-interactively).
-
-## Samples
-
-|Sample|Description|
-|---|---|
-|[Basics](./FoundryAgents_Step01.1_Basics/)|This sample demonstrates how to create and manage AI agents with versioning|
-|[Running a simple agent](./FoundryAgents_Step01.2_Running/)|This sample demonstrates how to create and run a basic Foundry agent|
-|[Multi-turn conversation](./FoundryAgents_Step02_MultiturnConversation/)|This sample demonstrates how to implement a multi-turn conversation with a Foundry agent|
-|[Using function tools](./FoundryAgents_Step03_UsingFunctionTools/)|This sample demonstrates how to use function tools with a Foundry agent|
-|[Using function tools with approvals](./FoundryAgents_Step04_UsingFunctionToolsWithApprovals/)|This sample demonstrates how to use function tools where approvals require human in the loop approvals before execution|
-|[Structured output](./FoundryAgents_Step05_StructuredOutput/)|This sample demonstrates how to use structured output with a Foundry agent|
-|[Persisted conversations](./FoundryAgents_Step06_PersistedConversations/)|This sample demonstrates how to persist conversations and reload them later|
-|[Observability](./FoundryAgents_Step07_Observability/)|This sample demonstrates how to add telemetry to a Foundry agent|
-|[Dependency injection](./FoundryAgents_Step08_DependencyInjection/)|This sample demonstrates how to add and resolve a Foundry agent with a dependency injection container|
-|[Using MCP client as tools](./FoundryAgents_Step09_UsingMcpClientAsTools/)|This sample demonstrates how to use MCP clients as tools with a Foundry agent|
-|[Using images](./FoundryAgents_Step10_UsingImages/)|This sample demonstrates how to use image multi-modality with a Foundry agent|
-|[Exposing as a function tool](./FoundryAgents_Step11_AsFunctionTool/)|This sample demonstrates how to expose a Foundry agent as a function tool|
-|[Using middleware](./FoundryAgents_Step12_Middleware/)|This sample demonstrates how to use middleware with a Foundry agent|
-|[Using plugins](./FoundryAgents_Step13_Plugins/)|This sample demonstrates how to use plugins with a Foundry agent|
-|[Code interpreter](./FoundryAgents_Step14_CodeInterpreter/)|This sample demonstrates how to use the code interpreter tool with a Foundry agent|
-|[Computer use](./FoundryAgents_Step15_ComputerUse/)|This sample demonstrates how to use computer use capabilities with a Foundry agent|
-|[File search](./FoundryAgents_Step16_FileSearch/)|This sample demonstrates how to use the file search tool with a Foundry agent|
-|[OpenAPI tools](./FoundryAgents_Step17_OpenAPITools/)|This sample demonstrates how to use OpenAPI tools with a Foundry agent|
-|[Bing Custom Search](./FoundryAgents_Step18_BingCustomSearch/)|This sample demonstrates how to use Bing Custom Search tool with a Foundry agent|
-|[SharePoint grounding](./FoundryAgents_Step19_SharePoint/)|This sample demonstrates how to use the SharePoint grounding tool with a Foundry agent|
-|[Microsoft Fabric](./FoundryAgents_Step20_MicrosoftFabric/)|This sample demonstrates how to use Microsoft Fabric tool with a Foundry agent|
-|[Web search](./FoundryAgents_Step21_WebSearch/)|This sample demonstrates how to use the Responses API web search tool with a Foundry agent|
-|[Memory search](./FoundryAgents_Step22_MemorySearch/)|This sample demonstrates how to use memory search tool with a Foundry agent|
-|[Local MCP](./FoundryAgents_Step23_LocalMCP/)|This sample demonstrates how to use a local MCP client with a Foundry agent|
-
-## Evaluation Samples
-
-Evaluation is critical for building trustworthy and high-quality AI applications. The evaluation samples demonstrate how to assess agent safety, quality, and performance using Azure AI Foundry's evaluation capabilities.
-
-|Sample|Description|
-|---|---|
-|[Red Team Evaluation](./FoundryAgents_Evaluations_Step01_RedTeaming/)|This sample demonstrates how to use Azure AI Foundry's Red Teaming service to assess model safety against adversarial attacks|
-|[Self-Reflection with Groundedness](./FoundryAgents_Evaluations_Step02_SelfReflection/)|This sample demonstrates the self-reflection pattern where agents iteratively improve responses based on groundedness evaluation|
-
-For details on safety evaluation, see the [Red Team Evaluation README](./FoundryAgents_Evaluations_Step01_RedTeaming/README.md).
-
-## Running the samples from the console
-
-To run the samples, navigate to the desired sample directory, e.g.
-
-```powershell
-cd FoundryAgents_Step01.2_Running
-```
-
-Set the following environment variables:
-
-```powershell
-$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" # Replace with your Azure Foundry resource endpoint
-$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" # Optional, defaults to gpt-4o-mini
-```
-
-If the variables are not set, you will be prompted for the values when running the samples.
-
-Execute the following command to build the sample:
-
-```powershell
-dotnet build
-```
-
-Execute the following command to run the sample:
-
-```powershell
-dotnet run --no-build
-```
-
-Or just build and run in one step:
-
-```powershell
-dotnet run
-```
-
-## Running the samples from Visual Studio
-
-Open the solution in Visual Studio and set the desired sample project as the startup project. Then, run the project using the built-in debugger or by pressing `F5`.
-
-You will be prompted for any required environment variables if they are not already set.
-
diff --git a/dotnet/samples/02-agents/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs b/dotnet/samples/02-agents/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs
index e91ed4d15a..bedf87b8c5 100644
--- a/dotnet/samples/02-agents/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs
+++ b/dotnet/samples/02-agents/ModelContextProtocol/FoundryAgent_Hosted_MCP/Program.cs
@@ -5,9 +5,11 @@
// The sample first shows how to use MCP tools with auto approval, and then how to set up a tool that requires approval before it can be invoked and how to approve such a tool.
using Azure.AI.Projects;
+using Azure.AI.Projects.Agents;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
+using OpenAI.Responses;
var endpoint = Environment.GetEnvironmentVariable("AZURE_AI_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("AZURE_AI_PROJECT_ENDPOINT is not set.");
var model = Environment.GetEnvironmentVariable("AZURE_AI_MODEL_DEPLOYMENT_NAME") ?? "gpt-4.1-mini";
@@ -23,26 +25,22 @@ var aiProjectClient = new AIProjectClient(new Uri(endpoint), new DefaultAzureCre
// Create an MCP tool definition that the agent can use.
// In this case we allow the tool to always be called without approval.
-var mcpTool = new HostedMcpServerTool(
- serverName: "microsoft_learn",
- serverAddress: "https://learn.microsoft.com/api/mcp")
-{
- AllowedTools = ["microsoft_docs_search"],
- ApprovalMode = HostedMcpServerToolApprovalMode.NeverRequire
-};
+var mcpTool = ResponseTool.CreateMcpTool(
+ serverLabel: "microsoft_learn",
+ serverUri: new Uri("https://learn.microsoft.com/api/mcp"),
+ toolCallApprovalPolicy: new McpToolCallApprovalPolicy(GlobalMcpToolCallApprovalPolicy.NeverRequireApproval));
// Create a server side agent with the mcp tool, and expose it as an AIAgent.
-AIAgent agent = await aiProjectClient.CreateAIAgentAsync(
- model: model,
- options: new()
- {
- Name = "MicrosoftLearnAgent",
- ChatOptions = new()
+AgentVersion agentVersion = await aiProjectClient.Agents.CreateAgentVersionAsync(
+ "MicrosoftLearnAgent",
+ new AgentVersionCreationOptions(
+ new PromptAgentDefinition(model: model)
{
Instructions = "You answer questions by searching the Microsoft Learn content only.",
- Tools = [mcpTool]
- },
- });
+ Tools = { mcpTool }
+ }));
+
+AIAgent agent = aiProjectClient.AsAIAgent(agentVersion);
// You can then invoke the agent like any other AIAgent.
AgentSession session = await agent.CreateSessionAsync();
@@ -56,26 +54,23 @@ aiProjectClient.Agents.DeleteAgent(agent.Name);
// Create an MCP tool definition that the agent can use.
// In this case we require approval before the tool can be called.
-var mcpToolWithApproval = new HostedMcpServerTool(
- serverName: "microsoft_learn",
- serverAddress: "https://learn.microsoft.com/api/mcp")
-{
- AllowedTools = ["microsoft_docs_search"],
- ApprovalMode = HostedMcpServerToolApprovalMode.AlwaysRequire
-};
+var mcpToolWithApproval = ResponseTool.CreateMcpTool(
+ serverLabel: "microsoft_learn",
+ serverUri: new Uri("https://learn.microsoft.com/api/mcp"),
+ allowedTools: new McpToolFilter() { ToolNames = { "microsoft_docs_search" } },
+ toolCallApprovalPolicy: new McpToolCallApprovalPolicy(GlobalMcpToolCallApprovalPolicy.AlwaysRequireApproval));
// Create an agent with the MCP tool that requires approval.
-AIAgent agentWithRequiredApproval = await aiProjectClient.CreateAIAgentAsync(
- model: model,
- options: new()
- {
- Name = "MicrosoftLearnAgentWithApproval",
- ChatOptions = new()
+AgentVersion agentVersionWithApproval = await aiProjectClient.Agents.CreateAgentVersionAsync(
+ "MicrosoftLearnAgentWithApproval",
+ new AgentVersionCreationOptions(
+ new PromptAgentDefinition(model: model)
{
Instructions = "You answer questions by searching the Microsoft Learn content only.",
- Tools = [mcpToolWithApproval]
- },
- });
+ Tools = { mcpToolWithApproval }
+ }));
+
+AIAgent agentWithRequiredApproval = aiProjectClient.AsAIAgent(agentVersionWithApproval);
// You can then invoke the agent like any other AIAgent.
// For simplicity, we are assuming here that only mcp tool approvals are pending.
diff --git a/dotnet/samples/02-agents/README.md b/dotnet/samples/02-agents/README.md
index b901645f88..5ff0db416d 100644
--- a/dotnet/samples/02-agents/README.md
+++ b/dotnet/samples/02-agents/README.md
@@ -1,22 +1,21 @@
-# Getting started
+# Getting started
-The getting started samples demonstrate the fundamental concepts and functionalities
-of the agent framework.
+The getting started samples demonstrate the fundamental concepts and functionality of the agent framework.
## Samples
-|Sample|Description|
-|---|---|
-|[Agents](./Agents/README.md)|Step by step instructions for getting started with agents|
-|[Foundry Agents](./FoundryAgents/README.md)|Getting started with Azure Foundry Agents|
-|[Agent Providers](./AgentProviders/README.md)|Getting started with creating agents using various providers|
-|[Agents With Retrieval Augmented Generation (RAG)](./AgentWithRAG/README.md)|Adding Retrieval Augmented Generation (RAG) capabilities to your agents.|
-|[Agents With Memory](./AgentWithMemory/README.md)|Adding Memory capabilities to your agents.|
-|[Agent Open Telemetry](./AgentOpenTelemetry/README.md)|Getting started with OpenTelemetry for agents|
-|[Agent With OpenAI exchange types](./AgentWithOpenAI/README.md)|Using OpenAI exchange types with agents|
-|[Agent With Anthropic](./AgentWithAnthropic/README.md)|Getting started with agents using Anthropic Claude|
-|[Model Context Protocol](./ModelContextProtocol/README.md)|Getting started with Model Context Protocol|
-|[Agent Skills](./AgentSkills/README.md)|Getting started with Agent Skills|
-|[Declarative Agents](./DeclarativeAgents)|Loading and executing AI agents from YAML configuration files| │
-|[AG-UI](./AGUI/README.md)|Getting started with AG-UI (Agent UI Protocol) servers and clients| │
-|[Dev UI](./DevUI/README.md)|Interactive web interface for testing and debugging AI agents during development|
\ No newline at end of file
+| Sample | Description |
+| --- | --- |
+| [Agents](./Agents/README.md) | Step-by-step instructions for getting started with agents |
+| [Agents with Foundry](./AgentsWithFoundry/README.md) | Foundry agent samples using `FoundryAgent` and `AIProjectClient.AsAIAgent(...)` |
+| [Agent Providers](./AgentProviders/README.md) | Getting started with creating agents using various providers |
+| [Agents With Retrieval Augmented Generation (RAG)](./AgentWithRAG/README.md) | Adding Retrieval Augmented Generation (RAG) capabilities to your agents |
+| [Agents With Memory](./AgentWithMemory/README.md) | Adding memory capabilities to your agents |
+| [Agent Open Telemetry](./AgentOpenTelemetry/README.md) | Getting started with OpenTelemetry for agents |
+| [Agent With OpenAI exchange types](./AgentWithOpenAI/README.md) | Using OpenAI exchange types with agents |
+| [Agent With Anthropic](./AgentWithAnthropic/README.md) | Getting started with agents using Anthropic Claude |
+| [Model Context Protocol](./ModelContextProtocol/README.md) | Getting started with Model Context Protocol |
+| [Agent Skills](./AgentSkills/README.md) | Getting started with Agent Skills |
+| [Declarative Agents](./DeclarativeAgents) | Loading and executing AI agents from YAML configuration files |
+| [AG-UI](./AGUI/README.md) | Getting started with AG-UI (Agent UI Protocol) servers and clients |
+| [Dev UI](./DevUI/README.md) | Interactive web interface for testing and debugging AI agents during development |
diff --git a/dotnet/samples/03-workflows/Agents/FoundryAgent/Program.cs b/dotnet/samples/03-workflows/Agents/FoundryAgent/Program.cs
index 589eca2bbc..5b1f59ac62 100644
--- a/dotnet/samples/03-workflows/Agents/FoundryAgent/Program.cs
+++ b/dotnet/samples/03-workflows/Agents/FoundryAgent/Program.cs
@@ -1,8 +1,10 @@
// Copyright (c) Microsoft. All rights reserved.
using Azure.AI.Projects;
+using Azure.AI.Projects.Agents;
using Azure.Identity;
using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.AzureAI;
using Microsoft.Agents.AI.Workflows;
using Microsoft.Extensions.AI;
@@ -68,15 +70,19 @@ public static class Program
/// The target language for translation
/// The to create the agent with.
/// The model to use for the agent
- /// A ChatClientAgent configured for the specified language
- private static async Task CreateTranslationAgentAsync(
+ /// A FoundryAgent configured for the specified language
+ private static async Task CreateTranslationAgentAsync(
string targetLanguage,
AIProjectClient aiProjectClient,
string model)
{
- return await aiProjectClient.CreateAIAgentAsync(
- name: $"{targetLanguage} Translator",
- model: model,
- instructions: $"You are a translation assistant that translates the provided text to {targetLanguage}.");
+ AgentVersion agentVersion = await aiProjectClient.Agents.CreateAgentVersionAsync(
+ $"{targetLanguage} Translator",
+ new AgentVersionCreationOptions(
+ new PromptAgentDefinition(model: model)
+ {
+ Instructions = $"You are a translation assistant that translates the provided text to {targetLanguage}.",
+ }));
+ return aiProjectClient.AsAIAgent(agentVersion);
}
}
diff --git a/dotnet/samples/03-workflows/Declarative/HostedWorkflow/Program.cs b/dotnet/samples/03-workflows/Declarative/HostedWorkflow/Program.cs
index 5936aaf82f..7852a8730f 100644
--- a/dotnet/samples/03-workflows/Declarative/HostedWorkflow/Program.cs
+++ b/dotnet/samples/03-workflows/Declarative/HostedWorkflow/Program.cs
@@ -8,6 +8,7 @@ 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 Microsoft.Extensions.Configuration;
using Shared.Foundry;
@@ -49,7 +50,7 @@ internal sealed class Program
string workflowInput = GetWorkflowInput(args);
- AIAgent agent = aiProjectClient.AsAIAgent(agentVersion);
+ FoundryAgent agent = aiProjectClient.AsAIAgent(agentVersion);
AgentSession session = await agent.CreateSessionAsync();
diff --git a/dotnet/samples/03-workflows/README.md b/dotnet/samples/03-workflows/README.md
index 2b8d375654..1ab52106ec 100644
--- a/dotnet/samples/03-workflows/README.md
+++ b/dotnet/samples/03-workflows/README.md
@@ -1,6 +1,6 @@
-# Workflow Getting Started Samples
+# Workflow Getting Started Samples
-The getting started with workflow samples demonstrate the fundamental concepts and functionalities of workflows in Agent Framework.
+The workflow samples demonstrate the fundamental concepts and functionality of workflows in Agent Framework.
## Samples Overview
@@ -20,15 +20,13 @@ Please begin with the [Start Here](./_StartHere) samples in order. These three s
| [Mixed Workflow with Agents and Executors](./_StartHere/06_MixedWorkflowAgentsAndExecutors) | Shows how to mix agents and executors with adapter pattern for type conversion and protocol handling |
| [Writer-Critic Workflow](./_StartHere/07_WriterCriticWorkflow) | Demonstrates iterative refinement with quality gates, max iteration safety, multiple message handlers, and conditional routing for feedback loops |
-Once completed, please proceed to other samples listed below.
-
-> Note that you don't need to follow a strict order after the foundational samples. However, some samples build upon concepts from previous ones, so it's beneficial to be aware of the dependencies.
+Once completed, please proceed to the other samples listed below.
### Agents
| Sample | Concepts |
|--------|----------|
-| [Foundry Agents in Workflows](./Agents/FoundryAgent) | Demonstrates using Azure Foundry Agents within a workflow |
+| [Foundry Agents in Workflows](./Agents/FoundryAgent) | Demonstrates using Azure Foundry agents in a workflow through `ChatClientAgent` |
| [Custom Agent Executors](./Agents/CustomAgentExecutors) | Shows how to create a custom agent executor for more complex scenarios |
| [Workflow as an Agent](./Agents/WorkflowAsAnAgent) | Illustrates how to encapsulate a workflow as an agent |
| [Group Chat with Tool Approval](./Agents/GroupChatToolApproval) | Shows multi-agent group chat with tool approval requests and human-in-the-loop interaction |
@@ -58,25 +56,3 @@ Once completed, please proceed to other samples listed below.
| [Edge Conditions](./ConditionalEdges/01_EdgeCondition) | Introduces conditional edges for dynamic routing based on executor outputs |
| [Switch-Case Routing](./ConditionalEdges/02_SwitchCase) | Extends conditional edges with switch-case routing for multiple paths |
| [Multi-Selection Routing](./ConditionalEdges/03_MultiSelection) | Demonstrates multi-selection routing where one executor can trigger multiple downstream executors |
-
-> These 3 samples build upon each other. It's recommended to explore them in sequence to fully grasp the concepts.
-
-### Declarative Workflows
-
-| Sample | Concepts |
-|--------|----------|
-| [Declarative](./Declarative) | Demonstrates execution of declartive workflows. |
-
-### Checkpointing
-
-| Sample | Concepts |
-|--------|----------|
-| [Checkpoint and Resume](./Checkpoint/CheckpointAndResume) | Introduces checkpoints for saving and restoring workflow state for time travel purposes |
-| [Checkpoint and Rehydrate](./Checkpoint/CheckpointAndRehydrate) | Demonstrates hydrating a new workflow instance from a saved checkpoint |
-| [Checkpoint with Human-in-the-Loop](./Checkpoint/CheckpointWithHumanInTheLoop) | Combines checkpointing with human-in-the-loop interactions |
-
-### Human-in-the-Loop
-
-| Sample | Concepts |
-|--------|----------|
-| [Basic Human-in-the-Loop](./HumanInTheLoop/HumanInTheLoopBasic) | Introduces human-in-the-loop interaction using input ports and external requests |
diff --git a/dotnet/samples/05-end-to-end/A2AClientServer/A2AServer/HostAgentFactory.cs b/dotnet/samples/05-end-to-end/A2AClientServer/A2AServer/HostAgentFactory.cs
index 1149f9a293..13c01be156 100644
--- a/dotnet/samples/05-end-to-end/A2AClientServer/A2AServer/HostAgentFactory.cs
+++ b/dotnet/samples/05-end-to-end/A2AClientServer/A2AServer/HostAgentFactory.cs
@@ -2,6 +2,7 @@
using A2A;
using Azure.AI.Projects;
+using Azure.AI.Projects.Agents;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
@@ -19,8 +20,8 @@ internal static class HostAgentFactory
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
var aiProjectClient = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential());
- AIAgent agent = await aiProjectClient
- .GetAIAgentAsync(agentName, tools: tools);
+ AgentRecord agentRecord = await aiProjectClient.Agents.GetAgentAsync(agentName);
+ AIAgent agent = aiProjectClient.AsAIAgent(agentRecord, tools: tools);
AgentCard agentCard = agentType.ToUpperInvariant() switch
{
diff --git a/dotnet/samples/AGENTS.md b/dotnet/samples/AGENTS.md
index 1578b39a26..f515f531eb 100644
--- a/dotnet/samples/AGENTS.md
+++ b/dotnet/samples/AGENTS.md
@@ -28,7 +28,7 @@ dotnet/samples/
│ ├── AGUI/ # AG-UI protocol samples
│ ├── DeclarativeAgents/ # Declarative agent definitions
│ ├── DevUI/ # DevUI samples
-│ ├── FoundryAgents/ # Azure AI Foundry agent samples
+│ ├── AgentsWithFoundry/ # Azure AI Foundry samples (FoundryAgent + AsAIAgent extensions)
│ └── ModelContextProtocol/ # MCP server/client patterns
├── 03-workflows/ # Workflow patterns
│ ├── _StartHere/ # Introductory workflow samples
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectChatClient.cs b/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectChatClient.cs
index 32bb08674b..ec788233ed 100644
--- a/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectChatClient.cs
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectChatClient.cs
@@ -44,7 +44,7 @@ internal sealed class AzureAIProjectChatClient : DelegatingChatClient
{
this._agentClient = aiProjectClient;
this._agentReference = Throw.IfNull(agentReference);
- this._metadata = new ChatClientMetadata("azure.ai.agents", defaultModelId: defaultModelId);
+ this._metadata = new ChatClientMetadata("microsoft.foundry", defaultModelId: defaultModelId);
this._chatOptions = chatOptions;
}
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectChatClientExtensions.cs b/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectChatClientExtensions.cs
index b129f4b1f2..479ab894ae 100644
--- a/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectChatClientExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectChatClientExtensions.cs
@@ -14,6 +14,7 @@ using Azure.AI.Projects.Agents;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.AzureAI;
using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Logging;
using Microsoft.Shared.DiagnosticIds;
using Microsoft.Shared.Diagnostics;
using OpenAI;
@@ -42,7 +43,7 @@ public static partial class AzureAIProjectChatClientExtensions
/// When instantiating a by using an , minimal information will be available about the agent in the instance level, and any logic that relies
/// on to retrieve information about the agent like will receive as the result.
///
- public static ChatClientAgent AsAIAgent(
+ public static FoundryAgent AsAIAgent(
this AIProjectClient aiProjectClient,
AgentReference agentReference,
IList? tools = null,
@@ -53,7 +54,7 @@ public static partial class AzureAIProjectChatClientExtensions
Throw.IfNull(agentReference);
ThrowIfInvalidAgentName(agentReference.Name);
- return AsChatClientAgent(
+ var innerAgent = AsChatClientAgent(
aiProjectClient,
agentReference,
new ChatClientAgentOptions()
@@ -64,6 +65,8 @@ public static partial class AzureAIProjectChatClientExtensions
},
clientFactory,
services);
+
+ return new FoundryAgent(aiProjectClient, innerAgent);
}
///
@@ -79,7 +82,8 @@ public static partial class AzureAIProjectChatClientExtensions
/// Thrown when or is .
/// Thrown when is empty or whitespace, or when the agent with the specified name was not found.
/// The agent with the specified name was not found.
- public static async Task GetAIAgentAsync(
+ [Obsolete("Use native AIProjectClient agent APIs and AsAIAgent(AgentRecord/AgentVersion) instead.")]
+ public static async Task GetAIAgentAsync(
this AIProjectClient aiProjectClient,
string name,
IList? tools = null,
@@ -110,7 +114,7 @@ public static partial class AzureAIProjectChatClientExtensions
/// An optional to use for resolving services required by the instances being invoked.
/// A instance that can be used to perform operations based on the latest version of the Azure AI Agent.
/// Thrown when or is .
- public static ChatClientAgent AsAIAgent(
+ public static FoundryAgent AsAIAgent(
this AIProjectClient aiProjectClient,
AgentRecord agentRecord,
IList? tools = null,
@@ -122,13 +126,15 @@ public static partial class AzureAIProjectChatClientExtensions
var allowDeclarativeMode = tools is not { Count: > 0 };
- return AsChatClientAgent(
+ var innerAgent = AsChatClientAgent(
aiProjectClient,
agentRecord,
tools,
clientFactory,
!allowDeclarativeMode,
services);
+
+ return new FoundryAgent(aiProjectClient, innerAgent);
}
///
@@ -141,7 +147,7 @@ public static partial class AzureAIProjectChatClientExtensions
/// An optional to use for resolving services required by the instances being invoked.
/// A instance that can be used to perform operations based on the provided version of the Azure AI Agent.
/// Thrown when or is .
- public static ChatClientAgent AsAIAgent(
+ public static FoundryAgent AsAIAgent(
this AIProjectClient aiProjectClient,
AgentVersion agentVersion,
IList? tools = null,
@@ -153,13 +159,15 @@ public static partial class AzureAIProjectChatClientExtensions
var allowDeclarativeMode = tools is not { Count: > 0 };
- return AsChatClientAgent(
+ var innerAgent = AsChatClientAgent(
aiProjectClient,
agentVersion,
tools,
clientFactory,
!allowDeclarativeMode,
services);
+
+ return new FoundryAgent(aiProjectClient, innerAgent);
}
///
@@ -172,7 +180,8 @@ public static partial class AzureAIProjectChatClientExtensions
/// A to cancel the operation if needed.
/// A instance that can be used to perform operations on the newly created agent.
/// Thrown when or is .
- public static async Task GetAIAgentAsync(
+ [Obsolete("Use native AIProjectClient agent APIs and AsAIAgent(AgentRecord/AgentVersion) instead.")]
+ public static async Task GetAIAgentAsync(
this AIProjectClient aiProjectClient,
ChatClientAgentOptions options,
Func? clientFactory = null,
@@ -194,12 +203,9 @@ public static partial class AzureAIProjectChatClientExtensions
var agentOptions = CreateChatClientAgentOptions(agentVersion, options, requireInvocableTools: !options.UseProvidedChatClientAsIs);
- return AsChatClientAgent(
+ return new FoundryAgent(
aiProjectClient,
- agentVersion,
- agentOptions,
- clientFactory,
- services);
+ AsChatClientAgent(aiProjectClient, agentVersion, agentOptions, clientFactory, services));
}
///
@@ -218,7 +224,8 @@ public static partial class AzureAIProjectChatClientExtensions
/// Thrown when , , or is .
/// Thrown when or is empty or whitespace.
/// When using prompt agent definitions with tools the parameter needs to be provided.
- public static Task CreateAIAgentAsync(
+ [Obsolete("Use native AIProjectClient.Agents APIs instead.")]
+ public static Task CreateAIAgentAsync(
this AIProjectClient aiProjectClient,
string name,
string model,
@@ -256,7 +263,8 @@ public static partial class AzureAIProjectChatClientExtensions
/// A instance that can be used to perform operations on the newly created agent.
/// Thrown when or is .
/// Thrown when is empty or whitespace, or when the agent name is not provided in the options.
- public static async Task CreateAIAgentAsync(
+ [Obsolete("Use native AIProjectClient.Agents APIs instead.")]
+ public static async Task CreateAIAgentAsync(
this AIProjectClient aiProjectClient,
string model,
ChatClientAgentOptions options,
@@ -267,7 +275,6 @@ public static partial class AzureAIProjectChatClientExtensions
Throw.IfNull(aiProjectClient);
Throw.IfNull(options);
Throw.IfNullOrWhitespace(model);
- const bool RequireInvocableTools = true;
if (string.IsNullOrWhiteSpace(options.Name))
{
@@ -276,43 +283,13 @@ public static partial class AzureAIProjectChatClientExtensions
ThrowIfInvalidAgentName(options.Name);
- PromptAgentDefinition agentDefinition = new(model)
- {
- Instructions = options.ChatOptions?.Instructions,
- Temperature = options.ChatOptions?.Temperature,
- TopP = options.ChatOptions?.TopP,
- TextOptions = new() { TextFormat = ToOpenAIResponseTextFormat(options.ChatOptions?.ResponseFormat, options.ChatOptions) }
- };
+ AgentVersion agentVersion = await CreateAgentVersionFromOptionsAsync(aiProjectClient, model, options, cancellationToken).ConfigureAwait(false);
- // Map reasoning options from the abstraction-level ChatOptions.Reasoning,
- // falling back to extracting from the raw representation factory for breaking glass scenarios.
- if (options.ChatOptions?.Reasoning is { } reasoning)
- {
- agentDefinition.ReasoningOptions = ToResponseReasoningOptions(reasoning);
- }
- else if (options.ChatOptions?.RawRepresentationFactory?.Invoke(new NoOpChatClient()) is CreateResponseOptions respCreationOptions)
- {
- agentDefinition.ReasoningOptions = respCreationOptions.ReasoningOptions;
- }
+ var agentOptions = CreateChatClientAgentOptions(agentVersion, options, requireInvocableTools: true);
- ApplyToolsToAgentDefinition(agentDefinition, options.ChatOptions?.Tools);
-
- AgentVersionCreationOptions? creationOptions = new(agentDefinition);
- if (!string.IsNullOrWhiteSpace(options.Description))
- {
- creationOptions.Description = options.Description;
- }
-
- AgentVersion agentVersion = await CreateAgentVersionWithProtocolAsync(aiProjectClient, options.Name, creationOptions, cancellationToken).ConfigureAwait(false);
-
- var agentOptions = CreateChatClientAgentOptions(agentVersion, options, RequireInvocableTools);
-
- return AsChatClientAgent(
+ return new FoundryAgent(
aiProjectClient,
- agentVersion,
- agentOptions,
- clientFactory,
- services);
+ AsChatClientAgent(aiProjectClient, agentVersion, agentOptions, clientFactory, services));
}
///
@@ -330,7 +307,8 @@ public static partial class AzureAIProjectChatClientExtensions
/// When using this extension method with a the tools are only declarative and not invocable.
/// Invocation of any in-process tools will need to be handled manually.
///
- public static Task CreateAIAgentAsync(
+ [Obsolete("Use native AIProjectClient.Agents APIs instead.")]
+ public static Task CreateAIAgentAsync(
this AIProjectClient aiProjectClient,
string name,
AgentVersionCreationOptions creationOptions,
@@ -351,6 +329,75 @@ public static partial class AzureAIProjectChatClientExtensions
cancellationToken);
}
+ ///
+ /// Creates a non-versioned backed by the project's Responses API using the specified model and instructions.
+ ///
+ /// The to use for Responses API calls. Cannot be .
+ /// The model deployment name to use for the agent. Cannot be or whitespace.
+ /// The instructions that guide the agent's behavior. Cannot be or whitespace.
+ /// Optional name for the agent.
+ /// Optional human-readable description for the agent.
+ /// Optional collection of tools that the agent can invoke during conversations.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// Optional logger factory for creating loggers used by the agent.
+ /// An optional to use for resolving services required by the instances being invoked.
+ /// A backed by the project's Responses API.
+ /// Thrown when is .
+ /// Thrown when or is empty or whitespace.
+ public static FoundryAgent AsAIAgent(
+ this AIProjectClient aiProjectClient,
+ string model,
+ string instructions,
+ string? name = null,
+ string? description = null,
+ IList? tools = null,
+ Func? clientFactory = null,
+ ILoggerFactory? loggerFactory = null,
+ IServiceProvider? services = null)
+ {
+ Throw.IfNull(aiProjectClient);
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNullOrWhitespace(instructions);
+
+ ChatClientAgentOptions options = new()
+ {
+ Name = name,
+ Description = description,
+ ChatOptions = new ChatOptions
+ {
+ ModelId = model,
+ Instructions = instructions,
+ Tools = tools,
+ },
+ };
+
+ return new FoundryAgent(aiProjectClient, CreateResponsesChatClientAgent(aiProjectClient, options, clientFactory, loggerFactory, services));
+ }
+
+ ///
+ /// Creates a non-versioned backed by the project's Responses API using the specified options.
+ ///
+ /// The to use for Responses API calls. Cannot be .
+ /// Configuration options that control the agent's behavior. is required.
+ /// Provides a way to customize the creation of the underlying used by the agent.
+ /// Optional logger factory for creating loggers used by the agent.
+ /// An optional to use for resolving services required by the instances being invoked.
+ /// A backed by the project's Responses API.
+ /// Thrown when or is .
+ /// Thrown when does not specify .
+ public static FoundryAgent AsAIAgent(
+ this AIProjectClient aiProjectClient,
+ ChatClientAgentOptions options,
+ Func? clientFactory = null,
+ ILoggerFactory? loggerFactory = null,
+ IServiceProvider? services = null)
+ {
+ Throw.IfNull(aiProjectClient);
+ Throw.IfNull(options);
+
+ return new FoundryAgent(aiProjectClient, CreateResponsesChatClientAgent(aiProjectClient, options, clientFactory, loggerFactory, services));
+ }
+
#region Private
private static readonly ModelReaderWriterOptions s_modelWriterOptionsWire = new("W");
@@ -358,7 +405,7 @@ public static partial class AzureAIProjectChatClientExtensions
///
/// Asynchronously retrieves an agent record by name using the protocol method to inject user-agent headers.
///
- private static async Task GetAgentRecordByNameAsync(AIProjectClient aiProjectClient, string agentName, CancellationToken cancellationToken)
+ internal static async Task GetAgentRecordByNameAsync(AIProjectClient aiProjectClient, string agentName, CancellationToken cancellationToken)
{
ClientResult protocolResponse = await aiProjectClient.Agents.GetAgentAsync(agentName, cancellationToken.ToRequestOptions(false)).ConfigureAwait(false);
var rawResponse = protocolResponse.GetRawResponse();
@@ -369,7 +416,7 @@ public static partial class AzureAIProjectChatClientExtensions
///
/// Asynchronously creates an agent version using the protocol method to inject user-agent headers.
///
- private static async Task CreateAgentVersionWithProtocolAsync(AIProjectClient aiProjectClient, string agentName, AgentVersionCreationOptions creationOptions, CancellationToken cancellationToken)
+ internal static async Task CreateAgentVersionWithProtocolAsync(AIProjectClient aiProjectClient, string agentName, AgentVersionCreationOptions creationOptions, CancellationToken cancellationToken)
{
BinaryData serializedOptions = ModelReaderWriter.Write(creationOptions, s_modelWriterOptionsWire, AzureAIProjectsAgentsContext.Default);
BinaryContent content = BinaryContent.Create(serializedOptions);
@@ -379,7 +426,7 @@ public static partial class AzureAIProjectChatClientExtensions
return result ?? throw new InvalidOperationException($"Failed to create agent version for agent '{agentName}'.");
}
- private static async Task CreateAIAgentAsync(
+ private static async Task CreateAIAgentAsync(
this AIProjectClient aiProjectClient,
string name,
IList? tools,
@@ -397,17 +444,61 @@ public static partial class AzureAIProjectChatClientExtensions
AgentVersion agentVersion = await CreateAgentVersionWithProtocolAsync(aiProjectClient, name, creationOptions, cancellationToken).ConfigureAwait(false);
- return AsChatClientAgent(
- aiProjectClient,
- agentVersion,
- tools,
- clientFactory,
- !allowDeclarativeMode,
- services);
+ return new FoundryAgent(aiProjectClient, AsChatClientAgent(aiProjectClient, agentVersion, tools, clientFactory, !allowDeclarativeMode, services));
}
- /// This method creates an with the specified ChatClientAgentOptions.
- private static ChatClientAgent AsChatClientAgent(
+ ///
+ /// Creates an agent version with optional tool application, using the protocol method to inject user-agent headers.
+ ///
+ internal static async Task CreateAgentVersionWithProtocolAsync(AIProjectClient aiProjectClient, string agentName, AgentVersionCreationOptions creationOptions, IList? tools, CancellationToken cancellationToken)
+ {
+ if (tools is { Count: > 0 })
+ {
+ ApplyToolsToAgentDefinition(creationOptions.Definition, tools);
+ }
+
+ return await CreateAgentVersionWithProtocolAsync(aiProjectClient, agentName, creationOptions, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ /// Creates an agent version from , mapping options to a .
+ ///
+ internal static async Task CreateAgentVersionFromOptionsAsync(
+ AIProjectClient aiProjectClient,
+ string model,
+ ChatClientAgentOptions options,
+ CancellationToken cancellationToken)
+ {
+ PromptAgentDefinition agentDefinition = new(model)
+ {
+ Instructions = options.ChatOptions?.Instructions,
+ Temperature = options.ChatOptions?.Temperature,
+ TopP = options.ChatOptions?.TopP,
+ TextOptions = new() { TextFormat = ToOpenAIResponseTextFormat(options.ChatOptions?.ResponseFormat, options.ChatOptions) }
+ };
+
+ if (options.ChatOptions?.Reasoning is { } reasoning)
+ {
+ agentDefinition.ReasoningOptions = ToResponseReasoningOptions(reasoning);
+ }
+ else if (options.ChatOptions?.RawRepresentationFactory?.Invoke(new NoOpChatClient()) is CreateResponseOptions respCreationOptions)
+ {
+ agentDefinition.ReasoningOptions = respCreationOptions.ReasoningOptions;
+ }
+
+ ApplyToolsToAgentDefinition(agentDefinition, options.ChatOptions?.Tools);
+
+ AgentVersionCreationOptions creationOptions = new(agentDefinition);
+ if (!string.IsNullOrWhiteSpace(options.Description))
+ {
+ creationOptions.Description = options.Description;
+ }
+
+ return await CreateAgentVersionWithProtocolAsync(aiProjectClient, options.Name!, creationOptions, cancellationToken).ConfigureAwait(false);
+ }
+
+ /// Creates a with the specified options.
+ internal static ChatClientAgent CreateChatClientAgent(
AIProjectClient aiProjectClient,
AgentVersion agentVersion,
ChatClientAgentOptions agentOptions,
@@ -424,6 +515,37 @@ public static partial class AzureAIProjectChatClientExtensions
return new ChatClientAgent(chatClient, agentOptions, services: services);
}
+ internal static ChatClientAgent CreateResponsesChatClientAgent(
+ AIProjectClient aiProjectClient,
+ ChatClientAgentOptions agentOptions,
+ Func? clientFactory,
+ ILoggerFactory? loggerFactory,
+ IServiceProvider? services)
+ {
+ Throw.IfNull(aiProjectClient);
+ Throw.IfNull(agentOptions);
+ Throw.IfNull(agentOptions.ChatOptions);
+ Throw.IfNullOrWhitespace(agentOptions.ChatOptions.ModelId);
+
+ IChatClient chatClient = new AzureAIProjectResponsesChatClient(aiProjectClient, agentOptions.ChatOptions.ModelId);
+
+ if (clientFactory is not null)
+ {
+ chatClient = clientFactory(chatClient);
+ }
+
+ return new ChatClientAgent(chatClient, agentOptions, loggerFactory, services);
+ }
+
+ /// This method creates an with the specified ChatClientAgentOptions.
+ private static ChatClientAgent AsChatClientAgent(
+ AIProjectClient aiProjectClient,
+ AgentVersion agentVersion,
+ ChatClientAgentOptions agentOptions,
+ Func? clientFactory,
+ IServiceProvider? services)
+ => CreateChatClientAgent(aiProjectClient, agentVersion, agentOptions, clientFactory, services);
+
/// This method creates an with the specified ChatClientAgentOptions.
private static ChatClientAgent AsChatClientAgent(
AIProjectClient aiProjectClient,
@@ -503,7 +625,7 @@ public static partial class AzureAIProjectChatClientExtensions
/// This method rebuilds the agent options from the agent definition returned by the version and combine with the in-proc tools when provided
/// this ensures that all required tools are provided and the definition of the agent options are consistent with the agent definition coming from the server.
///
- private static ChatClientAgentOptions CreateChatClientAgentOptions(AgentVersion agentVersion, ChatOptions? chatOptions, bool requireInvocableTools)
+ internal static ChatClientAgentOptions CreateChatClientAgentOptions(AgentVersion agentVersion, ChatOptions? chatOptions, bool requireInvocableTools)
{
var agentDefinition = agentVersion.Definition;
@@ -591,7 +713,7 @@ public static partial class AzureAIProjectChatClientExtensions
/// Specifies whether the returned options must include invocable tools. Set to to require
/// invocable tools; otherwise, .
/// A instance configured according to the specified parameters.
- private static ChatClientAgentOptions CreateChatClientAgentOptions(AgentVersion agentVersion, ChatClientAgentOptions? options, bool requireInvocableTools)
+ internal static ChatClientAgentOptions CreateChatClientAgentOptions(AgentVersion agentVersion, ChatClientAgentOptions? options, bool requireInvocableTools)
{
var agentOptions = CreateChatClientAgentOptions(agentVersion, options?.ChatOptions, requireInvocableTools);
if (options is not null)
@@ -768,7 +890,7 @@ public static partial class AzureAIProjectChatClientExtensions
private static Regex AgentNameValidationRegex() => new("^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$");
#endif
- private static string ThrowIfInvalidAgentName(string? name)
+ internal static string ThrowIfInvalidAgentName(string? name)
{
Throw.IfNullOrWhitespace(name);
if (!AgentNameValidationRegex().IsMatch(name))
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectResponsesChatClient.cs b/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectResponsesChatClient.cs
new file mode 100644
index 0000000000..48bb20d766
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAI/AzureAIProjectResponsesChatClient.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using Azure.AI.Projects;
+using Microsoft.Extensions.AI;
+using Microsoft.Shared.Diagnostics;
+
+namespace Microsoft.Agents.AI.AzureAI;
+
+#pragma warning disable OPENAI001
+internal sealed class AzureAIProjectResponsesChatClient : DelegatingChatClient
+{
+ private readonly ChatClientMetadata _metadata;
+ private readonly AIProjectClient _aiProjectClient;
+
+ internal AzureAIProjectResponsesChatClient(AIProjectClient aiProjectClient, string defaultModelId)
+ : base(Throw.IfNull(aiProjectClient)
+ .GetProjectOpenAIClient()
+ .GetProjectResponsesClientForModel(Throw.IfNullOrWhitespace(defaultModelId))
+ .AsIChatClient())
+ {
+ this._aiProjectClient = aiProjectClient;
+ this._metadata = new ChatClientMetadata("microsoft.foundry", defaultModelId: defaultModelId);
+ }
+
+ public override object? GetService(Type serviceType, object? serviceKey = null)
+ {
+ return (serviceKey is null && serviceType == typeof(ChatClientMetadata))
+ ? this._metadata
+ : (serviceKey is null && serviceType == typeof(AIProjectClient))
+ ? this._aiProjectClient
+ : base.GetService(serviceType, serviceKey);
+ }
+}
+#pragma warning restore OPENAI001
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAI/FoundryAITool.cs b/dotnet/src/Microsoft.Agents.AI.AzureAI/FoundryAITool.cs
new file mode 100644
index 0000000000..80ed48e1df
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAI/FoundryAITool.cs
@@ -0,0 +1,210 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Diagnostics.CodeAnalysis;
+using Azure.AI.Projects.Agents;
+using Microsoft.Extensions.AI;
+using Microsoft.Shared.DiagnosticIds;
+using OpenAI.Responses;
+
+#pragma warning disable OPENAI001
+
+namespace Microsoft.Agents.AI.AzureAI;
+
+///
+/// Provides factory methods for creating instances from Microsoft Foundry and OpenAI response tools.
+///
+///
+///
+/// This class wraps (Azure.AI.Projects.OpenAI) and (OpenAI SDK) factory methods,
+/// returning directly — eliminating the need for manual casting and .AsAITool() calls.
+///
+///
+/// Instead of writing:
+/// ((ResponseTool)AgentTool.CreateOpenApiTool(definition)).AsAITool()
+/// You can write:
+/// FoundryAITool.CreateOpenApiTool(definition)
+///
+///
+[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
+public static class FoundryAITool
+{
+ ///
+ /// Converts an existing into an .
+ ///
+ /// The response tool to convert.
+ /// An wrapping the provided response tool.
+ public static AITool FromResponseTool(ResponseTool responseTool) => responseTool.AsAITool();
+
+ // --- Azure.AI.Projects.OpenAI AgentTool factories ---
+
+ ///
+ /// Creates an for OpenAPI tool invocations.
+ ///
+ /// The OpenAPI function definition specifying the API endpoint, schema, and authentication.
+ /// An that calls the specified OpenAPI endpoint.
+ public static AITool CreateOpenApiTool(OpenApiFunctionDefinition definition)
+ => ((ResponseTool)AgentTool.CreateOpenApiTool(definition)).AsAITool();
+
+ ///
+ /// Creates an for Bing Grounding search.
+ ///
+ /// The Bing Grounding search configuration options.
+ /// An for Bing Grounding search.
+ public static AITool CreateBingGroundingTool(BingGroundingSearchToolOptions options)
+ => ((ResponseTool)AgentTool.CreateBingGroundingTool(options)).AsAITool();
+
+ ///
+ /// Creates an for Bing Custom Search.
+ ///
+ /// The Bing Custom Search configuration parameters.
+ /// An for Bing Custom Search.
+ public static AITool CreateBingCustomSearchTool(BingCustomSearchToolOptions parameters)
+ => ((ResponseTool)AgentTool.CreateBingCustomSearchTool(parameters)).AsAITool();
+
+ ///
+ /// Creates an for Microsoft Fabric data agent.
+ ///
+ /// The Fabric data agent configuration options.
+ /// An for Microsoft Fabric.
+ public static AITool CreateMicrosoftFabricTool(FabricDataAgentToolOptions options)
+ => ((ResponseTool)AgentTool.CreateMicrosoftFabricTool(options)).AsAITool();
+
+ ///
+ /// Creates an for SharePoint grounding.
+ ///
+ /// The SharePoint grounding configuration options.
+ /// An for SharePoint grounding.
+ public static AITool CreateSharepointTool(SharePointGroundingToolOptions options)
+ => ((ResponseTool)AgentTool.CreateSharepointTool(options)).AsAITool();
+
+ ///
+ /// Creates an for Azure AI Search.
+ ///
+ /// Optional Azure AI Search configuration options.
+ /// An for Azure AI Search.
+ public static AITool CreateAzureAISearchTool(AzureAISearchToolOptions? options = null)
+ => ((ResponseTool)AgentTool.CreateAzureAISearchTool(options)).AsAITool();
+
+ ///
+ /// Creates an for browser automation.
+ ///
+ /// The browser automation configuration parameters.
+ /// An for browser automation.
+ public static AITool CreateBrowserAutomationTool(BrowserAutomationToolOptions parameters)
+ => ((ResponseTool)AgentTool.CreateBrowserAutomationTool(parameters)).AsAITool();
+
+ ///
+ /// Creates an for structured output capture.
+ ///
+ /// The structured output definition.
+ /// An for structured output capture.
+ public static AITool CreateStructuredOutputsTool(StructuredOutputDefinition outputs)
+ => ((ResponseTool)AgentTool.CreateStructuredOutputsTool(outputs)).AsAITool();
+
+ ///
+ /// Creates an for Agent-to-Agent (A2A) communication.
+ ///
+ /// The base URI for the A2A agent.
+ /// Optional path to the agent card.
+ /// An for A2A communication.
+ public static AITool CreateA2ATool(Uri baseUri, string? agentCardPath = null)
+ => AgentTool.CreateA2ATool(baseUri, agentCardPath).AsAITool();
+
+ // --- OpenAI SDK ResponseTool factories ---
+
+ ///
+ /// Creates an for computer use (screen interaction).
+ ///
+ /// The computer tool environment type.
+ /// The display width in pixels.
+ /// The display height in pixels.
+ /// An for computer use.
+ [Experimental("OPENAICUA001")]
+ public static AITool CreateComputerTool(ComputerToolEnvironment environment, int displayWidth, int displayHeight)
+ => ResponseTool.CreateComputerTool(environment, displayWidth, displayHeight).AsAITool();
+
+ ///
+ /// Creates an for function tool invocations.
+ ///
+ /// The name of the function.
+ /// The function parameters schema as JSON.
+ /// Whether strict mode is enabled for parameter validation.
+ /// Optional description of the function.
+ /// An for function invocations.
+ public static AITool CreateFunctionTool(string functionName, BinaryData functionParameters, bool? strictModeEnabled, string? functionDescription = null)
+ => ResponseTool.CreateFunctionTool(functionName, functionParameters, strictModeEnabled, functionDescription).AsAITool();
+
+ ///
+ /// Creates an for file search over vector stores.
+ ///
+ /// The IDs of vector stores to search.
+ /// Optional maximum number of results to return.
+ /// Optional ranking options for search results.
+ /// Optional filters for search results.
+ /// An for file search.
+ public static AITool CreateFileSearchTool(IEnumerable vectorStoreIds, int? maxResultCount = null, FileSearchToolRankingOptions? rankingOptions = null, BinaryData? filters = null)
+ => ResponseTool.CreateFileSearchTool(vectorStoreIds, maxResultCount, rankingOptions, filters).AsAITool();
+
+ ///
+ /// Creates an for web search.
+ ///
+ /// Optional user location for search context.
+ /// Optional search context size.
+ /// Optional search filters.
+ /// An for web search.
+ public static AITool CreateWebSearchTool(WebSearchToolLocation? userLocation = null, WebSearchToolContextSize? searchContextSize = null, WebSearchToolFilters? filters = null)
+ => ResponseTool.CreateWebSearchTool(userLocation, searchContextSize, filters).AsAITool();
+
+ ///
+ /// Creates an for MCP (Model Context Protocol) server tools.
+ ///
+ /// The label for the MCP server.
+ /// The URI of the MCP server.
+ /// Optional authorization token.
+ /// Optional server description.
+ /// Optional custom headers.
+ /// Optional filter for allowed tools.
+ /// Optional tool call approval policy.
+ /// An for MCP server tools.
+ public static AITool CreateMcpTool(string serverLabel, Uri serverUri, string? authorizationToken = null, string? serverDescription = null, IDictionary? headers = null, McpToolFilter? allowedTools = null, McpToolCallApprovalPolicy? toolCallApprovalPolicy = null)
+ => ResponseTool.CreateMcpTool(serverLabel, serverUri, authorizationToken, serverDescription, headers, allowedTools, toolCallApprovalPolicy).AsAITool();
+
+ ///
+ /// Creates an for MCP (Model Context Protocol) server tools using a connector ID.
+ ///
+ /// The label for the MCP server.
+ /// The connector ID for the MCP server.
+ /// Optional authorization token.
+ /// Optional server description.
+ /// Optional custom headers.
+ /// Optional filter for allowed tools.
+ /// Optional tool call approval policy.
+ /// An for MCP server tools.
+ public static AITool CreateMcpTool(string serverLabel, McpToolConnectorId connectorId, string? authorizationToken = null, string? serverDescription = null, IDictionary? headers = null, McpToolFilter? allowedTools = null, McpToolCallApprovalPolicy? toolCallApprovalPolicy = null)
+ => ResponseTool.CreateMcpTool(serverLabel, connectorId, authorizationToken, serverDescription, headers, allowedTools, toolCallApprovalPolicy).AsAITool();
+
+ ///
+ /// Creates an for code interpreter.
+ ///
+ /// The container configuration for the code interpreter.
+ /// An for code interpreter.
+ public static AITool CreateCodeInterpreterTool(CodeInterpreterToolContainer container)
+ => ResponseTool.CreateCodeInterpreterTool(container).AsAITool();
+
+ ///
+ /// Creates an for image generation.
+ ///
+ /// The model to use for image generation.
+ /// Optional image quality setting.
+ /// Optional image size setting.
+ /// Optional output file format.
+ /// Optional output compression factor.
+ /// Optional moderation level.
+ /// Optional background setting.
+ /// Optional input fidelity setting.
+ /// Optional input image mask.
+ /// Optional partial image count.
+ /// An for image generation.
+ public static AITool CreateImageGenerationTool(string model, ImageGenerationToolQuality? quality = null, ImageGenerationToolSize? size = null, ImageGenerationToolOutputFileFormat? outputFileFormat = null, int? outputCompressionFactor = null, ImageGenerationToolModerationLevel? moderationLevel = null, ImageGenerationToolBackground? background = null, ImageGenerationToolInputFidelity? inputFidelity = null, ImageGenerationToolInputImageMask? inputImageMask = null, int? partialImageCount = null)
+ => ResponseTool.CreateImageGenerationTool(model, quality, size, outputFileFormat, outputCompressionFactor, moderationLevel, background, inputFidelity, inputImageMask, partialImageCount).AsAITool();
+}
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAI/FoundryAgent.cs b/dotnet/src/Microsoft.Agents.AI.AzureAI/FoundryAgent.cs
new file mode 100644
index 0000000000..66fa93e39f
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAI/FoundryAgent.cs
@@ -0,0 +1,208 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.ClientModel;
+using System.Diagnostics.CodeAnalysis;
+using Azure.AI.Extensions.OpenAI;
+using Azure.AI.Projects;
+using Microsoft.Extensions.AI;
+using Microsoft.Extensions.Logging;
+using Microsoft.Shared.DiagnosticIds;
+using Microsoft.Shared.Diagnostics;
+
+namespace Microsoft.Agents.AI.AzureAI;
+
+///
+/// Provides an that uses Microsoft Foundry for AI agent capabilities.
+///
+///
+///
+/// connects to a pre-configured server-side agent in Microsoft Foundry,
+/// wrapping it as an for use with Agent Framework. Unlike the direct
+/// AIProjectClient.AsAIAgent(model, instructions) approach (which creates a local agent
+/// backed by the Responses API without any server-side agent definition),
+/// works with agents that are managed and versioned in the Foundry service.
+///
+///
+/// This class provides convenient access to Foundry-specific features such as server-side
+/// conversation management via .
+///
+///
+/// Instances can be created directly via public constructors or through
+/// AsAIAgent extension methods on .
+///
+///
+[Experimental(DiagnosticIds.Experiments.AIOpenAIResponses)]
+public sealed class FoundryAgent : DelegatingAIAgent
+{
+ private readonly AIProjectClient _aiProjectClient;
+
+ ///
+ /// Initializes a new instance of the class using the direct Responses API path.
+ ///
+ /// The Microsoft Foundry project endpoint.
+ /// The authentication credential.
+ /// The model deployment name.
+ /// The instructions that guide the agent's behavior.
+ /// Optional configuration options for the .
+ /// Optional name for the agent.
+ /// Optional description for the agent.
+ /// Optional tools to use when interacting with the agent.
+ /// Provides a way to customize the creation of the underlying .
+ /// Optional logger factory for creating loggers used by the agent.
+ /// Optional service provider for resolving dependencies required by AI functions.
+ public FoundryAgent(
+ Uri projectEndpoint,
+ AuthenticationTokenProvider credential,
+ string model,
+ string instructions,
+ AIProjectClientOptions? clientOptions = null,
+ string? name = null,
+ string? description = null,
+ IList? tools = null,
+ Func? clientFactory = null,
+ ILoggerFactory? loggerFactory = null,
+ IServiceProvider? services = null)
+ : base(CreateInnerAgent(
+ CreateProjectClient(projectEndpoint, credential, clientOptions),
+ model, instructions, name, description, tools, clientFactory, loggerFactory, services,
+ out var aiProjectClient))
+ {
+ this._aiProjectClient = aiProjectClient;
+ }
+
+ ///
+ /// Initializes a new instance of the class from an agent-specific endpoint.
+ ///
+ /// The agent-specific endpoint URI (must contain the agent name in the path).
+ /// The authentication credential.
+ /// Optional configuration options for the .
+ /// Optional tools to use when interacting with the agent.
+ /// Provides a way to customize the creation of the underlying .
+ /// Optional service provider for resolving dependencies required by AI functions.
+ public FoundryAgent(
+ Uri agentEndpoint,
+ AuthenticationTokenProvider credential,
+ AIProjectClientOptions? clientOptions = null,
+ IList? tools = null,
+ Func? clientFactory = null,
+ IServiceProvider? services = null)
+ : base(CreateInnerAgentFromEndpoint(
+ CreateProjectClient(agentEndpoint, credential, clientOptions),
+ agentEndpoint, tools, clientFactory, services,
+ out var aiProjectClient))
+ {
+ this._aiProjectClient = aiProjectClient;
+ }
+
+ ///
+ /// Internal constructor used by AsAIAgent extension methods that already have an and a configured .
+ ///
+ internal FoundryAgent(AIProjectClient aiProjectClient, ChatClientAgent innerAgent)
+ : base(Throw.IfNull(innerAgent))
+ {
+ this._aiProjectClient = Throw.IfNull(aiProjectClient);
+ }
+
+ #region Convenience methods
+
+ ///
+ /// Creates a server-side conversation session that appears in the Foundry Project UI.
+ ///
+ /// A token to monitor for cancellation requests.
+ /// A linked to the newly created server-side conversation.
+ public async Task CreateConversationSessionAsync(CancellationToken cancellationToken = default)
+ {
+ var conversationsClient = this._aiProjectClient
+ .GetProjectOpenAIClient()
+ .GetProjectConversationsClient();
+
+ var conversation = (await conversationsClient.CreateProjectConversationAsync(options: null, cancellationToken).ConfigureAwait(false)).Value;
+
+ return (ChatClientAgentSession)await ((ChatClientAgent)this.InnerAgent).CreateSessionAsync(conversation.Id, cancellationToken).ConfigureAwait(false);
+ }
+
+ #endregion
+
+ ///
+ public override object? GetService(Type serviceType, object? serviceKey = null)
+ {
+ if (serviceKey is null && serviceType == typeof(AIProjectClient))
+ {
+ return this._aiProjectClient;
+ }
+
+ return base.GetService(serviceType, serviceKey);
+ }
+
+ #region Private helpers
+
+ private static ChatClientAgent CreateInnerAgent(
+ AIProjectClient aiProjectClient,
+ string model, string instructions,
+ string? name, string? description,
+ IList? tools,
+ Func? clientFactory,
+ ILoggerFactory? loggerFactory,
+ IServiceProvider? services,
+ out AIProjectClient outClient)
+ {
+ Throw.IfNullOrWhitespace(model);
+ Throw.IfNullOrWhitespace(instructions);
+
+ outClient = aiProjectClient;
+
+ ChatClientAgentOptions options = new()
+ {
+ Name = name,
+ Description = description,
+ ChatOptions = new ChatOptions
+ {
+ ModelId = model,
+ Instructions = instructions,
+ Tools = tools,
+ },
+ };
+
+ return AzureAIProjectChatClientExtensions.CreateResponsesChatClientAgent(aiProjectClient, options, clientFactory, loggerFactory, services);
+ }
+
+ private static ChatClientAgent CreateInnerAgentFromEndpoint(
+ AIProjectClient aiProjectClient,
+ Uri agentEndpoint,
+ IList? tools,
+ Func? clientFactory,
+ IServiceProvider? services,
+ out AIProjectClient outClient)
+ {
+ outClient = aiProjectClient;
+
+ AgentReference agentReference = agentEndpoint.Segments[^1].TrimEnd('/');
+
+ ChatClientAgentOptions agentOptions = new()
+ {
+ Name = agentReference.Name,
+ ChatOptions = new() { Tools = tools },
+ };
+
+ IChatClient chatClient = new AzureAIProjectChatClient(aiProjectClient, agentReference, defaultModelId: null, agentOptions.ChatOptions);
+
+ if (clientFactory is not null)
+ {
+ chatClient = clientFactory(chatClient);
+ }
+
+ return new ChatClientAgent(chatClient, agentOptions, services: services);
+ }
+
+ private static AIProjectClient CreateProjectClient(Uri endpoint, AuthenticationTokenProvider credential, AIProjectClientOptions? clientOptions = null)
+ {
+ Throw.IfNull(endpoint);
+ Throw.IfNull(credential);
+
+ clientOptions ??= new AIProjectClientOptions();
+ clientOptions.AddPolicy(RequestOptionsExtensions.UserAgentPolicy, System.ClientModel.Primitives.PipelinePosition.PerCall);
+ return new AIProjectClient(endpoint, credential, clientOptions);
+ }
+
+ #endregion
+}
diff --git a/dotnet/src/Microsoft.Agents.AI.AzureAI/RequestOptionsExtensions.cs b/dotnet/src/Microsoft.Agents.AI.AzureAI/RequestOptionsExtensions.cs
index 722d316330..2705611b57 100644
--- a/dotnet/src/Microsoft.Agents.AI.AzureAI/RequestOptionsExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.AI.AzureAI/RequestOptionsExtensions.cs
@@ -7,6 +7,9 @@ namespace Microsoft.Agents.AI;
internal static class RequestOptionsExtensions
{
+ /// Gets the singleton that adds a MEAI user-agent header.
+ internal static PipelinePolicy UserAgentPolicy => MeaiUserAgentPolicy.Instance;
+
/// Creates a configured for use with Foundry Agents.
public static RequestOptions ToRequestOptions(this CancellationToken cancellationToken, bool streaming)
{
diff --git a/dotnet/src/Microsoft.Agents.AI.FoundryMemory/FoundryMemoryProvider.cs b/dotnet/src/Microsoft.Agents.AI.FoundryMemory/FoundryMemoryProvider.cs
index 6f9f37518e..93b343b2de 100644
--- a/dotnet/src/Microsoft.Agents.AI.FoundryMemory/FoundryMemoryProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI.FoundryMemory/FoundryMemoryProvider.cs
@@ -19,7 +19,7 @@ using OpenAI.Responses;
namespace Microsoft.Agents.AI.FoundryMemory;
///
-/// Provides an Azure AI Foundry Memory backed that persists conversation messages as memories
+/// Provides a Microsoft Foundry Memory backed that persists conversation messages as memories
/// and retrieves related memories to augment the agent invocation context.
///
///
@@ -49,7 +49,7 @@ public sealed class FoundryMemoryProvider : AIContextProvider
/// Initializes a new instance of the class.
///
/// The Azure AI Project client configured for your Foundry project.
- /// The name of the memory store in Azure AI Foundry.
+ /// The name of the memory store in Microsoft Foundry.
/// A delegate that initializes the provider state on the first invocation, providing the scope for memory storage and retrieval.
/// Provider options.
/// Optional logger factory.
@@ -87,17 +87,7 @@ public sealed class FoundryMemoryProvider : AIContextProvider
public override IReadOnlyList StateKeys => this._stateKeys ??= [this._sessionState.StateKey];
private static Func ValidateStateInitializer(Func stateInitializer) =>
- session =>
- {
- State state = stateInitializer(session);
-
- if (state is null)
- {
- throw new InvalidOperationException("State initializer must return a non-null state.");
- }
-
- return state;
- };
+ session => stateInitializer(session) ?? throw new InvalidOperationException("State initializer must return a non-null state.");
///
protected override async ValueTask ProvideAIContextAsync(InvokingContext context, CancellationToken cancellationToken = default)
@@ -332,7 +322,7 @@ public sealed class FoundryMemoryProvider : AIContextProvider
/// Waits for all pending memory update operations to complete.
///
///
- /// Memory extraction in Azure AI Foundry is asynchronous. This method polls the latest pending update
+ /// Memory extraction in Microsoft Foundry is asynchronous. This method polls the latest pending update
/// and returns when it has completed, failed, or been superseded. Since updates are processed in order,
/// completion of the latest update implies all prior updates have also been processed.
///
diff --git a/dotnet/src/Microsoft.Agents.AI.FoundryMemory/FoundryMemoryProviderScope.cs b/dotnet/src/Microsoft.Agents.AI.FoundryMemory/FoundryMemoryProviderScope.cs
index 717df1d12b..6646c482a3 100644
--- a/dotnet/src/Microsoft.Agents.AI.FoundryMemory/FoundryMemoryProviderScope.cs
+++ b/dotnet/src/Microsoft.Agents.AI.FoundryMemory/FoundryMemoryProviderScope.cs
@@ -9,7 +9,7 @@ namespace Microsoft.Agents.AI.FoundryMemory;
/// Allows scoping of memories for the .
///
///
-/// Azure AI Foundry memories are scoped by a single string identifier that you control.
+/// Microsoft Foundry memories are scoped by a single string identifier that you control.
/// Common patterns include using a user ID, team ID, or other unique identifier
/// to partition memories across different contexts.
///
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.AzureAI/AzureAgentProvider.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.AzureAI/AzureAgentProvider.cs
index bfc7bd36ff..6db870f8ec 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.AzureAI/AzureAgentProvider.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Declarative.AzureAI/AzureAgentProvider.cs
@@ -175,7 +175,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
AIProjectClient client = this.GetAgentClient();
- agent = client.AsAIAgent(agentVersion, tools: null, clientFactory: null, services: null);
+ agent = client.AsAIAgent(agentVersion);
FunctionInvokingChatClient? functionInvokingClient = agent.GetService();
if (functionInvokingClient is not null)
diff --git a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentRunStreamingTests.cs b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentRunStreamingTests.cs
index 870dda648c..0f2b123fd9 100644
--- a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentRunStreamingTests.cs
+++ b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentRunStreamingTests.cs
@@ -7,6 +7,8 @@ using Microsoft.Agents.AI;
namespace AzureAI.IntegrationTests;
+#pragma warning disable CS0618 // Tests intentionally exercise obsolete AIProjectClientFixture
+[Obsolete("Use FoundryVersionedAgentRunTests instead. These tests exercise obsolete AIProjectClient extension methods.")]
public class AIProjectClientAgentRunStreamingPreviousResponseTests() : RunStreamingTests(() => new())
{
public override Task RunWithNoMessageDoesNotFailAsync()
@@ -16,7 +18,8 @@ public class AIProjectClientAgentRunStreamingPreviousResponseTests() : RunStream
}
}
-public class AIProjectClientAgentRunStreamingConversationTests() : RunTests(() => new())
+[Obsolete("Use FoundryVersionedAgentRunTests instead. These tests exercise obsolete AIProjectClient extension methods.")]
+public class AIProjectClientAgentRunStreamingConversationTests() : RunStreamingTests(() => new())
{
public override Func> AgentRunOptionsFactory => async () =>
{
diff --git a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentRunTests.cs b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentRunTests.cs
index af4cee82e6..ad10ec5b7a 100644
--- a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentRunTests.cs
+++ b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentRunTests.cs
@@ -7,6 +7,8 @@ using Microsoft.Agents.AI;
namespace AzureAI.IntegrationTests;
+#pragma warning disable CS0618 // Tests intentionally exercise obsolete AIProjectClientFixture
+[Obsolete("Use FoundryVersionedAgentRunTests instead. These tests exercise obsolete AIProjectClient extension methods.")]
public class AIProjectClientAgentRunPreviousResponseTests() : RunTests(() => new())
{
public override Task RunWithNoMessageDoesNotFailAsync()
@@ -16,6 +18,7 @@ public class AIProjectClientAgentRunPreviousResponseTests() : RunTests(() => new())
{
public override Func> AgentRunOptionsFactory => async () =>
diff --git a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentStructuredOutputRunTests.cs b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentStructuredOutputRunTests.cs
index 9db48f3832..b3782a6601 100644
--- a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentStructuredOutputRunTests.cs
+++ b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientAgentStructuredOutputRunTests.cs
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All rights reserved.
+using System;
using System.Threading.Tasks;
using AgentConformance.IntegrationTests;
using AgentConformance.IntegrationTests.Support;
@@ -8,6 +9,8 @@ using Microsoft.Extensions.AI;
namespace AzureAI.IntegrationTests;
+#pragma warning disable CS0618 // Tests intentionally exercise obsolete AIProjectClientFixture
+[Obsolete("Use FoundryVersionedAgentStructuredOutputRunTests instead. These tests exercise obsolete AIProjectClient extension methods.")]
public class AIProjectClientAgentStructuredOutputRunTests() : StructuredOutputRunTests>(() => new AIProjectClientStructuredOutputFixture())
{
private const string NotSupported = "AIProjectClient does not support specifying structured output type at invocation time.";
@@ -87,6 +90,7 @@ public class AIProjectClientAgentStructuredOutputRunTests() : StructuredOutputRu
///
/// Represents a fixture for testing AIProjectClient with structured output of type provided at agent initialization.
///
+[Obsolete("Use FoundryVersionedAgentStructuredOutputFixture instead.")]
public class AIProjectClientStructuredOutputFixture : AIProjectClientFixture
{
public override async ValueTask InitializeAsync()
diff --git a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientChatClientAgentRunStreamingTests.cs b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientChatClientAgentRunStreamingTests.cs
index 3b0c1c27b4..0e507e44c1 100644
--- a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientChatClientAgentRunStreamingTests.cs
+++ b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientChatClientAgentRunStreamingTests.cs
@@ -1,10 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
+using System;
using System.Threading.Tasks;
using AgentConformance.IntegrationTests;
namespace AzureAI.IntegrationTests;
+#pragma warning disable CS0618 // Tests intentionally exercise obsolete AIProjectClientFixture
+[Obsolete("Use FoundryVersionedAgentRunTests instead. These tests exercise obsolete AIProjectClient extension methods.")]
public class AIProjectClientChatClientAgentRunStreamingTests() : ChatClientAgentRunStreamingTests(() => new())
{
public override Task RunWithInstructionsAndNoMessageReturnsExpectedResultAsync()
diff --git a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientChatClientAgentRunTests.cs b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientChatClientAgentRunTests.cs
index 1e47d0a970..a0ee72ebd4 100644
--- a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientChatClientAgentRunTests.cs
+++ b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientChatClientAgentRunTests.cs
@@ -1,10 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
+using System;
using System.Threading.Tasks;
using AgentConformance.IntegrationTests;
namespace AzureAI.IntegrationTests;
+#pragma warning disable CS0618 // Tests intentionally exercise obsolete AIProjectClientFixture
+[Obsolete("Use FoundryVersionedAgentRunTests instead. These tests exercise obsolete AIProjectClient extension methods.")]
public class AIProjectClientChatClientAgentRunTests() : ChatClientAgentRunTests(() => new())
{
public override Task RunWithInstructionsAndNoMessageReturnsExpectedResultAsync()
diff --git a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientCreateTests.cs b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientCreateTests.cs
index 425197853e..bc5f38acf2 100644
--- a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientCreateTests.cs
+++ b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientCreateTests.cs
@@ -1,5 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
+#pragma warning disable CS0618 // Tests intentionally exercise obsolete extension methods
+
using System;
using System.IO;
using System.Threading.Tasks;
@@ -7,6 +9,7 @@ using AgentConformance.IntegrationTests.Support;
using Azure.AI.Projects;
using Azure.AI.Projects.Agents;
using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.AzureAI;
using Microsoft.Extensions.AI;
using OpenAI.Files;
using OpenAI.Responses;
@@ -14,6 +17,7 @@ using Shared.IntegrationTests;
namespace AzureAI.IntegrationTests;
+[Obsolete("Use FoundryVersionedAgentCreateTests instead. These tests exercise obsolete AIProjectClient extension methods.")]
public class AIProjectClientCreateTests
{
private readonly AIProjectClient _client = new(new Uri(TestConfiguration.GetRequiredValue(TestSettings.AzureAIProjectEndpoint)), TestAzureCliCredentials.CreateAzureCliCredential());
@@ -51,7 +55,7 @@ public class AIProjectClientCreateTests
Assert.NotNull(agent);
Assert.Equal(AgentName, agent.Name);
Assert.Equal(AgentDescription, agent.Description);
- Assert.Equal(AgentInstructions, agent.Instructions);
+ Assert.Equal(AgentInstructions, agent.GetService()!.Instructions);
var agentRecord = await this._client.Agents.GetAgentAsync(agent.Name);
Assert.NotNull(agentRecord);
@@ -275,7 +279,7 @@ public class AIProjectClientCreateTests
try
{
// Step 2: Wrap the agent version using AsAIAgent extension.
- ChatClientAgent agent = this._client.AsAIAgent(agentVersion);
+ FoundryAgent agent = this._client.AsAIAgent(agentVersion);
// Assert the agent was created correctly and retains version metadata.
Assert.NotNull(agent);
@@ -327,7 +331,7 @@ public class AIProjectClientCreateTests
static string GetWeather(string location) => $"The weather in {location} is sunny with a high of 23C.";
var weatherFunction = AIFunctionFactory.Create(GetWeather);
- ChatClientAgent agent = createMechanism switch
+ FoundryAgent agent = createMechanism switch
{
"CreateWithChatClientAgentOptionsAsync" => await this._client.CreateAIAgentAsync(
model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName),
diff --git a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientFixture.cs b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientFixture.cs
index 42892b99b3..112c76571b 100644
--- a/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientFixture.cs
+++ b/dotnet/tests/AzureAI.IntegrationTests/AIProjectClientFixture.cs
@@ -1,5 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
+#pragma warning disable CS0618 // Tests intentionally exercise obsolete extension methods
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -9,18 +11,20 @@ using AgentConformance.IntegrationTests.Support;
using Azure.AI.Extensions.OpenAI;
using Azure.AI.Projects;
using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.AzureAI;
using Microsoft.Extensions.AI;
using OpenAI.Responses;
using Shared.IntegrationTests;
namespace AzureAI.IntegrationTests;
+[Obsolete("Use FoundryVersionedAgentFixture instead. These tests exercise obsolete AIProjectClient extension methods.")]
public class AIProjectClientFixture : IChatClientAgentFixture
{
- private ChatClientAgent _agent = null!;
+ private FoundryAgent _agent = null!;
private AIProjectClient _client = null!;
- public IChatClient ChatClient => this._agent.ChatClient;
+ public IChatClient ChatClient => this._agent.GetService()!.ChatClient;
public AIAgent Agent => this._agent;
@@ -115,14 +119,14 @@ public class AIProjectClientFixture : IChatClientAgentFixture
string instructions = "You are a helpful assistant.",
IList? aiTools = null)
{
- return await this._client.CreateAIAgentAsync(GenerateUniqueAgentName(name), model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName), instructions: instructions, tools: aiTools);
+ return (await this._client.CreateAIAgentAsync(GenerateUniqueAgentName(name), model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName), instructions: instructions, tools: aiTools)).GetService()!;
}
public async Task CreateChatClientAgentAsync(ChatClientAgentOptions options)
{
options.Name ??= GenerateUniqueAgentName("HelpfulAssistant");
- return await this._client.CreateAIAgentAsync(model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName), options);
+ return (await this._client.CreateAIAgentAsync(model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName), options)).GetService()!;
}
public static string GenerateUniqueAgentName(string baseName) =>
@@ -170,12 +174,13 @@ public class AIProjectClientFixture : IChatClientAgentFixture
public virtual async ValueTask InitializeAsync()
{
this._client = new(new Uri(TestConfiguration.GetRequiredValue(TestSettings.AzureAIProjectEndpoint)), TestAzureCliCredentials.CreateAzureCliCredential());
- this._agent = await this.CreateChatClientAgentAsync();
+ this._agent = await this._client.CreateAIAgentAsync(GenerateUniqueAgentName("HelpfulAssistant"), model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName), instructions: "You are a helpful assistant.");
}
public async Task InitializeAsync(ChatClientAgentOptions options)
{
this._client = new(new Uri(TestConfiguration.GetRequiredValue(TestSettings.AzureAIProjectEndpoint)), TestAzureCliCredentials.CreateAzureCliCredential());
- this._agent = await this.CreateChatClientAgentAsync(options);
+ options.Name ??= GenerateUniqueAgentName("HelpfulAssistant");
+ this._agent = await this._client.CreateAIAgentAsync(model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName), options);
}
}
diff --git a/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentChatClientRunStreamingTests.cs b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentChatClientRunStreamingTests.cs
new file mode 100644
index 0000000000..5895ceb8b9
--- /dev/null
+++ b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentChatClientRunStreamingTests.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
+
+namespace AzureAI.IntegrationTests;
+
+public class ResponsesAgentChatClientRunStreamingTests() : ChatClientAgentRunStreamingTests(() => new())
+{
+ public override Task RunWithInstructionsAndNoMessageReturnsExpectedResultAsync()
+ {
+ Assert.Skip("No messages is not supported");
+ return base.RunWithInstructionsAndNoMessageReturnsExpectedResultAsync();
+ }
+}
diff --git a/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentChatClientRunTests.cs b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentChatClientRunTests.cs
new file mode 100644
index 0000000000..d80b25deb2
--- /dev/null
+++ b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentChatClientRunTests.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
+
+namespace AzureAI.IntegrationTests;
+
+public class ResponsesAgentChatClientRunTests() : ChatClientAgentRunTests(() => new())
+{
+ public override Task RunWithInstructionsAndNoMessageReturnsExpectedResultAsync()
+ {
+ Assert.Skip("No messages is not supported");
+ return base.RunWithInstructionsAndNoMessageReturnsExpectedResultAsync();
+ }
+}
diff --git a/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentExtensionCreateTests.cs b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentExtensionCreateTests.cs
new file mode 100644
index 0000000000..cd8dc6cb03
--- /dev/null
+++ b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentExtensionCreateTests.cs
@@ -0,0 +1,122 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests.Support;
+using Azure.AI.Projects;
+using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.AzureAI;
+using Microsoft.Extensions.AI;
+using Shared.IntegrationTests;
+
+namespace AzureAI.IntegrationTests;
+
+///
+/// Integration tests for non-versioned creation via extension methods.
+///
+public class ResponsesAgentExtensionCreateTests
+{
+ private static Uri Endpoint => new(TestConfiguration.GetRequiredValue(TestSettings.AzureAIProjectEndpoint));
+
+ private static string Model => TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName);
+
+ private readonly AIProjectClient _client = new(Endpoint, TestAzureCliCredentials.CreateAzureCliCredential());
+
+ [Fact]
+ public async Task AsAIAgent_WithModelAndInstructions_CreatesChatClientAgentAndRunsAsync()
+ {
+ // Arrange
+ const string AgentName = "ResponsesAgentExtensionSimple";
+ const string AgentDescription = "Integration test agent created from AIProjectClient.AsAIAgent(model, instructions).";
+ const string VerificationToken = "integration-extension-ok";
+
+ FoundryAgent agent = this._client.AsAIAgent(
+ model: Model,
+ instructions: $"You are a helpful assistant. When asked for verification, reply with exactly '{VerificationToken}'.",
+ name: AgentName,
+ description: AgentDescription);
+
+ AgentSession session = await agent.CreateSessionAsync();
+
+ try
+ {
+ // Act
+ AgentResponse response = await agent.RunAsync("Return the verification token.", session);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal(AgentName, agent.Name);
+ Assert.Equal(AgentDescription, agent.Description);
+ Assert.Same(this._client, agent.GetService());
+ Assert.NotNull(agent.GetService());
+ Assert.Contains(VerificationToken, response.Text, StringComparison.OrdinalIgnoreCase);
+ }
+ finally
+ {
+ await DeleteSessionAsync(this._client, session);
+ }
+ }
+
+ [Fact]
+ public async Task AsAIAgent_WithOptions_CreatesChatClientAgentAndRunsAsync()
+ {
+ // Arrange
+ const string VerificationToken = "integration-options-ok";
+ ChatClientAgentOptions options = new()
+ {
+ Name = "ResponsesAgentExtensionOptions",
+ Description = "Integration test agent created from AIProjectClient.AsAIAgent(options).",
+ ChatOptions = new ChatOptions
+ {
+ ModelId = Model,
+ Instructions = $"You are a helpful assistant. When asked for verification, reply with exactly '{VerificationToken}'.",
+ },
+ };
+
+ FoundryAgent agent = this._client.AsAIAgent(options);
+ ChatClientAgentSession session = await agent.CreateConversationSessionAsync();
+
+ try
+ {
+ // Act
+ AgentResponse response = await agent.RunAsync("Return the verification token.", session);
+
+ // Assert
+ Assert.StartsWith("conv_", session.ConversationId, StringComparison.OrdinalIgnoreCase);
+ Assert.Equal(options.Name, agent.Name);
+ Assert.Equal(options.Description, agent.Description);
+ Assert.Same(this._client, agent.GetService());
+ Assert.Contains(VerificationToken, response.Text, StringComparison.OrdinalIgnoreCase);
+ }
+ finally
+ {
+ await DeleteSessionAsync(this._client, session);
+ }
+ }
+
+ private static async Task DeleteSessionAsync(AIProjectClient client, AgentSession session)
+ {
+ ChatClientAgentSession typedSession = (ChatClientAgentSession)session;
+
+ if (typedSession.ConversationId?.StartsWith("conv_", StringComparison.OrdinalIgnoreCase) == true)
+ {
+ await client.GetProjectOpenAIClient().GetProjectConversationsClient().DeleteConversationAsync(typedSession.ConversationId);
+ }
+ else if (typedSession.ConversationId?.StartsWith("resp_", StringComparison.OrdinalIgnoreCase) == true)
+ {
+ await DeleteResponseChainAsync(client, typedSession.ConversationId);
+ }
+ }
+
+ private static async Task DeleteResponseChainAsync(AIProjectClient client, string lastResponseId)
+ {
+ var responsesClient = client.GetProjectOpenAIClient().GetProjectResponsesClient();
+ var response = await responsesClient.GetResponseAsync(lastResponseId);
+ await responsesClient.DeleteResponseAsync(lastResponseId);
+
+ if (response.Value.PreviousResponseId is not null)
+ {
+ await DeleteResponseChainAsync(client, response.Value.PreviousResponseId);
+ }
+ }
+}
diff --git a/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentFixture.cs b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentFixture.cs
new file mode 100644
index 0000000000..ec678a00d9
--- /dev/null
+++ b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentFixture.cs
@@ -0,0 +1,187 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
+using AgentConformance.IntegrationTests.Support;
+using Azure.AI.Extensions.OpenAI;
+using Azure.AI.Projects;
+using Microsoft.Agents.AI;
+using Microsoft.Agents.AI.AzureAI;
+using Microsoft.Extensions.AI;
+using OpenAI.Responses;
+using Shared.IntegrationTests;
+
+namespace AzureAI.IntegrationTests;
+
+///
+/// Integration test fixture that creates non-versioned Responses agents via the direct AIProjectClient.AsAIAgent(...) path.
+///
+public class ResponsesAgentFixture : IChatClientAgentFixture
+{
+ private FoundryAgent _agent = null!;
+ private AIProjectClient _client = null!;
+
+ public IChatClient ChatClient => this._agent.GetService()!.ChatClient;
+
+ public AIAgent Agent => this._agent;
+
+ public async Task CreateConversationAsync()
+ {
+ var response = await this._client.GetProjectOpenAIClient().GetProjectConversationsClient().CreateProjectConversationAsync();
+ return response.Value.Id;
+ }
+
+ public async Task> GetChatHistoryAsync(AIAgent agent, AgentSession session)
+ {
+ ChatClientAgentSession chatClientSession = (ChatClientAgentSession)session;
+
+ if (chatClientSession.ConversationId?.StartsWith("conv_", StringComparison.OrdinalIgnoreCase) == true)
+ {
+ return await this.GetChatHistoryFromConversationAsync(chatClientSession.ConversationId);
+ }
+
+ if (chatClientSession.ConversationId?.StartsWith("resp_", StringComparison.OrdinalIgnoreCase) == true)
+ {
+ return await this.GetChatHistoryFromResponsesChainAsync(chatClientSession.ConversationId);
+ }
+
+ ChatHistoryProvider? chatHistoryProvider = agent.GetService();
+
+ if (chatHistoryProvider is null)
+ {
+ return [];
+ }
+
+ return (await chatHistoryProvider.InvokingAsync(new(agent, session, []))).ToList();
+ }
+
+ private async Task> GetChatHistoryFromResponsesChainAsync(string conversationId)
+ {
+ var openAIResponseClient = this._client.GetProjectOpenAIClient().GetProjectResponsesClient();
+ var inputItems = await openAIResponseClient.GetResponseInputItemsAsync(conversationId).ToListAsync();
+ var response = await openAIResponseClient.GetResponseAsync(conversationId);
+ ResponseItem responseItem = response.Value.OutputItems.FirstOrDefault()!;
+
+ var previousMessages = inputItems
+ .Select(ConvertToChatMessage)
+ .Where(x => x.Text != "You are a helpful assistant.")
+ .Reverse();
+
+ ChatMessage responseMessage = ConvertToChatMessage(responseItem);
+
+ return [.. previousMessages, responseMessage];
+ }
+
+ private static ChatMessage ConvertToChatMessage(ResponseItem item)
+ {
+ if (item is MessageResponseItem messageResponseItem)
+ {
+ ChatRole role = messageResponseItem.Role == MessageRole.User ? ChatRole.User : ChatRole.Assistant;
+ return new ChatMessage(role, messageResponseItem.Content.FirstOrDefault()?.Text);
+ }
+
+ throw new NotSupportedException("This test currently only supports text messages");
+ }
+
+ private async Task> GetChatHistoryFromConversationAsync(string conversationId)
+ {
+ List messages = [];
+ await foreach (AgentResponseItem item in this._client.GetProjectOpenAIClient().GetProjectConversationsClient().GetProjectConversationItemsAsync(conversationId, order: "asc"))
+ {
+ var openAIItem = item.AsResponseResultItem();
+ if (openAIItem is MessageResponseItem messageItem)
+ {
+ messages.Add(new ChatMessage
+ {
+ Role = new ChatRole(messageItem.Role.ToString()),
+ Contents = messageItem.Content
+ .Where(c => c.Kind is ResponseContentPartKind.OutputText or ResponseContentPartKind.InputText)
+ .Select(c => new TextContent(c.Text))
+ .ToList()
+ });
+ }
+ }
+
+ return messages;
+ }
+
+ public Task CreateChatClientAgentAsync(
+ string name = "HelpfulAssistant",
+ string instructions = "You are a helpful assistant.",
+ IList? aiTools = null)
+ {
+ return Task.FromResult(this._client.AsAIAgent(
+ model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName),
+ instructions: instructions,
+ name: name,
+ tools: aiTools).GetService()!);
+ }
+
+ public Task CreateChatClientAgentAsync(ChatClientAgentOptions options)
+ {
+ return Task.FromResult(this._client.AsAIAgent(options).GetService()!);
+ }
+
+ // Non-versioned Responses agents have no server-side agent to delete.
+ public Task DeleteAgentAsync(ChatClientAgent agent) => Task.CompletedTask;
+
+ public async Task DeleteSessionAsync(AgentSession session)
+ {
+ ChatClientAgentSession typedSession = (ChatClientAgentSession)session;
+
+ if (typedSession.ConversationId?.StartsWith("conv_", StringComparison.OrdinalIgnoreCase) == true)
+ {
+ await this._client.GetProjectOpenAIClient().GetProjectConversationsClient().DeleteConversationAsync(typedSession.ConversationId);
+ }
+ else if (typedSession.ConversationId?.StartsWith("resp_", StringComparison.OrdinalIgnoreCase) == true)
+ {
+ await this.DeleteResponseChainAsync(typedSession.ConversationId!);
+ }
+ }
+
+ private async Task DeleteResponseChainAsync(string lastResponseId)
+ {
+ var response = await this._client.GetProjectOpenAIClient().GetProjectResponsesClient().GetResponseAsync(lastResponseId);
+ await this._client.GetProjectOpenAIClient().GetProjectResponsesClient().DeleteResponseAsync(lastResponseId);
+
+ if (response.Value.PreviousResponseId is not null)
+ {
+ await this.DeleteResponseChainAsync(response.Value.PreviousResponseId);
+ }
+ }
+
+ // Non-versioned Responses agents have no server-side agent to clean up on dispose.
+ public ValueTask DisposeAsync()
+ {
+ GC.SuppressFinalize(this);
+ return default;
+ }
+
+ public virtual ValueTask InitializeAsync()
+ {
+ this._client = new AIProjectClient(
+ new Uri(TestConfiguration.GetRequiredValue(TestSettings.AzureAIProjectEndpoint)),
+ TestAzureCliCredentials.CreateAzureCliCredential());
+
+ this._agent = this._client.AsAIAgent(
+ model: TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName),
+ instructions: "You are a helpful assistant.",
+ name: "HelpfulAssistant");
+
+ return default;
+ }
+
+ public ValueTask InitializeAsync(ChatClientAgentOptions options)
+ {
+ this._client = new AIProjectClient(
+ new Uri(TestConfiguration.GetRequiredValue(TestSettings.AzureAIProjectEndpoint)),
+ TestAzureCliCredentials.CreateAzureCliCredential());
+
+ this._agent = this._client.AsAIAgent(options);
+
+ return default;
+ }
+}
diff --git a/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentRunStreamingTests.cs b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentRunStreamingTests.cs
new file mode 100644
index 0000000000..5f21c316c4
--- /dev/null
+++ b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentRunStreamingTests.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
+using Microsoft.Agents.AI;
+
+namespace AzureAI.IntegrationTests;
+
+public class ResponsesAgentRunStreamingPreviousResponseTests() : RunStreamingTests(() => new())
+{
+ public override Task RunWithNoMessageDoesNotFailAsync()
+ {
+ Assert.Skip("No messages is not supported");
+ return base.RunWithNoMessageDoesNotFailAsync();
+ }
+}
+
+public class ResponsesAgentRunStreamingConversationTests() : RunStreamingTests(() => new())
+{
+ public override Func> AgentRunOptionsFactory => async () =>
+ {
+ var conversationId = await this.Fixture.CreateConversationAsync();
+ return new ChatClientAgentRunOptions(new() { ConversationId = conversationId });
+ };
+
+ public override Task RunWithNoMessageDoesNotFailAsync()
+ {
+ Assert.Skip("No messages is not supported");
+ return base.RunWithNoMessageDoesNotFailAsync();
+ }
+}
diff --git a/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentRunTests.cs b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentRunTests.cs
new file mode 100644
index 0000000000..71460f7737
--- /dev/null
+++ b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentRunTests.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System;
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
+using Microsoft.Agents.AI;
+
+namespace AzureAI.IntegrationTests;
+
+public class ResponsesAgentRunPreviousResponseTests() : RunTests(() => new())
+{
+ public override Task RunWithNoMessageDoesNotFailAsync()
+ {
+ Assert.Skip("No messages is not supported");
+ return base.RunWithNoMessageDoesNotFailAsync();
+ }
+}
+
+public class ResponsesAgentRunConversationTests() : RunTests(() => new())
+{
+ public override Func> AgentRunOptionsFactory => async () =>
+ {
+ var conversationId = await this.Fixture.CreateConversationAsync();
+ return new ChatClientAgentRunOptions(new() { ConversationId = conversationId });
+ };
+
+ public override Task RunWithNoMessageDoesNotFailAsync()
+ {
+ Assert.Skip("No messages is not supported");
+ return base.RunWithNoMessageDoesNotFailAsync();
+ }
+}
diff --git a/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentStructuredOutputRunTests.cs b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentStructuredOutputRunTests.cs
new file mode 100644
index 0000000000..19ebdb4e28
--- /dev/null
+++ b/dotnet/tests/AzureAI.IntegrationTests/ResponsesAgentStructuredOutputRunTests.cs
@@ -0,0 +1,100 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Threading.Tasks;
+using AgentConformance.IntegrationTests;
+using AgentConformance.IntegrationTests.Support;
+using Microsoft.Agents.AI;
+using Microsoft.Extensions.AI;
+using Shared.IntegrationTests;
+
+namespace AzureAI.IntegrationTests;
+
+public class ResponsesAgentStructuredOutputRunTests() : StructuredOutputRunTests>(() => new())
+{
+ private const string NotSupported = "The direct Responses AsAIAgent path does not support specifying structured output type at invocation time.";
+
+ ///
+ /// Verifies that response format provided at agent initialization is used when invoking RunAsync.
+ ///
+ [RetryFact(Constants.RetryCount, Constants.RetryDelay)]
+ public async Task RunWithResponseFormatAtAgentInitializationReturnsExpectedResultAsync()
+ {
+ // Arrange
+ AIAgent agent = this.Fixture.Agent;
+ AgentSession session = await agent.CreateSessionAsync();
+ await using var cleanup = new SessionCleanup(session, this.Fixture);
+
+ // Act
+ AgentResponse response = await agent.RunAsync(new ChatMessage(ChatRole.User, "Provide information about the capital of France."), session);
+
+ // Assert
+ Assert.NotNull(response);
+ Assert.Single(response.Messages);
+ Assert.Contains("Paris", response.Text);
+ Assert.True(TryDeserialize(response.Text, AgentAbstractionsJsonUtilities.DefaultOptions, out CityInfo cityInfo));
+ Assert.Equal("Paris", cityInfo.Name);
+ }
+
+ ///
+ /// Verifies that generic RunAsync works when structured output is configured at agent initialization.
+ ///
+ [RetryFact(Constants.RetryCount, Constants.RetryDelay)]
+ public async Task RunGenericWithResponseFormatAtAgentInitializationReturnsExpectedResultAsync()
+ {
+ // Arrange
+ AIAgent agent = this.Fixture.Agent;
+ AgentSession session = await agent.CreateSessionAsync();
+ await using var cleanup = new SessionCleanup(session, this.Fixture);
+
+ // Act
+ AgentResponse response = await agent.RunAsync(
+ new ChatMessage(ChatRole.User, "Provide information about the capital of France."),
+ session);
+
+ // Assert
+ Assert.NotNull(response);
+ Assert.Single(response.Messages);
+ Assert.Contains("Paris", response.Text);
+
+ Assert.NotNull(response.Result);
+ Assert.Equal("Paris", response.Result.Name);
+ }
+
+ public override Task RunWithGenericTypeReturnsExpectedResultAsync()
+ {
+ Assert.Skip(NotSupported);
+ return base.RunWithGenericTypeReturnsExpectedResultAsync();
+ }
+
+ public override Task RunWithResponseFormatReturnsExpectedResultAsync()
+ {
+ Assert.Skip(NotSupported);
+ return base.RunWithResponseFormatReturnsExpectedResultAsync();
+ }
+
+ public override Task RunWithPrimitiveTypeReturnsExpectedResultAsync()
+ {
+ Assert.Skip(NotSupported);
+ return base.RunWithPrimitiveTypeReturnsExpectedResultAsync();
+ }
+}
+
+///
+/// Fixture for testing the direct Responses path with structured output of type provided at agent initialization.
+///
+public class ResponsesAgentStructuredOutputFixture : ResponsesAgentFixture
+{
+ public override ValueTask InitializeAsync()
+ {
+ ChatClientAgentOptions agentOptions = new()
+ {
+ ChatOptions = new ChatOptions()
+ {
+ ModelId = TestConfiguration.GetRequiredValue(TestSettings.AzureAIModelDeploymentName),
+ ResponseFormat = ChatResponseFormat.ForJsonSchema(AgentAbstractionsJsonUtilities.DefaultOptions)
+ },
+ };
+
+ return this.InitializeAsync(agentOptions);
+ }
+}
diff --git a/dotnet/tests/Microsoft.Agents.AI.AzureAI.UnitTests/AzureAIProjectChatClientExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.AzureAI.UnitTests/AzureAIProjectChatClientExtensionsTests.cs
index 261faaded8..5c954d30e8 100644
--- a/dotnet/tests/Microsoft.Agents.AI.AzureAI.UnitTests/AzureAIProjectChatClientExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.AzureAI.UnitTests/AzureAIProjectChatClientExtensionsTests.cs
@@ -21,11 +21,173 @@ using OpenAI.Responses;
namespace Microsoft.Agents.AI.AzureAI.UnitTests;
+#pragma warning disable CS0618
///
/// Unit tests for the class.
///
+[Obsolete("Includes coverage for obsolete AIProjectClient compatibility extension methods.")]
public sealed class AzureAIProjectChatClientExtensionsTests
{
+ #region AsAIAgent(AIProjectClient, model, instructions) Tests
+
+ ///
+ /// Verify that the non-versioned AsAIAgent overload throws ArgumentNullException when AIProjectClient is null.
+ ///
+ [Fact]
+ public void AsAIAgent_WithModelAndInstructions_WithNullClient_ThrowsArgumentNullException()
+ {
+ // Arrange
+ AIProjectClient? client = null;
+
+ // Act & Assert
+ ArgumentNullException exception = Assert.Throws(() =>
+ client!.AsAIAgent("gpt-4o-mini", "You are helpful."));
+
+ Assert.Equal("aiProjectClient", exception.ParamName);
+ }
+
+ ///
+ /// Verify that the non-versioned AsAIAgent overload creates a valid ChatClientAgent.
+ ///
+ [Fact]
+ public void AsAIAgent_WithModelAndInstructions_CreatesChatClientAgent()
+ {
+ // Arrange
+ AIProjectClient client = this.CreateTestAgentClient();
+ List tools =
+ [
+ AIFunctionFactory.Create(() => "test", "test_function", "A test function")
+ ];
+
+ // Act
+ FoundryAgent agent = client.AsAIAgent(
+ "gpt-4o-mini",
+ "You are helpful.",
+ name: "test-agent",
+ description: "A test agent",
+ tools: tools);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("test-agent", agent.Name);
+ Assert.Equal("A test agent", agent.Description);
+ Assert.Same(client, agent.GetService());
+ Assert.NotNull(agent.GetService());
+ }
+
+ ///
+ /// Verify that the non-versioned AsAIAgent overload applies the clientFactory.
+ ///
+ [Fact]
+ public void AsAIAgent_WithModelAndInstructions_WithClientFactory_AppliesFactoryCorrectly()
+ {
+ // Arrange
+ AIProjectClient client = this.CreateTestAgentClient();
+ TestChatClient? testChatClient = null;
+
+ // Act
+ FoundryAgent agent = client.AsAIAgent(
+ "gpt-4o-mini",
+ "You are helpful.",
+ clientFactory: innerClient => testChatClient = new TestChatClient(innerClient));
+
+ // Assert
+ Assert.NotNull(agent);
+ TestChatClient? retrievedTestClient = agent.GetService();
+ Assert.NotNull(retrievedTestClient);
+ Assert.Same(testChatClient, retrievedTestClient);
+ }
+
+ ///
+ /// Verify that the options-based non-versioned AsAIAgent overload creates a valid ChatClientAgent.
+ ///
+ [Fact]
+ public void AsAIAgent_WithOptions_CreatesChatClientAgent()
+ {
+ // Arrange
+ AIProjectClient client = this.CreateTestAgentClient();
+ ChatClientAgentOptions options = new()
+ {
+ Name = "options-agent",
+ Description = "Agent from options",
+ ChatOptions = new ChatOptions
+ {
+ ModelId = "gpt-4o-mini",
+ Instructions = "You are helpful.",
+ },
+ };
+
+ // Act
+ FoundryAgent agent = client.AsAIAgent(options);
+
+ // Assert
+ Assert.NotNull(agent);
+ Assert.Equal("options-agent", agent.Name);
+ Assert.Equal("Agent from options", agent.Description);
+ Assert.Same(client, agent.GetService());
+ }
+
+ ///
+ /// Verify that the non-versioned AsAIAgent overload adds the MEAI user-agent header to Responses API requests.
+ ///
+ [Fact]
+ public async Task AsAIAgent_WithModelAndInstructions_UserAgentHeaderAddedToResponsesRequestsAsync()
+ {
+ // Arrange
+ bool userAgentFound = false;
+ using HttpHandlerAssert httpHandler = new(request =>
+ {
+ if (request.Headers.TryGetValues("User-Agent", out IEnumerable? values))
+ {
+ foreach (string value in values)
+ {
+ if (value.Contains("MEAI"))
+ {
+ userAgentFound = true;
+ }
+ }
+ }
+
+ if (request.Method == HttpMethod.Post && request.RequestUri!.PathAndQuery.Contains("/responses"))
+ {
+ return new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent(
+ TestDataUtil.GetOpenAIDefaultResponseJson(),
+ Encoding.UTF8,
+ "application/json")
+ };
+ }
+
+ return new HttpResponseMessage(HttpStatusCode.OK)
+ {
+ Content = new StringContent("{}", Encoding.UTF8, "application/json")
+ };
+ });
+
+#pragma warning disable CA5399
+ using HttpClient httpClient = new(httpHandler);
+#pragma warning restore CA5399
+
+ AIProjectClient aiProjectClient = new(
+ new Uri("https://test.openai.azure.com/"),
+ new FakeAuthenticationTokenProvider(),
+ new() { Transport = new HttpClientPipelineTransport(httpClient) });
+
+ FoundryAgent agent = aiProjectClient.AsAIAgent(
+ "gpt-4o-mini",
+ "You are helpful.");
+
+ // Act
+ AgentSession session = await agent.CreateSessionAsync();
+ await agent.RunAsync("Hello", session);
+
+ // Assert
+ Assert.True(userAgentFound, "MEAI user-agent header was not found in any request");
+ }
+
+ #endregion
+
#region AsAIAgent(AIProjectClient, AgentRecord) Tests
///
@@ -199,7 +361,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -217,7 +379,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
#endregion
@@ -409,7 +571,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
var chatClient = agent.GetService();
Assert.NotNull(chatClient);
var agentVersion = chatClient.GetService();
@@ -458,7 +620,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -481,7 +643,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
Assert.Equal("test-agent", agent.Name);
- Assert.Equal("Test instructions", agent.Instructions);
+ Assert.Equal("Test instructions", agent.GetService()!.Instructions);
}
///
@@ -570,7 +732,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -592,7 +754,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -612,7 +774,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -638,7 +800,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
var agentVersion = agent.GetService();
Assert.NotNull(agentVersion);
if (agentVersion.Definition is PromptAgentDefinition promptDef)
@@ -677,7 +839,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
var agentVersion = agent.GetService();
Assert.NotNull(agentVersion);
if (agentVersion.Definition is PromptAgentDefinition promptDef)
@@ -721,7 +883,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
var agentVersion = agent.GetService();
Assert.NotNull(agentVersion);
Assert.IsType(agentVersion.Definition);
@@ -783,7 +945,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
var chatClient = agent.GetService();
Assert.NotNull(chatClient);
var agentVersion = chatClient.GetService();
@@ -815,7 +977,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
var agentVersion = agent.GetService();
Assert.NotNull(agentVersion);
if (agentVersion.Definition is PromptAgentDefinition promptDef)
@@ -843,7 +1005,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -864,7 +1026,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
#endregion
@@ -912,7 +1074,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
var agentVersion = agent.GetService();
Assert.NotNull(agentVersion);
if (agentVersion.Definition is PromptAgentDefinition promptDef)
@@ -952,7 +1114,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -979,7 +1141,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -1011,7 +1173,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
#endregion
@@ -1064,7 +1226,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
Assert.Equal("test-agent", agent.Name);
- Assert.Equal("Custom instructions", agent.Instructions);
+ Assert.Equal("Custom instructions", agent.GetService()!.Instructions);
Assert.Equal("Custom description", agent.Description);
}
@@ -1353,7 +1515,7 @@ public sealed class AzureAIProjectChatClientExtensionsTests
// Assert
Assert.NotNull(agent);
Assert.Equal(AgentName, agent.Name);
- Assert.Equal(Instructions, agent.Instructions);
+ Assert.Equal(Instructions, agent.GetService()!.Instructions);
var wrappedClient = agent.GetService();
Assert.NotNull(wrappedClient);
}
@@ -1957,11 +2119,11 @@ public sealed class AzureAIProjectChatClientExtensionsTests
};
// Act
- ChatClientAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
+ FoundryAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -1983,11 +2145,11 @@ public sealed class AzureAIProjectChatClientExtensionsTests
};
// Act
- ChatClientAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
+ FoundryAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -2011,11 +2173,11 @@ public sealed class AzureAIProjectChatClientExtensionsTests
};
// Act
- ChatClientAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
+ FoundryAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -2044,11 +2206,11 @@ public sealed class AzureAIProjectChatClientExtensionsTests
};
// Act
- ChatClientAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
+ FoundryAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType(agent);
}
///
@@ -2077,11 +2239,11 @@ public sealed class AzureAIProjectChatClientExtensionsTests
};
// Act
- ChatClientAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
+ FoundryAgent agent = await testClient.Client.CreateAIAgentAsync("test-model", options);
// Assert
Assert.NotNull(agent);
- Assert.IsType(agent);
+ Assert.IsType