2025-12-05 · Authensor

AI Agent Safety for C# and .NET Developers

SafeClaw by Authensor brings deny-by-default action gating to C# and .NET AI agents, including those built with Microsoft Semantic Kernel. Every Process.Start(), File.ReadAllText(), and HttpClient.SendAsync() call is gated against your YAML policy before execution. Install SafeClaw with npx @authensor/safeclaw and integrate it into your .NET agent via the local REST API.

.NET Agent Risk Surface

.NET AI agents — especially those using Semantic Kernel's auto function calling — can invoke dangerous system APIs:

Semantic Kernel's planner can chain these operations autonomously. SafeClaw ensures every operation is checked against policy first, with 446 tests validating the gate logic and hash-chained audit logging for compliance.

Installation

npx @authensor/safeclaw

Policy

version: 1
defaultAction: deny

rules:
- action: file.read
path:
glob: "C:\\App\\Data\\**"
decision: allow

- action: file.write
path:
glob: "C:\\App\\Output\\**"
decision: allow

- action: process.exec
command:
startsWith: "dotnet"
decision: allow

- action: network.request
host:
in: ["api.openai.com", "api.anthropic.com"]
decision: allow

- action: file.read
path:
glob: "*\\appsettings.json"
decision: deny

C# Integration

using System.Net.Http.Json;
using System.Text.Json.Serialization;

public record ActionRequest(
[property: JsonPropertyName("action")] string Action,
[property: JsonPropertyName("path")] string? Path = null,
[property: JsonPropertyName("command")] string? Command = null,
[property: JsonPropertyName("host")] string? Host = null,
[property: JsonPropertyName("url")] string? Url = null,
[property: JsonPropertyName("method")] string? Method = null
);

public record GateDecision(
[property: JsonPropertyName("allowed")] bool Allowed,
[property: JsonPropertyName("reason")] string Reason
);

public class SafeClawGate : IDisposable
{
private readonly HttpClient _client = new();
private readonly string _endpoint;

public SafeClawGate(string endpoint = "http://localhost:9800")
{
_endpoint = endpoint;
}

public async Task<GateDecision> CheckAsync(ActionRequest request)
{
try
{
var response = await _client.PostAsJsonAsync($"{_endpoint}/check", request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<GateDecision>()
?? new GateDecision(false, "Deserialization failed");
}
catch
{
// Fail closed
return new GateDecision(false, "SafeClaw unreachable");
}
}

public void Dispose() => _client.Dispose();
}

Semantic Kernel Integration

Wrap Semantic Kernel native functions with SafeClaw gating:

using Microsoft.SemanticKernel;
using System.ComponentModel;
using System.Diagnostics;

public class SafeFilePlugin
{
private readonly SafeClawGate _gate = new();

[KernelFunction, Description("Read a file from disk")]
public async Task<string> ReadFileAsync(string path)
{
var decision = await _gate.CheckAsync(new ActionRequest("file.read", Path: path));
if (!decision.Allowed)
throw new UnauthorizedAccessException($"SafeClaw denied: {decision.Reason}");

return await File.ReadAllTextAsync(path);
}

[KernelFunction, Description("Execute a shell command")]
public async Task<string> ExecCommandAsync(string command)
{
var decision = await _gate.CheckAsync(new ActionRequest("process.exec", Command: command));
if (!decision.Allowed)
throw new UnauthorizedAccessException($"SafeClaw denied: {decision.Reason}");

var process = Process.Start(new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = $"/c {command}",
RedirectStandardOutput = true,
UseShellExecute = false
});
return await process!.StandardOutput.ReadToEndAsync();
}
}

Register with the kernel:

var kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion("gpt-4", apiKey)
    .Build();

kernel.Plugins.AddFromObject(new SafeFilePlugin());

SafeClaw logs all decisions to its hash-chained audit trail. MIT licensed, provider-agnostic.

Cross-References

Try SafeClaw

Action-level gating for AI agents. Set it up in your browser in 60 seconds.

$ npx @authensor/safeclaw