IntFlows.AgentFramework.Guardrails 0.1.0-preview.2

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

IntFlows Guardrails for Microsoft Agent Framework

NuGet License

Lightweight guardrail middleware for C# agents built with Microsoft Agent Framework. It intercepts calls at the IChatClient boundary, blocks common prompt-injection attempts, masks personally identifiable information before it reaches the model, and optionally restricts requests to allowed intents.

Preview: 0.1.0-preview.2 contains the initial in-memory implementation. Its public API and behavior may change before version 1.0.

Features

  • Prompt-injection detection before model invocation
  • Reversible PII masking for email addresses, Australian phone numbers, and candidate TFN, ABN, Medicare and payment-card numbers
  • PII restoration in responses and structured tool arguments
  • PII masking of tool results before the next model call
  • Isolated, per-model-call in-memory token vaults
  • Custom intent policies through IIntentValidator
  • Semantic intent matching through SemanticIntentValidator
  • Typed block reasons through GuardrailException
  • Tool allow, block, PII-redact, and application-approval policies
  • Versioned, content-free decision events for audit integrations
  • Normal and buffered streaming Agent Framework calls

Redis and other persistent vault providers are outside the preview scope.

Requirements

  • .NET 10 or later
  • Microsoft Agent Framework 1.20.0 or a compatible release
  • An IChatClient supplied by your model provider

Installation

dotnet add package IntFlows.AgentFramework.Guardrails --version 0.1.0-preview.2

Or add a package reference:

<PackageReference Include="IntFlows.AgentFramework.Guardrails" Version="0.1.0-preview.2" />

Quick start

Wrap the provider's IChatClient before constructing ChatClientAgent:

using IntFlows.AgentFramework.Guardrails;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

// Create this with Azure OpenAI, OpenAI, Ollama, or another provider.
IChatClient modelClient = CreateYourChatClient();

using var guardedClient = modelClient
    .AsBuilder()
    .UseGuardrails(new GuardOptions
    {
        DetectPromptInjection = true,
        MaskPii = true,
        RestorePii = true,
        MaxInputCharacters = 100_000
    })
    .Build();

var agent = new ChatClientAgent(
    guardedClient,
    instructions: "Help users build integration workflows.");

try
{
    var response = await agent.RunAsync(
        "Email jane@example.com about the Azure Blob workflow.");

    Console.WriteLine(response.Text);
}
catch (GuardrailException exception)
{
    Console.WriteLine($"Request blocked: {exception.Reason}");
}

The model receives an opaque value similar to:

Email [[EMAIL_991d40d7d2f34f5ba6200650d31fb929_0]] about the Azure Blob workflow.

The application receives the restored response containing jane@example.com. The original caller-owned messages are not mutated.

Intent validation

Intent checking is disabled until an IIntentValidator is configured. Use the built-in semantic validator with any compatible embedding generator:

var guardOptions = new GuardOptions
{
    IntentValidator = new SemanticIntentValidator(
        embeddingGenerator,
        allowedIntentDescriptions:
        [
            "Integrate Azure Blob Storage, APIs, and business workflows",
            "Diagnose failures in an existing integration"
        ],
        threshold: 0.7)
};

It embeds the latest masked user message and the allowed descriptions, then uses cosine similarity. Tune the threshold against examples from your application. The embedding generator can be local or remote and remains owned by the caller.

For deterministic business rules, implement the policy interface:

public sealed class SupportIntentValidator : IIntentValidator
{
    public ValueTask<bool> IsAllowedAsync(
        string input,
        CancellationToken cancellationToken = default)
    {
        var allowed = input.Contains("support", StringComparison.OrdinalIgnoreCase);
        return ValueTask.FromResult(allowed);
    }
}

Configuration

Option Default Purpose
DetectPromptInjection true Reject common attempts to override instructions or expose secrets.
MaskPii true Replace detected PII before every model request.
RestorePii true Restore request PII in responses and tool arguments.
MaxInputCharacters 100000 Reject requests whose scanned text exceeds this budget.
IntentValidator null Optional application-specific or semantic intent policy.

Blocked calls throw GuardrailException without including the original input. Reasons are PromptInjection, DisallowedIntent, InputTooLarge, and UnsupportedContent. Blocked input never reaches the model.

Tool calls

Place the guard around the provider client passed to ChatClientAgent. The agent owns the function-invocation loop while the guard sees each model call:

user input -> mask -> model -> restore tool arguments -> tool
tool result -> mask -> model -> restore final response -> application

Supported content consists of text, function calls, and JSON-serializable function results. Images, audio, files, and other content types currently fail closed.

Tool policies

Add function middleware to the agent builder using exact function names:

