From 4949bc6ba73db43865d13e11a398d7cbc8cb3bb6 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:31:18 +0000 Subject: [PATCH 1/5] .NET: Add Web Search sample #3674 --- .../FoundryAgents_Step25_WebSearch.csproj | 22 +++++ .../FoundryAgents_Step25_WebSearch/Program.cs | 85 +++++++++++++++++++ .../FoundryAgents_Step25_WebSearch/README.md | 52 ++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/FoundryAgents_Step25_WebSearch.csproj create mode 100644 dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs create mode 100644 dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/FoundryAgents_Step25_WebSearch.csproj b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/FoundryAgents_Step25_WebSearch.csproj new file mode 100644 index 0000000000..4a34560946 --- /dev/null +++ b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/FoundryAgents_Step25_WebSearch.csproj @@ -0,0 +1,22 @@ + + + + Exe + net10.0 + + enable + enable + $(NoWarn);CA1812 + + + + + + + + + + + + + diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs new file mode 100644 index 0000000000..cfdfa41015 --- /dev/null +++ b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample shows how to use Web Search Tool with AI Agents. + +using Azure.AI.Projects; +using Azure.AI.Projects.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.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 bingConnectionId = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_BING_CONNECTION_ID") ?? throw new InvalidOperationException("AZURE_FOUNDRY_BING_CONNECTION_ID is not set."); + +const string AgentInstructions = "You are a helpful assistant that can search the web to find current information and answer questions accurately."; +const string AgentNameMEAI = "WebSearchAgent-MEAI"; +const string AgentNameNative = "WebSearchAgent-NATIVE"; + +// Get a client to create/retrieve/delete server side agents with Azure Foundry Agents. +AIProjectClient aiProjectClient = new(new Uri(endpoint), new AzureCliCredential()); + +// Option 1 - Using HostedWebSearchTool + AgentOptions (MEAI + AgentFramework) +// Create the server side agent version with connection ID +Dictionary webSearchProperties = new() +{ + ["connectionId"] = bingConnectionId +}; +HostedWebSearchTool webSearchTool = new(webSearchProperties); + +AIAgent agentOption1 = await aiProjectClient.CreateAIAgentAsync( + model: deploymentName, + name: AgentNameMEAI, + instructions: AgentInstructions, + tools: [webSearchTool]); + +// 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.CreateWebSearchTool(), + } + }) +); + +// Either invoke option1 or option2 agent, should have same result +// Option 1 +AgentResponse response = await agentOption1.RunAsync("What's the weather today in Seattle?"); + +// Option 2 +// AgentResponse response = await agentOption2.RunAsync("What's the weather today in Seattle?"); + +// Get the text response +foreach (ChatMessage message in response.Messages) +{ + foreach (AIContent content in message.Contents) + { + if (content is TextContent textContent) + { + Console.WriteLine($"Response: {textContent.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(agentOption1.Name); +await aiProjectClient.Agents.DeleteAgentAsync(agentOption2.Name); diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md new file mode 100644 index 0000000000..09646300f1 --- /dev/null +++ b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md @@ -0,0 +1,52 @@ +# Using Web Search with AI Agents + +This sample demonstrates how to use the 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 +- Bing Grounding connection configured in your Azure Foundry project +- 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_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:AZURE_FOUNDRY_BING_CONNECTION_ID="your-bing-connection-id" # Your Bing Grounding connection ID +``` + +## Run the sample + +Navigate to the FoundryAgents sample directory and run: + +```powershell +cd dotnet/samples/GettingStarted/FoundryAgents +dotnet run --project .\FoundryAgents_Step25_WebSearch +``` + +## Expected behavior + +The sample will: + +1. Create two agents with web search capabilities: + - Option 1: Using HostedWebSearchTool (MEAI abstraction) + - Option 2: Using native SDK web search tools +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 both agents From ab64a2104dbee61deda0d0399a4d0fe22a71d167 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Wed, 18 Feb 2026 17:24:55 +0000 Subject: [PATCH 2/5] .NET: Fix WebSearch sample to use Responses API built-in web search Remove incorrect Bing Grounding connection ID requirement from the WebSearch sample. The web search tool uses the OpenAI Responses API built-in capability and does not need a connection ID. - Remove AZURE_FOUNDRY_BING_CONNECTION_ID env var requirement - Use HostedWebSearchTool() without connectionId properties - Refactor creation options into local functions (MEAI + NativeSDK) - Switch from AzureCliCredential to DefaultAzureCredential - Update README to reflect correct prerequisites Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../FoundryAgents_Step25_WebSearch.csproj | 2 +- .../FoundryAgents_Step25_WebSearch/Program.cs | 67 ++++++++----------- .../FoundryAgents_Step25_WebSearch/README.md | 16 ++--- 3 files changed, 37 insertions(+), 48 deletions(-) diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/FoundryAgents_Step25_WebSearch.csproj b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/FoundryAgents_Step25_WebSearch.csproj index 4a34560946..4d17fe06bb 100644 --- a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/FoundryAgents_Step25_WebSearch.csproj +++ b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/FoundryAgents_Step25_WebSearch.csproj @@ -6,7 +6,7 @@ enable enable - $(NoWarn);CA1812 + $(NoWarn);CA1812;CS8321 diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs index cfdfa41015..6111a09347 100644 --- a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs +++ b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs @@ -1,6 +1,6 @@ // Copyright (c) Microsoft. All rights reserved. -// This sample shows how to use Web Search Tool with AI Agents. +// This sample shows how to use the Responses API Web Search Tool with AI Agents. using Azure.AI.Projects; using Azure.AI.Projects.OpenAI; @@ -11,49 +11,20 @@ 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 bingConnectionId = Environment.GetEnvironmentVariable("AZURE_FOUNDRY_BING_CONNECTION_ID") ?? throw new InvalidOperationException("AZURE_FOUNDRY_BING_CONNECTION_ID is not set."); const string AgentInstructions = "You are a helpful assistant that can search the web to find current information and answer questions accurately."; -const string AgentNameMEAI = "WebSearchAgent-MEAI"; -const string AgentNameNative = "WebSearchAgent-NATIVE"; +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 AzureCliCredential()); +AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential()); -// Option 1 - Using HostedWebSearchTool + AgentOptions (MEAI + AgentFramework) -// Create the server side agent version with connection ID -Dictionary webSearchProperties = new() -{ - ["connectionId"] = bingConnectionId -}; -HostedWebSearchTool webSearchTool = new(webSearchProperties); - -AIAgent agentOption1 = await aiProjectClient.CreateAIAgentAsync( - model: deploymentName, - name: AgentNameMEAI, - instructions: AgentInstructions, - tools: [webSearchTool]); - -// 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.CreateWebSearchTool(), - } - }) -); +// Option 1 - Using HostedWebSearchTool (MEAI + AgentFramework) +AIAgent agent = await CreateAgentWithMEAIAsync(); -// Either invoke option1 or option2 agent, should have same result -// Option 1 -AgentResponse response = await agentOption1.RunAsync("What's the weather today in Seattle?"); +// Option 2 - Using PromptAgentDefinition with the Responses API native type +// AIAgent agent = await CreateAgentWithNativeSDKAsync(); -// Option 2 -// AgentResponse response = await agentOption2.RunAsync("What's the weather today in Seattle?"); +AgentResponse response = await agent.RunAsync("What's the weather today in Seattle?"); // Get the text response foreach (ChatMessage message in response.Messages) @@ -81,5 +52,23 @@ } // Cleanup by agent name removes the agent version created. -await aiProjectClient.Agents.DeleteAgentAsync(agentOption1.Name); -await aiProjectClient.Agents.DeleteAgentAsync(agentOption2.Name); +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/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md index 09646300f1..be51d5b01e 100644 --- a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md +++ b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md @@ -1,6 +1,6 @@ # Using Web Search with AI Agents -This sample demonstrates how to use the web search tool with AI agents. The web search tool allows agents to search the web for current information to answer questions accurately. +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 @@ -16,17 +16,17 @@ Before you begin, ensure you have the following prerequisites: - .NET 10 SDK or later - Azure Foundry service endpoint and deployment configured -- Bing Grounding connection configured in your Azure Foundry project - 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). +**Note**: This demo uses default Azure credentials for authentication. Make sure you're logged in with `az login` or have appropriate credentials configured. 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 -$env:AZURE_FOUNDRY_BING_CONNECTION_ID="your-bing-connection-id" # Your Bing Grounding connection ID ``` ## Run the sample @@ -42,11 +42,11 @@ dotnet run --project .\FoundryAgents_Step25_WebSearch The sample will: -1. Create two agents with web search capabilities: - - Option 1: Using HostedWebSearchTool (MEAI abstraction) - - Option 2: Using native SDK web search tools +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 both agents +6. Clean up resources by deleting the agent From e800d8a1a7e1112eb404dd2ed563fdc125226800 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+RogerBarreto@users.noreply.github.com> Date: Wed, 18 Feb 2026 17:50:43 +0000 Subject: [PATCH 3/5] Fix README to align DefaultAzureCredential docs with code Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../FoundryAgents/FoundryAgents_Step25_WebSearch/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md index be51d5b01e..95de275e8d 100644 --- a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md +++ b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/README.md @@ -16,9 +16,9 @@ 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) +- Azure authentication configured for `DefaultAzureCredential` (for example, Azure CLI logged in with `az login`, environment variables, managed identity, or IDE sign-in) -**Note**: This demo uses default Azure credentials for authentication. Make sure you're logged in with `az login` or have appropriate credentials configured. For more information, see the [Azure Identity documentation](https://learn.microsoft.com/dotnet/api/overview/azure/identity-readme). +**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. From 984b92eddedb56b221750075ebba7edf53b722dc Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Mon, 23 Feb 2026 15:52:01 +0000 Subject: [PATCH 4/5] Address review: add project to solution, README, simplify response text - Add FoundryAgents_Step25_WebSearch to agent-framework-dotnet.slnx - Add web search sample entry to parent FoundryAgents README.md - Simplify text response extraction to use response.Text directly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/agent-framework-dotnet.slnx | 1 + .../FoundryAgents_Step25_WebSearch/Program.cs | 11 +---------- dotnet/samples/GettingStarted/FoundryAgents/README.md | 1 + 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx index dfb8717c85..d835223def 100644 --- a/dotnet/agent-framework-dotnet.slnx +++ b/dotnet/agent-framework-dotnet.slnx @@ -176,6 +176,7 @@ + diff --git a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs index 6111a09347..77e5d5aeb7 100644 --- a/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs +++ b/dotnet/samples/GettingStarted/FoundryAgents/FoundryAgents_Step25_WebSearch/Program.cs @@ -27,16 +27,7 @@ AgentResponse response = await agent.RunAsync("What's the weather today in Seattle?"); // Get the text response -foreach (ChatMessage message in response.Messages) -{ - foreach (AIContent content in message.Contents) - { - if (content is TextContent textContent) - { - Console.WriteLine($"Response: {textContent.Text}"); - } - } -} +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 ?? [])) diff --git a/dotnet/samples/GettingStarted/FoundryAgents/README.md b/dotnet/samples/GettingStarted/FoundryAgents/README.md index 4b297105aa..96a62c3687 100644 --- a/dotnet/samples/GettingStarted/FoundryAgents/README.md +++ b/dotnet/samples/GettingStarted/FoundryAgents/README.md @@ -58,6 +58,7 @@ Before you begin, ensure you have the following prerequisites: |[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| +|[Web search](./FoundryAgents_Step25_WebSearch/)|This sample demonstrates how to use the Responses API web search tool with a Foundry agent| |[Local MCP](./FoundryAgents_Step27_LocalMCP/)|This sample demonstrates how to use a local MCP client with a Foundry agent| ## Evaluation Samples From cc544a0e5a35d01f62383bec3266aa987e769f93 Mon Sep 17 00:00:00 2001 From: Roger Barreto <19890735+rogerbarreto@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:12:58 +0000 Subject: [PATCH 5/5] Fix merge conflict in slnx solution file Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/agent-framework-dotnet.slnx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx index 6b7216f82d..2db09a8b98 100644 --- a/dotnet/agent-framework-dotnet.slnx +++ b/dotnet/agent-framework-dotnet.slnx @@ -181,13 +181,10 @@ -<<<<<<< feature/3674-web-search + + -======= - - ->>>>>>> main