Skip to content

Commit 86a1393

Browse files
authored
Update function-calling.md
Updating to have full version of sample
1 parent 2b3fc0a commit 86a1393

File tree

1 file changed

+131
-13
lines changed

1 file changed

+131
-13
lines changed

articles/ai-services/agents/how-to/tools/function-calling.md

Lines changed: 131 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,35 @@ Azure AI Agents supports function calling, which allows you to describe the stru
2828

2929
::: zone pivot="csharp"
3030

31-
## Define a function for your agent to call
31+
# Sample using agents with functions in Azure.AI.Agents
3232

33-
Start by defining a function for your agent to call. When you create a function for an agent to call, you describe its structure of it with any required parameters in a docstring.
33+
In this example we are demonstrating how to use the local functions with the agents. The functions can be used to provide agent specific information in response to user question.
34+
35+
1. First, set up the configuration and create a `PersistentAgentsClient`. This client will be used for all interactions with the Azure AI Agents Service. This step also includes all necessary `using` directives.
36+
37+
```C# Snippet:AgentsFunctions_Step1_SetupClient
38+
using Azure;
39+
using Azure.AI.Agents.Persistent;
40+
using Azure.Identity;
41+
using Microsoft.Extensions.Configuration;
42+
using System.Text.Json;
43+
44+
IConfigurationRoot configuration = new ConfigurationBuilder()
45+
.SetBasePath(AppContext.BaseDirectory)
46+
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
47+
.Build();
3448

35-
```csharp
49+
var projectEndpoint = configuration["ProjectEndpoint"];
50+
var modelDeploymentName = configuration["ModelDeploymentName"];
51+
PersistentAgentsClient client = new(projectEndpoint, new DefaultAzureCredential());
52+
```
53+
54+
2. Next, define the local functions that the agent can call. For each function, create a `FunctionToolDefinition` that describes its name, purpose, and parameters to the agent. These functions and definitions are used by both synchronous and asynchronous agent operations.
55+
56+
```C# Snippet:AgentsFunctions_Step2_DefineFunctionTools
3657
string GetUserFavoriteCity() => "Seattle, WA";
3758
FunctionToolDefinition getUserFavoriteCityTool = new("getUserFavoriteCity", "Gets the user's favorite city.");
59+
3860
string GetCityNickname(string location) => location switch
3961
{
4062
"Seattle, WA" => "The Emerald City",
@@ -58,6 +80,7 @@ FunctionToolDefinition getCityNicknameTool = new(
5880
Required = new[] { "location" },
5981
},
6082
new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }));
83+
6184
string GetWeatherAtLocation(string location, string temperatureUnit = "f") => location switch
6285
{
6386
"Seattle, WA" => temperatureUnit == "f" ? "70f" : "21c",
@@ -88,11 +111,9 @@ FunctionToolDefinition getCurrentWeatherAtLocationTool = new(
88111
new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }));
89112
```
90113

91-
<!--See the [C# file on GitHub](https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/ai/azure-ai-projects/samples/agents/user_functions.py) for an additional function definition examples. -->
114+
3. Create a helper function, `GetResolvedToolOutput`. This function takes a `RequiredToolCall` (when the agent determines a local function should be executed) and invokes the appropriate C# function defined in the previous step. It then wraps the result in a `ToolOutput` object for the agent.
92115

93-
In the following sample, we create a helper function to get and parse the resolved tools' outputs, and return it.
94-
95-
```csharp
116+
```C# Snippet:AgentsFunctions_Step3_GetResolvedToolOutput
96117
ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall)
97118
{
98119
if (toolCall is RequiredFunctionToolCall functionToolCall)
@@ -122,9 +143,23 @@ ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall)
122143
}
123144
```
124145

125-
## Create a client and agent
146+
4. Now, create the agent. Provide the model deployment name (retrieved in step 1), a descriptive name for the agent, instructions for its behavior, and the list of `FunctionToolDefinition`s (defined in step 2) it can use.
147+
148+
Synchronous sample:
149+
150+
```C# Snippet:AgentsFunctions_Step4_CreateAgent_Sync
151+
PersistentAgent agent = client.Administration.CreateAgent(
152+
model: modelDeploymentName,
153+
name: "SDK Test Agent - Functions",
154+
instructions: "You are a weather bot. Use the provided functions to help answer questions. "
155+
+ "Customize your responses to the user's preferences as much as possible and use friendly "
156+
+ "nicknames for cities whenever possible.",
157+
tools: [getUserFavoriteCityTool, getCityNicknameTool, getCurrentWeatherAtLocationTool]);
158+
```
159+
160+
Asynchronous sample:
126161

