function-tools-approvals
Learn how to use function tools with human in the loop approvals
$ npx -y skills add managedcode/dotnet-skills --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
Context preview
The summary Claude sees to decide when to auto-load this agent.
Learn how to use function tools with human in the loop approvals
Agent definition
function-tools-approvals.mdtitle: Using function tools with human in the loop approvals
description: Learn how to use function tools with human in the loop approvals
zone_pivot_groups: programming-languages
author: westey-m
ms.topic: tutorial
ms.author: westey
ms.date: 09/15/2025
ms.service: agent-framework
Using function tools with human in the loop approvals
::: zone pivot="programming-language-csharp"
This tutorial step shows you how to use function tools that require human approval with an agent, where the agent is built on the Azure OpenAI Chat Completion service.
When agents require any user input, for example to approve a function call, this is referred to as a human-in-the-loop pattern. An agent run that requires user input, will complete with a response that indicates what input is required from the user, instead of completing with a final answer. The caller of the agent is then responsible for getting the required input from the user, and passing it back to the agent as part of a new agent run.
Prerequisites
For prerequisites and installing NuGet packages, see the [Create and run a simple agent](./run-agent.md) step in this tutorial.
Create the agent with function tools
When using functions, it's possible to indicate for each function, whether it requires human approval before being executed. This is done by wrapping the `AIFunction` instance in an `ApprovalRequiredAIFunction` instance.
Here is an example of a simple function tool that fakes getting the weather for a given location.
using System;
using System.ComponentModel;
using System.Linq;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;
[Description("Get the weather for a given location.")]
static string GetWeather([Description("The location to get the weather for.")] string location)
=> $"The weather in {location} is cloudy with a high of 15°C.";To create an `AIFunction` and then wrap it in an `ApprovalRequiredAIFunction`, you can do the following:
AIFunction weatherFunction = AIFunctionFactory.Create(GetWeather);
AIFunction approvalRequiredWeatherFunction = new ApprovalRequiredAIFunction(weatherFunction);
When creating the agent, you can now provide the approval requiring function tool to the agent, by passing a list of tools to the `AsAIAgent` method.
AIAgent agent = new AzureOpenAIClient(
new Uri("https://<myresource>.openai.azure.com"),
new AzureCliCredential())
.GetChatClient("gpt-4o-mini")
.AsAIAgent(instructions: "You are a helpful assistant", tools: [approvalRequiredWeatherFunction]);Since you now have a function that requires approval, the agent might respond with a request for approval, instead of executing the function directly and returning the result. You can check the response content for any `FunctionApprovalRequestContent` instances, which indicates that the agent requires user approval for a function.
AgentThread thread = await agent.GetNewThreadAsync();
AgentResponse response = await agent.RunAsync("What is the weather like in Amsterdam?", thread);
var functionApprovalRequests = response.Messages
.SelectMany(x => x.Contents)
.OfType<FunctionApprovalRequestContent>()
.ToList();If there are any function approval requests, the detail of the function call including name and arguments can be found in the `FunctionCall` property on the `FunctionApprovalRequestContent` instance. This can be shown to the user, so that they can decide whether to approve or reject the function call. For this example, assume there is one request.
FunctionApprovalRequestContent requestContent = functionApprovalRequests.First();
Console.WriteLine($"We require approval to execute '{requestContent.FunctionCall.Name}'");Once the user has provided their input, you can create a `FunctionApprovalResponseContent` instance using the `CreateResponse` method on the `FunctionApprovalRequestContent`. Pass `true` to approve the function call, or `false` to reject it.
The response content can then be passed to the agent in a new `User` `ChatMessage`, along with the same thread object to get the result back from the agent.
var approvalMessage = new ChatMessage(ChatRole.User, [requestContent.CreateResponse(true)]);
Console.WriteLine(await agent.RunAsync(approvalMessage, thread));
Whenever you are using function tools with human in the loop approvals, remember to check for `FunctionApprovalRequestContent` instances in the response, after each agent run, until all function calls have been approved or rejected.
::: zone-end ::: zone pivot="programming-language-python"
This tutorial step shows you how to use function tools that require human approval with an agent.
When agents require any user input, for example to approve a function call, this is referred to as a human-in-the-loop pattern. An agent run that requires user input, will complete with a response that indicates what input is required from the user, instead of completing with a final answer. The caller of the agent is then responsible for getting the required input from the user, and passing it back to the agent as part of a new agent run.
Prerequisites
For prerequisites and installing Python packages, see the [Create and run a simple agent](./run-agent.md) step in this tutorial.
Create the agent with function tools requiring approval
When using functions, it's possible to indicate for each function, whether it requires human approval before being executed. This is done by setting the `approval_mode` parameter to `"always_require"` when using the `@ai_function` decorator.
Here is an example of a simple function tool that fakes getting the weather for a given location.
from typing import Annotated
from agent_framework import ai_function
@ai_function
def get_weather(location: Annotated[str, "The city and state, e.g. San Francisco, CA"]) -> str:
"""Get the current weRead more
title: Using function tools with human in the loop approvals description: Learn how to use function tools with human in the loop approvals zone_pivot_groups: programming-languages author: westey-m ms.topic: tutorial ms.author: westey ms.date: 09/15/2025 ms.service: agent-framework
Using function tools with human in the loop approvals
::: zone pivot="programming-language-csharp"
This tutorial step shows you how to use function tools that require human approval with an agent, where the agent is built on the Azure OpenAI Chat Completion service.
When agents require any user input, for example to approve a function call, this is referred to as a human-in-the-loop pattern. An agent run that requires user input, will complete with a response that indicates what input is required from the user, instead of completing with a final answer. The caller of the agent is then responsible for getting the required input from the user, and passing it back to the agent as part of a new agent run.
Prerequisites
For prerequisites and installing NuGet packages, see the [Create and run a simple agent](./run-agent.md) step in this tutorial.
Create the agent with function tools
When using functions, it's possible to indicate for each function, whether it requires human approval before being executed. This is done by wrapping the `AIFunction` instance in an `ApprovalRequiredAIFunction` instance.
Here is an example of a simple function tool that fakes getting the weather for a given location.
using System;
using System.ComponentModel;
using System.Linq;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;
[Description("Get the weather for a given location.")]
static string GetWeather([Description("The location to get the weather for.")] string location)
=> $"The weather in {location} is cloudy with a high of 15°C.";To create an `AIFunction` and then wrap it in an `ApprovalRequiredAIFunction`, you can do the following:
AIFunction weatherFunction = AIFunctionFactory.Create(GetWeather); AIFunction approvalRequiredWeatherFunction = new ApprovalRequiredAIFunction(weatherFunction);
When creating the agent, you can now provide the approval requiring function tool to the agent, by passing a list of tools to the `AsAIAgent` method.
AIAgent agent = new AzureOpenAIClient(
new Uri("https://<myresource>.openai.azure.com"),
new AzureCliCredential())
.GetChatClient("gpt-4o-mini")
.AsAIAgent(instructions: "You are a helpful assistant", tools: [approvalRequiredWeatherFunction]);Since you now have a function that requires approval, the agent might respond with a request for approval, instead of executing the function directly and returning the result. You can check the response content for any `FunctionApprovalRequestContent` instances, which indicates that the agent requires user approval for a function.
AgentThread thread = await agent.GetNewThreadAsync();
AgentResponse response = await agent.RunAsync("What is the weather like in Amsterdam?", thread);
var functionApprovalRequests = response.Messages
.SelectMany(x => x.Contents)
.OfType<FunctionApprovalRequestContent>()
.ToList();If there are any function approval requests, the detail of the function call including name and arguments can be found in the `FunctionCall` property on the `FunctionApprovalRequestContent` instance. This can be shown to the user, so that they can decide whether to approve or reject the function call. For this example, assume there is one request.
FunctionApprovalRequestContent requestContent = functionApprovalRequests.First();
Console.WriteLine($"We require approval to execute '{requestContent.FunctionCall.Name}'");Once the user has provided their input, you can create a `FunctionApprovalResponseContent` instance using the `CreateResponse` method on the `FunctionApprovalRequestContent`. Pass `true` to approve the function call, or `false` to reject it.
The response content can then be passed to the agent in a new `User` `ChatMessage`, along with the same thread object to get the result back from the agent.
var approvalMessage = new ChatMessage(ChatRole.User, [requestContent.CreateResponse(true)]); Console.WriteLine(await agent.RunAsync(approvalMessage, thread));
Whenever you are using function tools with human in the loop approvals, remember to check for `FunctionApprovalRequestContent` instances in the response, after each agent run, until all function calls have been approved or rejected.
::: zone-end ::: zone pivot="programming-language-python"
This tutorial step shows you how to use function tools that require human approval with an agent.
When agents require any user input, for example to approve a function call, this is referred to as a human-in-the-loop pattern. An agent run that requires user input, will complete with a response that indicates what input is required from the user, instead of completing with a final answer. The caller of the agent is then responsible for getting the required input from the user, and passing it back to the agent as part of a new agent run.
Prerequisites
For prerequisites and installing Python packages, see the [Create and run a simple agent](./run-agent.md) step in this tutorial.
Create the agent with function tools requiring approval
When using functions, it's possible to indicate for each function, whether it requires human approval before being executed. This is done by setting the `approval_mode` parameter to `"always_require"` when using the `@ai_function` decorator.
Here is an example of a simple function tool that fakes getting the weather for a given location.
from typing import Annotated
from agent_framework import ai_function
@ai_function
def get_weather(location: Annotated[str, "The city and state, e.g. San Francisco, CA"]) -> str:
"""Get the current weStop explaining .NET to your AI. Start building. We've all been there: asking Claude to use Entity Framework, only to get EF6 patterns in a .NET 8 project. Explaining to Copilot that Blazor Server and Blazor WebAssembly aren't the same thing.
Repo: managedcode/dotnet-skills
Other agents on dotnet-skills.
- AGENT
Specialist orchestration agent for .NET Aspire work. Use when the problem is clearly about AppHost design, ServiceDefaults, first-party versus CommunityToolkit/Aspire integrations, dashboard and testing, `DistributedApplicationTestingBuilder`, `WebApplicationFactory`
Open agent - agent-as-function-tool
Legacy tutorial alias retained locally; the live Learn URL now resolves into the broader Function Tools surface
Open agent - agent-as-mcp-tool
Learn how to expose an agent as a tool over the MCP protocol
Open agent - create-and-run-durable-agent
Learn how to create and run a durable AI agent with Azure Functions and the durable task extension for Microsoft Agent Framework
Open agent - enable-observability
Enable OpenTelemetry for an agent so agent interactions are automatically logged
Open agent - function-tools
Learn how to use function tools with an agent
Open agent

