Skip to content

Commit 7a39753

Browse files
authored
Update openapi-spec-samples.md
OpenAPI Tool usage sample.
1 parent 9315c8b commit 7a39753

File tree

1 file changed

+123
-84
lines changed

1 file changed

+123
-84
lines changed

articles/ai-services/agents/how-to/tools/openapi-spec-samples.md

Lines changed: 123 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -44,115 +44,154 @@ Use this article to find step-by-step instructions and code samples for using Op
4444

4545
:::zone pivot="csharp"
4646

47-
## Step 1: Create a project client
48-
Create a client object, which will contain the connection string for connecting to your AI project and other resources.
47+
# How to use the OpenAPI spec tool
4948

50-
```csharp
51-
using System;
52-
using System.Collections.Generic;
53-
using System.IO;
54-
using System.Runtime.CompilerServices;
55-
using System.Text.Json.Serialization;
56-
using System.Text.Json;
57-
using System.Threading.Tasks;
58-
using Azure.Core.TestFramework;
59-
using NUnit.Framework;
60-
using Newtonsoft.Json.Linq;
61-
62-
namespace Azure.AI.Projects.Tests;
63-
64-
public partial class Sample_Agent_OpenAPI : SamplesBase<AIProjectsTestEnvironment>
65-
{
66-
private static string GetFile([CallerFilePath] string pth = "")
67-
{
68-
var dirName = Path.GetDirectoryName(pth) ?? "";
69-
return Path.Combine(dirName, "weather_openapi.json");
70-
}
49+
In this example we will demonstrate the possibility to use services with [OpenAPI Specification](https://en.wikipedia.org/wiki/OpenAPI_Specification) with the agent. We will use [wttr.in](https://wttr.in) service to get weather and its specification file [weather_openapi.json](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/ai/Azure.AI.Projects/tests/Samples/Agent/weather_openapi.json).
7150

72-
[Test]
73-
public async Task OpenAPICallingExample()
74-
{
75-
var connectionString = TestEnvironment.AzureAICONNECTIONSTRING;
76-
var storageQueueUri = TestEnvironment.STORAGE_QUEUE_URI;
77-
AgentsClient client = new(connectionString, new DefaultAzureCredential());
78-
var file_path = GetFile();
51+
1. First get `ProjectEndpoint` and `ModelDeploymentName` from config and create a `PersistentAgentsClient`. Also, create an `OpenApiAnonymousAuthDetails` and `OpenApiToolDefinition` from config.
52+
53+
```csharp
54+
var projectEndpoint = configuration["ProjectEndpoint"];
55+
var modelDeploymentName = configuration["ModelDeploymentName"];
56+
var openApiSpec = configuration["OpenApiSpec"];
57+
PersistentAgentsClient client = new(new Uri(projectEndpoint), new DefaultAzureCredential());
58+
59+
var spec = BinaryData.FromBytes(File.ReadAllBytes(openApiSpec));
60+
OpenApiAnonymousAuthDetails openApiAnonAuth = new();
61+
OpenApiToolDefinition openApiTool = new(
62+
name: "get_weather",
63+
description: "Retrieve weather information for a location",
64+
spec: spec,
65+
auth: openApiAnonAuth,
66+
defaultParams: ["format"]
67+
);
7968
```
8069

70+
2. Next we will need to create an agent.
8171

82-
## Step 2: Create the OpenAPI Spec tool definition
83-
You might want to store the OpenAPI specification in another file and import the content to initialize the tool. The sample code is using `anonymous` as the authentication type.
72+
Synchronous sample:
8473

8574
```csharp
86-
OpenApiAnonymousAuthDetails oaiAuth = new();
87-
OpenApiToolDefinition openapiTool = new(
88-
name: "get_weather",
89-
description: "Retrieve weather information for a location",
90-
spec: BinaryData.FromBytes(File.ReadAllBytes(file_path)),
91-
auth: oaiAuth
92-
);
75+
PersistentAgent agent = client.CreateAgent(
76+
model: modelDeploymentName,
77+
name: "Open API Tool Calling Agent",
78+
instructions: "You are a helpful agent.",
79+
tools: [openApiTool]
80+
);
9381
```
9482

95-
## Step 3: Create an agent and a thread
83+
Asynchronous sample:
9684

9785
```csharp
98-
Response<Agent> agentResponse = await client.CreateAgentAsync(
99-
model: "gpt-4o",
100-
name: "azure-function-agent-foo",
101-
instructions: "You are a helpful assistant.",
102-
tools: new List<ToolDefinition> { openapiTool }
103-
);
104-
Agent agent = agentResponse.Value;
105-
#endregion
106-
Response<AgentThread> threadResponse = await client.CreateThreadAsync();
107-
AgentThread thread = threadResponse.Value;
86+
PersistentAgent agent = await client.CreateAgentAsync(
87+
model: modelDeploymentName,
88+
name: "Open API Tool Calling Agent",
89+
instructions: "You are a helpful agent.",
90+
tools: [openApiTool]
91+
);
10892
```
10993

94+
3. Now we will create a `ThreadRun` and wait until it is complete. If the run will not be successful, we will print the last error.
11095

111-
## Step 4: Create a run and check the output
112-
Create a run and observe that the model uses the OpenAPI Spec tool to provide a response to the user's question.
96+
Synchronous sample:
97+
```csharp
98+
PersistentAgentThread thread = client.CreateThread();
99+
ThreadMessage message = client.CreateMessage(
100+
thread.Id,
101+
MessageRole.User,
102+
"What's the weather in Seattle?");
103+
104+
ThreadRun run = client.CreateRun(thread, agent);
105+
106+
do
107+
{
108+
Thread.Sleep(TimeSpan.FromMilliseconds(500));
109+
run = client.GetRun(thread.Id, run.Id);
110+
}
111+
while (run.Status == RunStatus.Queued
112+
|| run.Status == RunStatus.InProgress
113+
|| run.Status == RunStatus.RequiresAction);
114+
```
113115

116+
Asynchronous sample:
114117

115118
```csharp
116-
#region Snippet:OpenAPIHandlePollingWithRequiredAction
117-
Response<ThreadMessage> messageResponse = await client.CreateMessageAsync(
118-
thread.Id,
119-
MessageRole.User,
120-
"What's the weather in Seattle?");
121-
ThreadMessage message = messageResponse.Value;
119+
PersistentAgentThread thread = await client.CreateThreadAsync();
120+
ThreadMessage message = await client.CreateMessageAsync(
121+
thread.Id,
122+
MessageRole.User,
123+
"What's the weather in Seattle?");
124+
125+
ThreadRun run = await client.CreateRunAsync(thread, agent);
126+
127+
do
128+
{
129+
await Task.Delay(TimeSpan.FromMilliseconds(500));
130+
run = await client.GetRunAsync(thread.Id, run.Id);
131+
}
132+
while (run.Status == RunStatus.Queued
133+
|| run.Status == RunStatus.InProgress
134+
|| run.Status == RunStatus.RequiresAction);
135+
```
122136

123-
Response<ThreadRun> runResponse = await client.CreateRunAsync(thread, agent);
137+
4. Print the messages to the console in chronological order.
124138

125-
do
139+
Synchronous sample:
140+
141+
```csharp
142+
PageableList<ThreadMessage> messages = client.GetMessages(
143+
threadId: thread.Id,
144+
order: ListSortOrder.Ascending
145+
);
146+
147+
foreach (ThreadMessage threadMessage in messages)
148+
{
149+
foreach (MessageContent contentItem in threadMessage.ContentItems)
150+
{
151+
if (contentItem is MessageTextContent textItem)
126152
{
127-
await Task.Delay(TimeSpan.FromMilliseconds(500));
128-
runResponse = await client.GetRunAsync(thread.Id, runResponse.Value.Id);
153+
Console.Write($"{threadMessage.Role}: {textItem.Text}");
129154
}
130-
while (runResponse.Value.Status == RunStatus.Queued
131-
|| runResponse.Value.Status == RunStatus.InProgress
132-
|| runResponse.Value.Status == RunStatus.RequiresAction);
133-
#endregion
155+
Console.WriteLine();
156+
}
157+
}
158+
```
159+
160+
Asynchronous sample:
134161

135-
Response<PageableList<ThreadMessage>> afterRunMessagesResponse
136-
= await client.GetMessagesAsync(thread.Id);
137-
IReadOnlyList<ThreadMessage> messages = afterRunMessagesResponse.Value.Data;
162+
```csharp
163+
PageableList<ThreadMessage> messages = await client.GetMessagesAsync(
164+
threadId: thread.Id,
165+
order: ListSortOrder.Ascending
166+
);
138167

