@@ -28,13 +28,35 @@ Azure AI Agents supports function calling, which allows you to describe the stru
28
28
29
29
::: zone pivot="csharp"
30
30
31
- ## Define a function for your agent to call
31
+ # Sample using agents with functions in Azure.AI.Agents
32
32
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 ();
34
48
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
36
57
string GetUserFavoriteCity () => " Seattle, WA" ;
37
58
FunctionToolDefinition getUserFavoriteCityTool = new (" getUserFavoriteCity" , " Gets the user's favorite city." );
59
+
38
60
string GetCityNickname (string location ) => location switch
39
61
{
40
62
" Seattle, WA" => " The Emerald City" ,
@@ -58,6 +80,7 @@ FunctionToolDefinition getCityNicknameTool = new(
58
80
Required = new [] { " location" },
59
81
},
60
82
new JsonSerializerOptions () { PropertyNamingPolicy = JsonNamingPolicy .CamelCase }));
83
+
61
84
string GetWeatherAtLocation (string location , string temperatureUnit = " f" ) => location switch
62
85
{
63
86
" Seattle, WA" => temperatureUnit == " f" ? " 70f" : " 21c" ,
@@ -88,11 +111,9 @@ FunctionToolDefinition getCurrentWeatherAtLocationTool = new(
88
111
new JsonSerializerOptions () { PropertyNamingPolicy = JsonNamingPolicy .CamelCase }));
89
112
```
90
113
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.
92
115
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
96
117
ToolOutput GetResolvedToolOutput (RequiredToolCall toolCall )
97
118
{
98
119
if (toolCall is RequiredFunctionToolCall functionToolCall )
@@ -122,9 +143,23 @@ ToolOutput GetResolvedToolOutput(RequiredToolCall toolCall)
122
143
}
123
144
```
124
145
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 :
126
161
127
- ```csharp
162
+ ```C # Snippet : AgentsFunctions_Step4_CreateAgent_Async
128
163
PersistentAgent agent = await client .Administration .CreateAgentAsync (
129
164
model : modelDeploymentName ,
130
165
name : " SDK Test Agent - Functions" ,
@@ -134,9 +169,22 @@ PersistentAgent agent = await client.Administration.CreateAgentAsync(
134
169
tools : [getUserFavoriteCityTool , getCityNicknameTool , getCurrentWeatherAtLocationTool ]);
135
170
```
136
171
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
+ ```
138
184
139
- ```csharp
185
+ Asynchronous sample :
186
+
187
+ ```C # Snippet :AgentsFunctions_Step5_CreateThreadAndMessage_Async
140
188
PersistentAgentThread thread = await client .Threads .CreateThreadAsync ();
141
189
142
190
await client .Messages .CreateMessageAsync (
@@ -145,9 +193,37 @@ await client.Messages.CreateMessageAsync(
145
193
" What's the weather like in my favorite city?" );
146
194
```
147
195
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 :
149
225
150
- ```csharp
226
+ ```C # Snippet : AgentsFunctions_Step6_CreateAndPollRun_Async
151
227
ThreadRun run = await client .Runs .CreateRunAsync (thread .Id , agent .Id );
152
228
153
229
do
173
249
while (run .Status == RunStatus .Queued
174
250
|| run .Status == RunStatus .InProgress
175
251
|| 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 :
176
279
280
+ ```C # Snippet :AgentsFunctions_Step7_ProcessResults_Async
177
281
AsyncPageable <ThreadMessage > messages = client .Messages .GetMessagesAsync (
178
282
threadId : thread .Id ,
179
283
order : ListSortOrder .Ascending
@@ -191,11 +295,25 @@ await foreach (ThreadMessage threadMessage in messages)
191
295
}
192
296
}
193
297
}
298
+ ```
299
+
300
+ 8. Finally , clean up the created resources by deleting the thread and the agent .
194
301
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
195
312
await client .Threads .DeleteThreadAsync (threadId : thread .Id );
196
313
await client .Administration .DeleteAgentAsync (agentId : agent .Id );
197
314
```
198
315
316
+
199
317
::: zone -end
200
318
201
319
::: zone pivot =" javascript"
0 commit comments