127-
```csharp
162+
```C# Snippet:AgentsFunctions_Step4_CreateAgent_Async
128163
PersistentAgent agent = await client.Administration.CreateAgentAsync(
129164
model: modelDeploymentName,
130165
name: "SDK Test Agent - Functions",
@@ -134,9 +169,22 @@ PersistentAgent agent = await client.Administration.CreateAgentAsync(
134169
tools: [getUserFavoriteCityTool, getCityNicknameTool, getCurrentWeatherAtLocationTool]);
135170
```
136171

137-
## Create a thread
172+
5. Create a new conversation thread and add an initial user message to it. The agent will respond to this message.
173+
174+
Synchronous sample:
175+
176+
```C# Snippet:AgentsFunctions_Step5_CreateThreadAndMessage_Sync
177+
PersistentAgentThread thread = client.Threads.CreateThread();
178+
179+
client.Messages.CreateMessage(
180+
thread.Id,
181+
MessageRole.User,
182+
"What's the weather like in my favorite city?");
183+
```
138184

139-
```csharp
185+
Asynchronous sample:
186+
187+
```C# Snippet:AgentsFunctions_Step5_CreateThreadAndMessage_Async
140188
PersistentAgentThread thread = await client.Threads.CreateThreadAsync();
141189

142190
await client.Messages.CreateMessageAsync(
@@ -145,9 +193,37 @@ await client.Messages.CreateMessageAsync(
145193
"What's the weather like in my favorite city?");
146194
```
147195

148-
## Create a run and check the output
196+
6. Create a run for the agent on the thread and poll for its completion. If the run requires action (e.g., a function call), submit the tool outputs.
197+
198+
Synchronous sample:
199+
200+
```C# Snippet:AgentsFunctions_Step6_CreateAndPollRun_Sync
201+
ThreadRun run = client.Runs.CreateRun(thread.Id, agent.Id);
202+
203+
do
204+
{
205+
Thread.Sleep(TimeSpan.FromMilliseconds(500));
206+
run = client.Runs.GetRun(thread.Id, run.Id);
207+
208+
if (run.Status == RunStatus.RequiresAction
209+
&& run.RequiredAction is SubmitToolOutputsAction submitToolOutputsAction)
210+
{
211+
List<ToolOutput> toolOutputs = [];
212+
foreach (RequiredToolCall toolCall in submitToolOutputsAction.ToolCalls)
213+
{
214+
toolOutputs.Add(GetResolvedToolOutput(toolCall));
215+
}
216+
run = client.Runs.SubmitToolOutputsToRun(run, toolOutputs);
217+
}
218+
}
219+
while (run.Status == RunStatus.Queued
220+
|| run.Status == RunStatus.InProgress
221+
|| run.Status == RunStatus.RequiresAction);
222+
```
223+
224+
Asynchronous sample:
149225

150-
```csharp
226+
```C# Snippet:AgentsFunctions_Step6_CreateAndPollRun_Async
151227
ThreadRun run = await client.Runs.CreateRunAsync(thread.Id, agent.Id);
152228

153229
do
@@ -173,7 +249,35 @@ do
173249
while (run.Status == RunStatus.Queued
174250
|| run.Status == RunStatus.InProgress
175251
|| run.Status == RunStatus.RequiresAction);
252+
```
253+
254+
7. After the run completes, retrieve and display the messages from the thread to see the conversation, including the agent's responses.
255+
256+
Synchronous sample:
257+
258+
```C# Snippet:AgentsFunctions_Step7_ProcessResults_Sync
259+
Pageable<ThreadMessage> messages = client.Messages.GetMessages(
260+
threadId: thread.Id,
261+
order: ListSortOrder.Ascending
262+
);
263+
264+
foreach (ThreadMessage threadMessage in messages)
265+
{
266+
foreach (MessageContent content in threadMessage.ContentItems)
267+
{
268+
switch (content)
269+
{
270+
case MessageTextContent textItem:
271+
Console.WriteLine($"[{threadMessage.Role}]: {textItem.Text}");
272+
break;
273+
}
274+
}
275+
}
276+
```
277+
278+
Asynchronous sample:
176279

280+
```C# Snippet:AgentsFunctions_Step7_ProcessResults_Async
177281
AsyncPageable<ThreadMessage> messages = client.Messages.GetMessagesAsync(
178282
threadId: thread.Id,
179283
order: ListSortOrder.Ascending
@@ -191,11 +295,25 @@ await foreach (ThreadMessage threadMessage in messages)
191295
}
192296
}
193297
}
298+
```
299+
300+
8. Finally, clean up the created resources by deleting the thread and the agent.
194301

302+
Synchronous sample:
303+
304+
```C# Snippet:AgentsFunctions_Step8_Cleanup_Sync
305+
client.Threads.DeleteThread(threadId: thread.Id);
306+
client.Administration.DeleteAgent(agentId: agent.Id);
307+
```
308+
309+
Asynchronous sample:
310+
311+
```C# Snippet:AgentsFunctions_Step8_Cleanup_Async
195312
await client.Threads.DeleteThreadAsync(threadId: thread.Id);
196313
await client.Administration.DeleteAgentAsync(agentId: agent.Id);
197314
```
198315

316+
199317
::: zone-end
200318

201319
::: zone pivot="javascript"

0 commit comments

Comments
 (0)