AzureAICommunity.Agent.Middleware.ApprovalMiddleware 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package AzureAICommunity.Agent.Middleware.ApprovalMiddleware --version 1.0.0
                    
NuGet\Install-Package AzureAICommunity.Agent.Middleware.ApprovalMiddleware -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="AzureAICommunity.Agent.Middleware.ApprovalMiddleware" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="AzureAICommunity.Agent.Middleware.ApprovalMiddleware" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="AzureAICommunity.Agent.Middleware.ApprovalMiddleware" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add AzureAICommunity.Agent.Middleware.ApprovalMiddleware --version 1.0.0
                    
#r "nuget: AzureAICommunity.Agent.Middleware.ApprovalMiddleware, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package AzureAICommunity.Agent.Middleware.ApprovalMiddleware@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=AzureAICommunity.Agent.Middleware.ApprovalMiddleware&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=AzureAICommunity.Agent.Middleware.ApprovalMiddleware&version=1.0.0
                    
Install as a Cake Tool

<div align="center">

๐Ÿ” AzureAICommunity - Agent - Approval Middleware

Add a human-in-the-loop approval gate to AI agent tool calls with a single method call.

NuGet Version NuGet Downloads License .NET GitHub Repo GitHub Follow YouTube Channel YouTube Subscribers LinkedIn

Getting Started ยท Callback Contract ยท How It Works ยท Contributing

</div>


Overview

AzureAICommunity.Agent.Middleware.ApprovalMiddleware adds an approval gate directly into the AIAgentBuilder function-invocation pipeline. You pass only the tools that need approval โ€” all other tools registered on the agent execute freely without interruption. Before any gated tool executes, your callback is called with the pending FunctionCallContent; you decide whether to approve or deny using any UI: console, desktop dialog, HTTP call to a remote approver, etc. The middleware itself contains no UI code.


โœจ Features

Feature
๐ŸŽฏ Selective gating โ€” only the tools you specify are intercepted; others run freely
๐Ÿ”” Simple callback โ€” Func<FunctionCallContent, Task<bool?>> receives the tool name and arguments
๐Ÿ’ฌ LLM-aware denial โ€” when denied, a descriptive message is returned to the model so it can reason about the refusal
๐Ÿ”Œ MEA integration โ€” drops directly into any Microsoft.Agents.AI pipeline via UseApprovalMiddleware()
๐Ÿ–ฅ๏ธ UI agnostic โ€” use any approval UI: console, GUI, HTTP, SignalR, webhooks
๐Ÿ”— Method chaining โ€” returns the builder for fluent composition with other middleware

๐Ÿ“ฆ Installation

dotnet add package AzureAICommunity.Agent.Middleware.ApprovalMiddleware

๐Ÿš€ Quick Start

using AzureAICommunity.Agent.Middleware.ApprovalMiddleware;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

// Read-only tool โ€” no approval needed
var getStatusTool = AIFunctionFactory.Create(GetDeviceStatus);

// Destructive tools โ€” require approval before executing
var turnOnTool  = AIFunctionFactory.Create(TurnOnDevice);
var turnOffTool = AIFunctionFactory.Create(TurnOffDevice);

// All tools are registered on the agent
AIAgent baseAgent = new ChatClientAgent(
    chatClient,
    instructions: "You are a helpful smart-home assistant.",
    tools: [getStatusTool, turnOnTool, turnOffTool]);

// Only the destructive tools are passed to UseApprovalMiddleware.
// GetDeviceStatus is intentionally omitted โ€” it bypasses the approval gate.
AIAgent agent = new AIAgentBuilder(baseAgent)
    .UseApprovalMiddleware([turnOnTool, turnOffTool], async fc =>
    {
        // Return true          โ†’ approved
        // Return false or null โ†’ denied, a denial message is returned to the LLM
        Console.Write($"Allow '{fc.Name}'? (y/n): ");
        bool approved = Console.ReadLine()?.Trim() == "y";
        return (bool?)approved;
    })
    .Build();

AgentResponse response = await agent.RunAsync("Check the lights, then turn them on.");
Console.WriteLine(response);

๐Ÿ”” Callback Contract

The approvalCallback receives a FunctionCallContent with the tool name and arguments.

Return value Effect
true Approved โ€” the tool executes and its real result is returned to the LLM
false or null Denied โ€” a denial message is returned to the LLM as the tool result so it can reason about the refusal

The callback is Func<FunctionCallContent, Task<bool?>>, so it can be async and use any UI or remote call.


โš™๏ธ How It Works

LLM decides to call a tool
    โ””โ”€โ–บ FunctionInvocationContext intercepted by ApprovalMiddleware
            โ”‚
            โ”œโ”€ tool name in approvalTools?
            โ”‚       โ”œโ”€ YES โ†’ approvalCallback(FunctionCallContent) called
            โ”‚       โ”‚           โ”œโ”€ returns true         โ†’ next(context, ct)  โ† tool executes normally
            โ”‚       โ”‚           โ””โ”€ returns false/null   โ†’ denial message returned to LLM
            โ”‚       โ””โ”€ NO  โ†’ next(context, ct)    โ† tool executes freely, no approval prompt
            โ”‚
            โ””โ”€ agent continues with the result

๐Ÿ“‹ Type Reference

Type Description
ApprovalMiddlewareExtensions Provides the UseApprovalMiddleware extension method on AIAgentBuilder
FunctionCallContent Passed to the callback โ€” contains Name and Arguments of the pending tool call

Extension method

builder.UseApprovalMiddleware(
    IEnumerable<AITool> approvalTools,            // Tools that require approval
    Func<FunctionCallContent, Task<bool?>> approvalCallback  // Approval decision callback
);

๐Ÿค Contributing

Contributions are welcome! Please open an issue to discuss what you'd like to change before submitting a pull request.

๐Ÿ“ Repository: https://github.com/rvinothrajendran/AgentFramework

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Commit your changes (git commit -m 'Add my feature')
  4. Push to the branch (git push origin feature/my-feature)
  5. Open a Pull Request

๐Ÿ‘ค Author

Built and maintained by Vinoth Rajendran.


๐Ÿ“„ License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 92 5/1/2026
1.0.0 85 5/1/2026