ToolGate.Approvals 0.1.0

dotnet add package ToolGate.Approvals --version 0.1.0
                    
NuGet\Install-Package ToolGate.Approvals -Version 0.1.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="ToolGate.Approvals" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ToolGate.Approvals" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="ToolGate.Approvals" />
                    
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 ToolGate.Approvals --version 0.1.0
                    
#r "nuget: ToolGate.Approvals, 0.1.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 ToolGate.Approvals@0.1.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=ToolGate.Approvals&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=ToolGate.Approvals&version=0.1.0
                    
Install as a Cake Tool

ToolGate.NET

CI NuGet License: MIT

Policy and approvals middleware for AI tool calls in .NET applications.

ToolGate evaluates every LLM tool call against configurable policies — Allow, Deny, or RequireApproval — before the tool executes. It integrates with Microsoft.Extensions.AI as a DelegatingChatClient decorator.

Features

  • Policy Pipeline — Sequential evaluator with first-deny-wins aggregation
  • Built-in Policies — Denylist, allowlist, and high-risk approval policies
  • Approval Workflow — Human-in-the-loop approval with state machine (Pending → Approved/Denied/Expired)
  • Custom Policies — Implement IToolPolicy to add your own evaluation logic
  • Argument Redaction — Sensitive fields (passwords, keys, tokens) are automatically redacted in logs and audit
  • Observability — OpenTelemetry-compatible tracing (ActivitySource) and metrics (Meter)
  • Fail-Closed by Default — Policy errors block tool execution (configurable)

Packages

Package Purpose
ToolGate.Core Pipeline, models, abstractions, diagnostics
ToolGate.Policies Built-in denylist, allowlist, and high-risk policies
ToolGate.Approvals In-memory approval store and state machine
ToolGate.Adapters.ExtensionsAI MEAI DelegatingChatClient adapter + convenience registration

Quick Start

1. Install packages

dotnet add package ToolGate.Adapters.ExtensionsAI

The adapter package transitively includes Core, Policies, and Approvals.

2. Register services

using ToolGate.Adapters.ExtensionsAI.DependencyInjection;

services.AddToolGate(
    configureDenylist: deny =>
    {
        deny.DeniedTools.Add("delete_database");
        deny.DeniedPatterns.Add("rm_*");
    },
    configureAllowlist: allow =>
    {
        allow.AllowedTools.Add("get_weather");
        allow.AllowedTools.Add("get_time");
    });

// Wrap your chat client with ToolGate
services.AddChatClient(innerClient)
    .UseToolGate();

3. Tool calls are now evaluated

When the LLM returns a tool call, ToolGate intercepts it:

  • Allowed tools pass through unchanged
  • Denied tools are replaced with a FunctionResultContent containing the denial reason
  • RequireApproval tools are held until a human approves or denies via IApprovalProvider

Configuration

ToolGateOptions

services.AddToolGateCore(options =>
{
    options.FailMode = FailMode.FailClosed;        // Default: errors block execution
    options.DefaultDecision = Decision.Deny;        // Default: unknown tools are denied
    options.DefaultApprovalTtl = TimeSpan.FromMinutes(30);
    options.Redaction.SensitiveKeys.Add("my_secret_field");
});

Denylist Policy

Blocks tools by exact name or glob pattern. Evaluated first (Order: -1000).

services.AddToolGatePolicies(configureDenylist: deny =>
{
    deny.DeniedTools.Add("delete_database");
    deny.DeniedTools.Add("drop_table");
    deny.DeniedPatterns.Add("rm_*");        // Glob pattern
    deny.DeniedPatterns.Add("*.destructive");
});

Allowlist Policy

Explicitly allows tools. Optional DenyUnlisted mode blocks everything not in the list. Evaluated second (Order: -500).

services.AddToolGatePolicies(configureAllowlist: allow =>
{
    allow.AllowedTools.Add("get_weather");
    allow.AllowedTools.Add("search_docs");
    allow.DenyUnlisted = true;   // Deny everything not explicitly allowed
});

High-Risk Approval Policy

Requires human approval for tools with high risk metadata. Evaluated late (Order: 500).

services.AddToolGatePolicies(configureHighRisk: risk =>
{
    risk.MinimumRiskLevel = RiskLevel.High;  // Default
});

Triggered when ToolCallContext.Metadata.RiskLevel >= MinimumRiskLevel or when metadata contains the "high-risk" tag.

Custom Policies

Implement IToolPolicy and register it in DI:

public class RateLimitPolicy : IToolPolicy
{
    public string Name => "RateLimit";
    public int Order => 100;   // After allowlist, before high-risk

    public Task<PolicyOutcome> EvaluateAsync(
        ToolCallContext context,
        CancellationToken cancellationToken = default)
    {
        if (IsOverLimit(context.ToolName))
            return Task.FromResult(PolicyOutcome.DenyResult(
                "RateLimited", "Too many calls to this tool"));

        return Task.FromResult(PolicyOutcome.AbstainResult());
    }
}

// Register:
services.TryAddEnumerable(
    ServiceDescriptor.Singleton<IToolPolicy, RateLimitPolicy>());

Policy outcomes: AllowResult(), DenyResult(), RequireApprovalResult(), AbstainResult()

Policy ordering: Lower Order values evaluate first. Built-in: Denylist (-1000), Allowlist (-500), HighRisk (500). Custom policies default to 0.

Approval Workflow

When a policy returns RequireApproval, the pipeline creates an approval request:

var approvalProvider = sp.GetRequiredService<IApprovalProvider>();

// Approve programmatically (e.g., from an admin UI or webhook)
var result = await approvalProvider.ApproveAsync(approvalId, actor: "admin@example.com");

// On next evaluation of the same invocation, ToolGate recognizes the approval
// and allows the tool call to proceed (resume-after-approval)

The in-memory approval store uses first-writer-wins concurrency and lazy TTL expiration.

Observability

ToolGate emits OpenTelemetry-compatible diagnostics:

  • Tracing: ActivitySource named "ToolGate" with evaluation spans
  • Metrics: Meter named "ToolGate" with:
    • toolgate.evaluations.count — Counter by decision
    • toolgate.evaluations.duration — Histogram in ms
    • toolgate.errors.count — Counter by error type
    • toolgate.approvals.count — Counter by state transition
  • Logging: Structured log events with stable IDs (see ToolGateEventIds)

Samples

Sample Description
ConsoleChat Minimal console app demonstrating all decision types (Allow, Deny, RequireApproval)
AzureChat Azure OpenAI integration with tool policies
ExpenseAgent Expense report agent with custom policies (amount thresholds, read-only enforcement)
dotnet run --project samples/ToolGate.Samples.ConsoleChat

Prerequisites

Contributing

See CONTRIBUTING.md for guidelines on building, testing, and submitting pull requests.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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 (1)

Showing the top 1 NuGet packages that depend on ToolGate.Approvals:

Package Downloads
ToolGate.Adapters.ExtensionsAI

Microsoft.Extensions.AI adapter for ToolGate — DelegatingChatClient that evaluates tool calls against policies.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 87 3/6/2026