Skip to content

Commit 0d9059d

Browse files
authored
Merge pull request #70 from aryaan-singh/main
Add code sample for the Browser Automation Tool
2 parents ff50a70 + b56f234 commit 0d9059d

File tree

4 files changed

+503
-0
lines changed

4 files changed

+503
-0
lines changed
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Sample for using Azure Functions with agents in Azure.AI.Agents
2+
3+
## Prerequisites
4+
[Optional Step]
5+
In the appsettings.json, set a value for \"PlaywrightConnectionResourceId\" to ehe connection ID of the Serverless connection containing the details
6+
of the Playwright browser. If not provided, a MSFT managed playwright resource will be used.
7+
Format: <AI Project resource ID>/connections<Serverless connection name>
8+
- Creating a Microsoft Playwright Resource: https://learn.microsoft.com/en-us/azure/playwright-testing/how-to-manage-playwright-workspace?tabs=playwright
9+
- Give the Project Identity a "Contributor" role on the Playwright resource.
10+
- Generate an API Key for the Playwright resource: https://learn.microsoft.com/en-us/azure/playwright-testing/how-to-manage-access-tokens
11+
- Create a serverless connection in the Azure AI Foundry project with the Playwright endpoint and Access Key.
12+
13+
## Azure.AI.Agents Sample Code
14+
15+
1. First, we set up the necessary configuration, initialize the `PersistentAgentsClient`, define the tool definition for the Browser Automation tool, and then create the agent. This step includes all necessary `using` directives.
16+
17+
Common setup:
18+
19+
```C# Snippet:BrowserAutomationStep1CommonSetup
20+
using Azure;
21+
using Azure.Core;
22+
using Azure.AI.Agents.Persistent;
23+
using Azure.Identity;
24+
using Microsoft.Extensions.Configuration;
25+
using System.Text.Json;
26+
27+
IConfigurationRoot configuration = new ConfigurationBuilder()
28+
.SetBasePath(AppContext.BaseDirectory)
29+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
30+
.Build();
31+
32+
var projectEndpoint = configuration["ProjectEndpoint"];
33+
var modelDeploymentName = configuration["ModelDeploymentName"];
34+
var playwrightConnectionResourceId = configuration["PlaywrightConnectionResourceId"];
35+
PersistentAgentsClient client = new(projectEndpoint, new DefaultAzureCredential());
36+
37+
object browserAutomationToolDefinition = null;
38+
if (string.IsNullOrWhitespace(playwrightConnectionResourceId))
39+
{
40+
browserAutomationToolDefinition = new(
41+
type: "browser_automation",
42+
);
43+
}
44+
else
45+
{
46+
browserAutomationToolDefinition = new(
47+
type: "browser_automation",
48+
browser_automation: new(
49+
connection: new(
50+
id: playwrightConnectionResourceId,
51+
),
52+
),
53+
);
54+
}
55+
56+
object agentPayload = new(
57+
name: "Browser Automation Tool Demo Agent",
58+
description: "A simple agent that uses the browser automation tool.",
59+
model: modelDeploymentName,
60+
instructions: "You are an agent to help me with browser automation tasks. "
61+
+ "You can answer questions, provide information, and assist with various tasks "
62+
+ "related to web browsing using the browser_automation tool available to you.",
63+
tools: new[]
64+
{
65+
browserAutomationToolDefinition
66+
},
67+
);
68+
```
69+
70+
Synchronous sample:
71+
72+
```C# Snippet:BrowserAutomationStep1CreateAgentSync
73+
RequestContent agentRequestContent = RequestContent.Create(BinaryData.FromObjectAsJson(agentPayload));
74+
Response agentResponse = client.Administration.CreateAgent(content: agentRequestContent);
75+
PersistentAgent agent = PersistentAgent.FromResponse(agentResponse);
76+
```
77+
78+
Asynchronous sample:
79+
80+
```C# Snippet:BrowserAutomationStep1CreateAgentAsync
81+
RequestContent agentRequestContent = RequestContent.Create(BinaryData.FromObjectAsJson(agentPayload));
82+
Response agentResponse = await client.Administration.CreateAgentAsync(content: agentRequestContent);
83+
PersistentAgent agent = PersistentAgent.FromResponse(agentResponse);
84+
```
85+
86+
2. Next, we create a new persistent agent thread and add an initial user message to it.
87+
88+
Synchronous sample:
89+
90+
```C# Snippet:BrowserAutomationStep2CreateThreadMessageSync
91+
PersistentAgentThread thread = client.Threads.CreateThread();
92+
93+
client.Messages.CreateMessage(
94+
thread.Id,
95+
MessageRole.User,
96+
"Find a popular quinoa salad recipe on Allrecipes with more than 500 reviews and a rating above 4 stars. Create a shopping list of ingredients for this recipe and include the total cooking and preparation time. on https://www.allrecipes.com/"
97+
);
98+
```
99+
100+
Asynchronous sample:
101+
102+
```C# Snippet:BrowserAutomationStep2CreateThreadMessageAsync
103+
PersistentAgentThread thread = await client.Threads.CreateThreadAsync();
104+
105+
await client.Messages.CreateMessageAsync(
106+
thread.Id,
107+
MessageRole.User,
108+
"Find a popular quinoa salad recipe on Allrecipes with more than 500 reviews and a rating above 4 stars. Create a shopping list of ingredients for this recipe and include the total cooking and preparation time. on https://www.allrecipes.com/"
109+
);
110+
```
111+
112+
3. Then, we create a run for the agent on the thread and poll its status until it completes or requires action.
113+
114+
Synchronous sample:
115+
116+
```C# Snippet:BrowserAutomationStep3RunAndPollSync
117+
ThreadRun run = client.Runs.CreateRun(thread.Id, agent.Id);
118+
119+
do
120+
{
121+
Thread.Sleep(TimeSpan.FromMilliseconds(500));
122+
run = client.Runs.GetRun(thread.Id, run.Id);
123+
}
124+
while (run.Status == RunStatus.Queued
125+
|| run.Status == RunStatus.InProgress
126+
|| run.Status == RunStatus.RequiresAction);
127+
```
128+
129+
Asynchronous sample:
130+
131+
```C# Snippet:BrowserAutomationStep3RunAndPollAsync
132+
ThreadRun run = await client.Runs.CreateRunAsync(thread.Id, agent.Id);
133+
134+
do
135+
{
136+
await Task.Delay(TimeSpan.FromMilliseconds(500));
137+
run = await client.Runs.GetRunAsync(thread.Id, run.Id);
138+
}
139+
while (run.Status == RunStatus.Queued
140+
|| run.Status == RunStatus.InProgress
141+
|| run.Status == RunStatus.RequiresAction);
142+
```
143+
144+
4. After the run is complete, we retrieve and process the messages from the thread.
145+
146+
Synchronous sample:
147+
148+
```C# Snippet:BrowserAutomationStep4ProcessResultsSync
149+
Pageable<ThreadMessage> messages = client.Messages.GetMessages(
150+
threadId: thread.Id,
151+
order: ListSortOrder.Ascending
152+
);
153+
154+
foreach (ThreadMessage threadMessage in messages)
155+
{
156+
foreach (MessageContent content in threadMessage.ContentItems)
157+
{
158+
switch (content)
159+
{
160+
case MessageTextContent textItem:
161+
Console.WriteLine($"[{threadMessage.Role}]: {textItem.Text}");
162+
break;
163+
}
164+
}
165+
}
166+
```
167+
168+
Asynchronous sample:
169+
170+
```C# Snippet:BrowserAutomationStep4ProcessResultsAsync
171+
AsyncPageable<ThreadMessage> messages = client.Messages.GetMessagesAsync(
172+
threadId: thread.Id,
173+
order: ListSortOrder.Ascending
174+
);
175+
176+
await foreach (ThreadMessage threadMessage in messages)
177+
{
178+
foreach (MessageContent content in threadMessage.ContentItems)
179+
{
180+
switch (content)
181+
{
182+
case MessageTextContent textItem:
183+
Console.WriteLine($"[{threadMessage.Role}]: {textItem.Text}");
184+
break;
185+
}
186+
}
187+
}
188+
```
189+
190+
5. Finally, we clean up the created resources by deleting the thread and the agent.
191+
192+
Synchronous sample:
193+
194+
```C# Snippet:BrowserAutomationStep5CleanupSync
195+
client.Threads.DeleteThread(thread.Id);
196+
client.Administration.DeleteAgent(agent.Id);
197+
```
198+
199+
Asynchronous sample:
200+
201+
```C# Snippet:BrowserAutomationStep5CleanupAsync
202+
await client.Threads.DeleteThreadAsync(thread.Id);
203+
await client.Administration.DeleteAgentAsync(agent.Id);
204+
```
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using Azure;
2+
using Azure.Core;
3+
using Azure.AI.Agents.Persistent;
4+
using Azure.Identity;
5+
using Microsoft.Extensions.Configuration;
6+
using System.Text.Json;
7+
8+
IConfigurationRoot configuration = new ConfigurationBuilder()
9+
.SetBasePath(AppContext.BaseDirectory)
10+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
11+
.Build();
12+
13+
var projectEndpoint = configuration["ProjectEndpoint"];
14+
var modelDeploymentName = configuration["ModelDeploymentName"];
15+
var playwrightConnectionResourceId = configuration["PlaywrightConnectionResourceId"];
16+
PersistentAgentsClient client = new(projectEndpoint, new DefaultAzureCredential());
17+
18+
object browserAutomationToolDefinition = null;
19+
if (string.IsNullOrWhitespace(playwrightConnectionResourceId))
20+
{
21+
browserAutomationToolDefinition = new(
22+
type: "browser_automation",
23+
);
24+
}
25+
else
26+
{
27+
browserAutomationToolDefinition = new(
28+
type: "browser_automation",
29+
browser_automation: new(
30+
connection: new(
31+
id: playwrightConnectionResourceId,
32+
),
33+
),
34+
);
35+
}
36+
37+
object agentPayload = new(
38+
name: "Browser Automation Tool Demo Agent",
39+
description: "A simple agent that uses the browser automation tool.",
40+
model: modelDeploymentName,
41+
instructions: "You are an agent to help me with browser automation tasks. "
42+
+ "You can answer questions, provide information, and assist with various tasks "
43+
+ "related to web browsing using the browser_automation tool available to you.",
44+
tools: new[]
45+
{
46+
browserAutomationToolDefinition
47+
},
48+
);
49+
50+
RequestContent agentRequestContent = RequestContent.Create(BinaryData.FromObjectAsJson(agentPayload));
51+
Response agentResponse = await client.Administration.CreateAgentAsync(content: agentRequestContent);
52+
PersistentAgent agent = PersistentAgent.FromResponse(agentResponse);
53+
54+
PersistentAgentThread thread = await client.Threads.CreateThreadAsync();
55+
56+
await client.Messages.CreateMessageAsync(
57+
thread.Id,
58+
MessageRole.User,
59+
"Find a popular quinoa salad recipe on Allrecipes with more than 500 reviews and a rating above 4 stars. Create a shopping list of ingredients for this recipe and include the total cooking and preparation time. on https://www.allrecipes.com/"
60+
);
61+
62+
ThreadRun run = await client.Runs.CreateRunAsync(thread.Id, agent.Id);
63+
64+
do
65+
{
66+
await Task.Delay(TimeSpan.FromMilliseconds(500));
67+
run = await client.Runs.GetRunAsync(thread.Id, run.Id);
68+
}
69+
while (run.Status == RunStatus.Queued
70+
|| run.Status == RunStatus.InProgress
71+
|| run.Status == RunStatus.RequiresAction);
72+
73+
AsyncPageable<ThreadMessage> messages = client.Messages.GetMessagesAsync(
74+
threadId: thread.Id,
75+
order: ListSortOrder.Ascending
76+
);
77+
78+
await foreach (ThreadMessage threadMessage in messages)
79+
{
80+
foreach (MessageContent content in threadMessage.ContentItems)
81+
{
82+
switch (content)
83+
{
84+
case MessageTextContent textItem:
85+
Console.WriteLine($"[{threadMessage.Role}]: {textItem.Text}");
86+
break;
87+
}
88+
}
89+
}
90+
91+
await client.Threads.DeleteThreadAsync(thread.Id);
92+
await client.Administration.DeleteAgentAsync(agent.Id);
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using Azure;
2+
using Azure.Core;
3+
using Azure.AI.Agents.Persistent;
4+
using Azure.Identity;
5+
using Microsoft.Extensions.Configuration;
6+
using System.Text.Json;
7+
8+
IConfigurationRoot configuration = new ConfigurationBuilder()
9+
.SetBasePath(AppContext.BaseDirectory)
10+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
11+
.Build();
12+
13+
var projectEndpoint = configuration["ProjectEndpoint"];
14+
var modelDeploymentName = configuration["ModelDeploymentName"];
15+
var playwrightConnectionResourceId = configuration["PlaywrightConnectionResourceId"];
16+
PersistentAgentsClient client = new(projectEndpoint, new DefaultAzureCredential());
17+
18+
object browserAutomationToolDefinition = null;
19+
if (string.IsNullOrWhitespace(playwrightConnectionResourceId))
20+
{
21+
browserAutomationToolDefinition = new(
22+
type: "browser_automation",
23+
);
24+
}
25+
else
26+
{
27+
browserAutomationToolDefinition = new(
28+
type: "browser_automation",
29+
browser_automation: new(
30+
connection: new(
31+
id: playwrightConnectionResourceId,
32+
),
33+
),
34+
);
35+
}
36+
37+
object agentPayload = new(
38+
name: "Browser Automation Tool Demo Agent",
39+
description: "A simple agent that uses the browser automation tool.",
40+
model: modelDeploymentName,
41+
instructions: "You are an agent to help me with browser automation tasks. "
42+
+ "You can answer questions, provide information, and assist with various tasks "
43+
+ "related to web browsing using the browser_automation tool available to you.",
44+
tools: new[]
45+
{
46+
browserAutomationToolDefinition
47+
},
48+
);
49+
50+
RequestContent agentRequestContent = RequestContent.Create(BinaryData.FromObjectAsJson(agentPayload));
51+
Response agentResponse = client.Administration.CreateAgent(content: agentRequestContent);
52+
PersistentAgent agent = PersistentAgent.FromResponse(agentResponse);
53+
54+
PersistentAgentThread thread = client.Threads.CreateThread();
55+
56+
client.Messages.CreateMessage(
57+
thread.Id,
58+
MessageRole.User,
59+
"Find a popular quinoa salad recipe on Allrecipes with more than 500 reviews and a rating above 4 stars. Create a shopping list of ingredients for this recipe and include the total cooking and preparation time. on https://www.allrecipes.com/"
60+
);
61+
62+
ThreadRun run = client.Runs.CreateRun(thread.Id, agent.Id);
63+
64+
do
65+
{
66+
Thread.Sleep(TimeSpan.FromMilliseconds(500));
67+
run = client.Runs.GetRun(thread.Id, run.Id);
68+
}
69+
while (run.Status == RunStatus.Queued
70+
|| run.Status == RunStatus.InProgress
71+
|| run.Status == RunStatus.RequiresAction);
72+
73+
Pageable<ThreadMessage> messages = client.Messages.GetMessages(
74+
threadId: thread.Id,
75+
order: ListSortOrder.Ascending
76+
);
77+
78+
foreach (ThreadMessage threadMessage in messages)
79+
{
80+
foreach (MessageContent content in threadMessage.ContentItems)
81+
{
82+
switch (content)
83+
{
84+
case MessageTextContent textItem:
85+
Console.WriteLine($"[{threadMessage.Role}]: {textItem.Text}");
86+
break;
87+
}
88+
}
89+
}
90+
91+
client.Threads.DeleteThread(thread.Id);
92+
client.Administration.DeleteAgent(agent.Id);

0 commit comments

Comments
 (0)