var guardedAgent = new ChatClientAgent(
        guardedClient,
        instructions: "Help with support requests.",
        tools: [searchDocs, updateTicket, deleteTicket])
    .AsBuilder()
    .UseGuardrailTools(new ToolGuardOptions
    {
        PolicyVersion = "support-tools-v1",
        DefaultAction = GuardAction.Block,
        Rules = new Dictionary<string, GuardAction>
        {
            ["searchDocs"] = GuardAction.Allow,
            ["updateTicket"] = GuardAction.Redact,
            ["deleteTicket"] = GuardAction.ApprovalRequired
        },
        ApproveAsync = async (call, cancellationToken) =>
        {
            // Ask a trusted, application-owned approval service.
            return await approvals.IsApprovedAsync(
                call.ToolName, call.Arguments, cancellationToken);
        }
    })
    .Build();
Action Behavior
Allow Execute the tool with its arguments unchanged.
Block Stop before executing the tool.
Redact Replace detected PII in nested string arguments with [REDACTED], then execute.
ApprovalRequired Execute only when ApproveAsync returns true.

DefaultAction = GuardAction.Block creates an allowlist. With the default Allow, unlisted tools continue to run. Approval belongs to trusted application code; do not derive approval from model output. Redaction is irreversible and may make an argument invalid for its tool schema. Blocked and denied policies return a GuardToolBlockedResult and set the Agent Framework function loop to terminate. This prevents the tool from running and avoids sending its failure through another model call. Inspect the emitted decision to handle the policy outcome in application code.

Decision events

Both model guardrails and tool policies can emit audit decisions. Events contain identifiers, timing, policy version, action, and reason only. They never include prompt text, PII values, or tool arguments.

var modelOptions = new GuardOptions
{
    PolicyVersion = "support-model-v1",
    OnDecision = async (decision, cancellationToken) =>
        await auditStore.WriteAsync(decision, cancellationToken)
};

var toolOptions = new ToolGuardOptions
{
    PolicyVersion = "support-tools-v1",
    OnDecision = async (decision, cancellationToken) =>
        await auditStore.WriteAsync(decision, cancellationToken)
};

GuardDecision.SchemaVersion is currently "1". Callbacks are awaited so an application can choose fail-closed auditing: callback failures stop processing.

Run the example

The repository includes an offline ChatClientAgent example using a fake model. It requires no credentials, model download, Redis instance, or cloud subscription:

dotnet build
dotnet run --project examples/Guardrails.Example
dotnet run --project examples/Guardrails.Example -- "Azure workflow for jane@example.com"

With no command-line prompt, the example executes seven deterministic scenarios:

  1. PII masking and response restoration without a tool call
  2. An allowed lookup tool receiving restored PII
  3. A redacted tool receiving [REDACTED]
  4. A side-effect tool denied by the application approval callback
  5. An unlisted tool stopped by the default-block policy
  6. A prompt-injection request blocked before the model
  7. An unrelated intent blocked before the model

The console shows every content-free audit decision, the masked text received by the model, and the arguments received by tools. The scripted IChatClient controls only model responses; ChatClientAgent, its function loop, AIFunctionFactory, chat middleware, and function middleware are all the real Agent Framework APIs.

Run the executable behavioral checks with:

dotnet run --project tests/Guardrails.Tests

The check process exits with a nonzero code on failure.

Preview limitations

  • Prompt-injection and PII checks use regular expressions. They can miss harmful or sensitive input and can reject benign input.
  • Numeric PII matches are candidates and are not checksum-validated. Names, addresses, and model-based PII classification are not included yet.
  • JSON string values are transformed. Field names, tool names and schemas, provider options, and opaque provider state are not scanned.
  • System and developer messages are masked but exempt from injection checks. The latest user message is checked by the configured intent policy.
  • Streaming calls are buffered so placeholders can be restored atomically.
  • Raw provider payloads and extension metadata are omitted from transformed messages so unscanned copies of the input are not forwarded.
  • Each vault lasts for one model invocation. There is no persistence, Redis, cross-process recovery, audit store, or cryptographic erasure.
  • Restored PII is visible to application code, tools, logs, and agent history. Set RestorePii = false when downstream code should receive opaque tokens.

Combine this library with provider safety controls, tool authorization, least-privilege credentials, output validation, secure logging, and tests for your application's threat model.

Contributing

Issues and pull requests are welcome. Validate changes with:

dotnet build
dotnet run --project tests/Guardrails.Tests

License

Licensed under the Apache License 2.0.

See Microsoft's Agent Framework middleware documentation for more information about middleware composition.

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
0.1.0-preview.2 63 9/16/2026
0.1.0-preview.1 70 9/5/2026

Adds tool allow/block/redact/approval policies and versioned, content-free guard decision callbacks.