Skip to content

Commit 29eb241

Browse files
authored
Merge pull request #57 from petehauge/Latest-sdk-BingGrounding
Update the Bing Grounding sample to latest C# packages
2 parents 3b525ba + 061b3b6 commit 29eb241

File tree

4 files changed

+253
-42
lines changed

4 files changed

+253
-42
lines changed
Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ To enable your Agent to perform search through Bing search API, you use `BingGro
44
1. First we need to create an agent and read the environment variables, which will be used in the next steps.
55

66
```C# Snippet:AgentsBingGrounding_CreateProject
7-
8-
// Get Connection information from Environment Variables
9-
// To use App Config instead: https://learn.microsoft.com/en-us/visualstudio/ide/managing-application-settings-dotnet
10-
var projectEndpoint = System.Environment.GetEnvironmentVariable("PROJECT_ENDPOINT");
11-
var modelDeploymentName = System.Environment.GetEnvironmentVariable("MODEL_DEPLOYMENT_NAME");
12-
var connectionId = System.Environment.GetEnvironmentVariable("AZURE_BING_CONECTION_ID");
7+
// Get Connection information from App Configuration
8+
var projectEndpoint = configuration["ProjectEndpoint"];
9+
var modelDeploymentName = configuration["ModelDeploymentName"];
10+
var bingConnectionId = configuration["BingConnectionId"];
1311

