IntFlows.AgentFramework.Guardrails
0.1.0-preview.2
dotnet add package IntFlows.AgentFramework.Guardrails --version 0.1.0-preview.2
NuGet\Install-Package IntFlows.AgentFramework.Guardrails -Version 0.1.0-preview.2
<PackageReference Include="IntFlows.AgentFramework.Guardrails" Version="0.1.0-preview.2" />
<PackageVersion Include="IntFlows.AgentFramework.Guardrails" Version="0.1.0-preview.2" />
<PackageReference Include="IntFlows.AgentFramework.Guardrails" />
paket add IntFlows.AgentFramework.Guardrails --version 0.1.0-preview.2
#r "nuget: IntFlows.AgentFramework.Guardrails, 0.1.0-preview.2"
#:package IntFlows.AgentFramework.Guardrails@0.1.0-preview.2
#addin nuget:?package=IntFlows.AgentFramework.Guardrails&version=0.1.0-preview.2&prerelease
#tool nuget:?package=IntFlows.AgentFramework.Guardrails&version=0.1.0-preview.2&prerelease
IntFlows Guardrails for Microsoft Agent Framework
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.2contains 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
IChatClientsupplied 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:
- PII masking and response restoration without a tool call
- An allowed lookup tool receiving restored PII
- A redacted tool receiving
[REDACTED] - A side-effect tool denied by the application approval callback
- An unlisted tool stopped by the default-block policy
- A prompt-injection request blocked before the model
- 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 = falsewhen 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 | Versions 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. |
-
net10.0
- Microsoft.Agents.AI (>= 1.20.0)
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.