139-
// Note: messages iterate from newest to oldest, with the messages[0] being the most recent
140-
foreach (ThreadMessage threadMessage in messages)
168+
foreach (ThreadMessage threadMessage in messages)
169+
{
170+
foreach (MessageContent contentItem in threadMessage.ContentItems)
171+
{
172+
if (contentItem is MessageTextContent textItem)
141173
{
142-
Console.Write($"{threadMessage.CreatedAt:yyyy-MM-dd HH:mm:ss} - {threadMessage.Role,10}: ");
143-
foreach (MessageContent contentItem in threadMessage.ContentItems)
144-
{
145-
if (contentItem is MessageTextContent textItem)
146-
{
147-
Console.Write(textItem.Text);
148-
}
149-
else if (contentItem is MessageImageFileContent imageFileItem)
150-
{
151-
Console.Write($"<image from ID: {imageFileItem.FileId}");
152-
}
153-
Console.WriteLine();
154-
}
174+
Console.Write($"{threadMessage.Role}: {textItem.Text}");
155175
}
176+
Console.WriteLine();
177+
}
178+
}
179+
```
180+
181+
5. Finally, we delete all the resources, we have created in this sample.
182+
183+
Synchronous sample:
184+
185+
```csharp
186+
client.DeleteThread(thread.Id);
187+
client.DeleteAgent(agent.Id);
188+
```
189+
190+
Asynchronous sample:
191+
192+
```csharp
193+
await client.DeleteThreadAsync(thread.Id);
194+
await client.DeleteAgentAsync(agent.Id);
156195
```
157196

158197
:::zone-end

0 commit comments

Comments
 (0)