1412
// Create the Agent Client
1513
PersistentAgentsClient agentClient = new(projectEndpoint, new DefaultAzureCredential());
@@ -18,53 +16,58 @@ PersistentAgentsClient agentClient = new(projectEndpoint, new DefaultAzureCreden
1816
2. We will use the Bing connection Id to initialize the `BingGroundingToolDefinition`.
1917

2018
```C# Snippet:AgentsBingGrounding_GetConnection
21-
ToolConnectionList connectionList = new()
22-
{
23-
ConnectionList = { new ToolConnection(bingConnectionId) }
24-
};
25-
BingGroundingToolDefinition bingGroundingTool = new(connectionList);
26-
```
19+
// Create the BingGroundingToolDefinition object used when creating the agent
20+
BingGroundingToolDefinition bingGroundingTool = new BingGroundingToolDefinition(
21+
new BingGroundingSearchConfigurationList(
22+
[
23+
new BingGroundingSearchConfiguration(bingConnectionId)
24+
]
25+
)
26+
);
2727

28+
```
2829
3. We will use the `BingGroundingToolDefinition` during the agent initialization.
2930

3031
Synchronous sample:
3132
```C# Snippet:AgentsBingGrounding_CreateAgent
3233
// Create the Agent
33-
PersistentAgent agent = agentClient.CreateAgent(
34-
model: modelDeploymentName,
35-
name: "my-agent",
36-
instructions: "You are a helpful agent.",
37-
tools: [bingGroundingTool]);
34+
PersistentAgent agent = agentClient.Administration.CreateAgent(
35+
model: modelDeploymentName,
36+
name: "my-agent",
37+
instructions: "You are a helpful agent.",
38+
tools: [bingGroundingTool]
39+
);
3840
```
3941

4042
Asynchronous sample:
4143
```C# Snippet:AgentsBingGroundingAsync_CreateAgent
4244
// Create the Agent
43-
PersistentAgent agent = await agentClient.CreateAgentAsync(
44-
model: modelDeploymentName,
45-
name: "my-agent",
46-
instructions: "You are a helpful agent.",
47-
tools: [ bingGroundingTool ]);
45+
PersistentAgent agent = await agentClient.Administration.CreateAgentAsync(
46+
model: modelDeploymentName,
47+
name: "my-agent",
48+
instructions: "You are a helpful agent.",
49+
tools: [bingGroundingTool]
50+
);
4851
```
4952

5053
4. Now we will create the thread, add the message containing a question for agent and start the run.
5154

5255
Synchronous sample:
5356
```C# Snippet:AgentsBingGrounding_CreateThreadMessage
54-
PersistentAgentThread thread = agentClient.CreateThread();
57+
PersistentAgentThread thread = agentClient.Threads.CreateThread();
5558

5659
// Create message and run the agent
57-
ThreadMessage message = agentClient.CreateMessage(
60+
ThreadMessage message = agentClient.Messages.CreateMessage(
5861
thread.Id,
5962
MessageRole.User,
6063
"How does wikipedia explain Euler's Identity?");
61-
ThreadRun run = agentClient.CreateRun(thread, agent);
64+
ThreadRun run = agentClient.Runs.CreateRun(thread, agent);
6265

6366
// Wait for the agent to finish running
6467
do
6568
{
6669
Thread.Sleep(TimeSpan.FromMilliseconds(500));
67-
run = agentClient.GetRun(thread.Id, run.Id);
70+
run = agentClient.Runs.GetRun(thread.Id, run.Id);
6871
}
6972
while (run.Status == RunStatus.Queued
7073
|| run.Status == RunStatus.InProgress);
@@ -79,20 +82,20 @@ if (run.Status != RunStatus.Completed)
7982

8083
Asynchronous sample:
8184
```C# Snippet:AgentsBingGroundingAsync_CreateThreadMessage
82-
PersistentAgentThread thread = await agentClient.CreateThreadAsync();
85+
PersistentAgentThread thread = await agentClient.Threads.CreateThreadAsync();
8386

8487
// Create message and run the agent
85-
ThreadMessage message = await agentClient.CreateMessageAsync(
88+
ThreadMessage message = await agentClient.Messages.CreateMessageAsync(
8689
thread.Id,
8790
MessageRole.User,
8891
"How does wikipedia explain Euler's Identity?");
89-
ThreadRun run = await agentClient.CreateRunAsync(thread, agent);
92+
ThreadRun run = await agentClient.Runs.CreateRunAsync(thread, agent);
9093

9194
// Wait for the agent to finish running
9295
do
9396
{
94-
await Task.Delay(TimeSpan.FromMilliseconds(500));
95-
run = await agentClient.GetRunAsync(thread.Id, run.Id);
97+
Thread.Sleep(TimeSpan.FromMilliseconds(500));
98+
run = await agentClient.Runs.GetRunAsync(thread.Id, run.Id);
9699
}
97100
while (run.Status == RunStatus.Queued
98101
|| run.Status == RunStatus.InProgress);
@@ -102,15 +105,14 @@ if (run.Status != RunStatus.Completed)
102105
{
103106
throw new Exception("Run did not complete successfully, error: " + run.LastError?.Message);
104107
}
105-
106108
```
107109

108110
5. Print the agent messages to console in chronological order (including formatting URL citations).
109111

110112
Synchronous sample:
111113
```C# Snippet:AgentsBingGrounding_Print
112114
// Retrieve all messages from the agent client
113-
PageableList<ThreadMessage> messages = agentClient.GetMessages(
115+
Pageable<ThreadMessage> messages = agentClient.Messages.GetMessages(
114116
threadId: thread.Id,
115117
order: ListSortOrder.Ascending
116118
);
@@ -149,15 +151,16 @@ foreach (ThreadMessage threadMessage in messages)
149151

150152
Asynchronous sample:
151153
```C# Snippet:AgentsBingGroundingAsync_Print
152-
PageableList<ThreadMessage> messages = await agentClient.GetMessagesAsync(
154+
// Retrieve all messages from the agent client
155+
AsyncPageable<ThreadMessage> messages = agentClient.Messages.GetMessagesAsync(
153156
threadId: thread.Id,
154157
order: ListSortOrder.Ascending
155158
);
156159

157-
foreach (ThreadMessage threadMessage in messages)
160+
// Process messages in order
161+
await foreach (ThreadMessage threadMessage in messages)
158162
{
159163
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
160-
161164
foreach (MessageContent contentItem in threadMessage.ContentItems)
162165
{
163166
if (contentItem is MessageTextContent textItem)
@@ -191,13 +194,13 @@ foreach (ThreadMessage threadMessage in messages)
191194
Synchronous sample:
192195
```C# Snippet:AgentsBingGrounding_Cleanup
193196
// Delete thread and agent
194-
agentClient.DeleteThread(threadId: thread.Id);
195-
agentClient.DeleteAgent(agentId: agent.Id);
197+
agentClient.Threads.DeleteThread(threadId: thread.Id);
198+
agentClient.Administration.DeleteAgent(agentId: agent.Id);
196199
```
197200

198201
Asynchronous sample:
199202
```C# Snippet:AgentsBingGroundingAsync_Cleanup
200203
// Delete thread and agent
201-
await agentClient.DeleteThreadAsync(threadId: thread.Id);
202-
await agentClient.DeleteAgentAsync(agentId: agent.Id);
204+
agentClient.Threads.DeleteThread(threadId: thread.Id);
205+
agentClient.Administration.DeleteAgent(agentId: agent.Id);
203206
```
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
using Azure;
2+
using Azure.AI.Agents.Persistent;
3+
using Azure.Identity;
4+
using Microsoft.Extensions.Configuration;
5+
using System;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
9+
// Get Connection information from App Configuration
10+
IConfigurationRoot configuration = new ConfigurationBuilder()
11+
.SetBasePath(AppContext.BaseDirectory)
12+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
13+
.Build();
14+
15+
var projectEndpoint = configuration["ProjectEndpoint"];
16+
var modelDeploymentName = configuration["ModelDeploymentName"];
17+
var bingConnectionId = configuration["BingConnectionId"];
18+
19+
// Create the Agent Client
20+
PersistentAgentsClient agentClient = new(projectEndpoint, new DefaultAzureCredential());
21+
22+
// Create the BingGroundingToolDefinition object used when creating the agent
23+
BingGroundingToolDefinition bingGroundingTool = new BingGroundingToolDefinition(
24+
new BingGroundingSearchConfigurationList(
25+
[
26+
new BingGroundingSearchConfiguration(bingConnectionId)
27+
]
28+
)
29+
);
30+
31+
// Create the Agent
32+
PersistentAgent agent = await agentClient.Administration.CreateAgentAsync(
33+
model: modelDeploymentName,
34+
name: "my-agent",
35+
instructions: "You are a helpful agent.",
36+
tools: [bingGroundingTool]
37+
);
38+
39+
PersistentAgentThread thread = await agentClient.Threads.CreateThreadAsync();
40+
41+
// Create message and run the agent
42+
ThreadMessage message = await agentClient.Messages.CreateMessageAsync(
43+
thread.Id,
44+
MessageRole.User,
45+
"How does wikipedia explain Euler's Identity?");
46+
ThreadRun run = await agentClient.Runs.CreateRunAsync(thread, agent);
47+
48+
// Wait for the agent to finish running
49+
do
50+
{
51+
Thread.Sleep(TimeSpan.FromMilliseconds(500));
52+
run = await agentClient.Runs.GetRunAsync(thread.Id, run.Id);
53+
}
54+
while (run.Status == RunStatus.Queued
55+
|| run.Status == RunStatus.InProgress);
56+
57+
// Confirm that the run completed successfully
58+
if (run.Status != RunStatus.Completed)
59+
{
60+
throw new Exception("Run did not complete successfully, error: " + run.LastError?.Message);
61+
}
62+
63+
// Retrieve all messages from the agent client
64+
AsyncPageable<ThreadMessage> messages = agentClient.Messages.GetMessagesAsync(
65+
threadId: thread.Id,
66+
order: ListSortOrder.Ascending
67+
);
68+
69+
// Process messages in order
70+
await foreach (ThreadMessage threadMessage in messages)
71+
{
72+
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
73+
foreach (MessageContent contentItem in threadMessage.ContentItems)
74+
{
75+
if (contentItem is MessageTextContent textItem)
76+
{
77+
string response = textItem.Text;
78+
79+
// If we have Text URL citation annotations, reformat the response to show title & URL for citations
80+
if (textItem.Annotations != null)
81+
{
82+
foreach (MessageTextAnnotation annotation in textItem.Annotations)
83+
{
84+
if (annotation is MessageTextUrlCitationAnnotation urlAnnotation)
85+
{
86+
response = response.Replace(urlAnnotation.Text, $" [{urlAnnotation.UrlCitation.Title}]({urlAnnotation.UrlCitation.Url})");
87+
}
88+
}
89+
}
90+
Console.Write($"Agent response: {response}");
91+
}
92+
else if (contentItem is MessageImageFileContent imageFileItem)
93+
{
94+
Console.Write($"<image from ID: {imageFileItem.FileId}");
95+
}
96+
Console.WriteLine();
97+
}
98+
}
99+
100+
// Delete thread and agent
101+
agentClient.Threads.DeleteThread(threadId: thread.Id);
102+
agentClient.Administration.DeleteAgent(agentId: agent.Id);
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using Azure;
2+
using Azure.AI.Agents.Persistent;
3+
using Azure.Identity;
4+
using Microsoft.Extensions.Configuration;
5+
using System;
6+
using System.Threading;
7+
8+
// Get Connection information from app configuration
9+
IConfigurationRoot configuration = new ConfigurationBuilder()
10+
.SetBasePath(AppContext.BaseDirectory)
11+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
12+
.Build();
13+
14+
var projectEndpoint = configuration["ProjectEndpoint"];
15+
var modelDeploymentName = configuration["ModelDeploymentName"];
16+
var bingConnectionId = configuration["BingConnectionId"];
17+
18+
// Create the Agent Client
19+
PersistentAgentsClient agentClient = new(
20+
projectEndpoint,
21+
new DefaultAzureCredential(),
22+
new PersistentAgentsAdministrationClientOptions(
23+
PersistentAgentsAdministrationClientOptions.ServiceVersion.V2025_05_01
24+
));
25+
26+
// Create the BingGroundingToolDefinition object used when creating the agent
27+
BingGroundingToolDefinition bingGroundingTool = new BingGroundingToolDefinition(
28+
new BingGroundingSearchConfigurationList(
29+
[
30+
new BingGroundingSearchConfiguration(bingConnectionId)
31+
]
32+
)
33+
);
34+
35+
// Create the Agent
36+
PersistentAgent agent = agentClient.Administration.CreateAgent(
37+
model: modelDeploymentName,
38+
name: "my-agent",
39+
instructions: "You are a helpful agent.",
40+
tools: [bingGroundingTool]
41+
);
42+
43+
PersistentAgentThread thread = agentClient.Threads.CreateThread();
44+
45+
// Create message and run the agent
46+
ThreadMessage message = agentClient.Messages.CreateMessage(
47+
thread.Id,
48+
MessageRole.User,
49+
"How does wikipedia explain Euler's Identity?");
50+
ThreadRun run = agentClient.Runs.CreateRun(thread, agent);
51+
52+
// Wait for the agent to finish running
53+
do
54+
{
55+
Thread.Sleep(TimeSpan.FromMilliseconds(500));
56+
run = agentClient.Runs.GetRun(thread.Id, run.Id);
57+
}
58+
while (run.Status == RunStatus.Queued
59+
|| run.Status == RunStatus.InProgress);
60+
61+
// Confirm that the run completed successfully
62+
if (run.Status != RunStatus.Completed)
63+
{
64+
throw new Exception("Run did not complete successfully, error: " + run.LastError?.Message);
65+
}
66+
67+
// Retrieve all messages from the agent client
68+
Pageable<ThreadMessage> messages = agentClient.Messages.GetMessages(
69+
threadId: thread.Id,
70+
order: ListSortOrder.Ascending
71+
);
72+
73+
// Process messages in order
74+
foreach (ThreadMessage threadMessage in messages)
75+
{
76+
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
77+
foreach (MessageContent contentItem in threadMessage.ContentItems)
78+
{
79+
if (contentItem is MessageTextContent textItem)
80+
{
81+
string response = textItem.Text;
82+
83+
// If we have Text URL citation annotations, reformat the response to show title & URL for citations
84+
if (textItem.Annotations != null)
85+
{
86+
foreach (MessageTextAnnotation annotation in textItem.Annotations)
87+
{
88+
if (annotation is MessageTextUrlCitationAnnotation urlAnnotation)
89+
{
90+
response = response.Replace(urlAnnotation.Text, $" [{urlAnnotation.UrlCitation.Title}]({urlAnnotation.UrlCitation.Url})");
91+
}
92+
}
93+
}
94+
Console.Write($"Agent response: {response}");
95+
}
96+
else if (contentItem is MessageImageFileContent imageFileItem)
97+
{
98+
Console.Write($"<image from ID: {imageFileItem.FileId}");
99+
}
100+
Console.WriteLine();
101+
}
102+
}
103+
104+
// Delete thread and agent
105+
agentClient.Threads.DeleteThread(threadId: thread.Id);
106+
agentClient.Administration.DeleteAgent(agentId: agent.Id);

samples/microsoft/csharp/getting-started-agents/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ This table tracks the current status of code samples for each supported tool in
1616
| Tool | Sample Description | Status | Notes / Known Issues |
1717
|--------------------|-----------------------------------------|-----------------|-----------------------------------------------|
1818
| **Basic Agent** | Using agent with no tools | ❌ Doesn't exist| |
19-
| **Bing** | Using Bing in an agent | ⚠️ Exists| Sample updated - works with project connection string, but not with project endpoint |
20-
| **File Search** | Uploading files | ⚠️ Exists| Sample updated - works with project connection string, but not with project endpoint |
19+
| **Bing** | Using Bing in an agent | ⚠️ Exists| Sample updated - get "Bing Search API key is missing" error |
20+
| **File Search** | Uploading files | ⚠️ Exists| Sample updated - get "Bing Search API key is missing" error |
2121
| | Using blob storage (project data assets)| ❌ Doesn't exist| |
2222
| | Managing files | ❌ Doesn't exist| |
2323
| **Azure AI Search**| Using a knowledge store | ❌ Doesn't exist| |

0 commit comments

Comments
 (0)