DI Setup
The entire GuardRails stack is wired by a single extension method. One call registers every layer — domain contracts, service implementations, providers, circuit breaker, audit logger, and all built-in guards.
Minimal Setup
In your application's Program.cs or startup class, call AddGuardRailsExecution():
// Program.cs / Startup.cs
builder.Services.AddGuardRailsExecution();
That's all that's required. Every component below is registered automatically.
What AddGuardRailsExecution() Registers
| Service Interface | Implementation | Lifetime |
|---|---|---|
INodeGuardExecutor | NodeGuardExecutor | Scoped |
IGuardRailsExecutor | GuardRailsExecutor | Scoped |
IGuardRailsOrchestrator | GuardRailsOrchestrator | Scoped |
IGuardConfigResolver | GuardConfigResolver | Singleton |
IGuardRegistry | GuardRegistry | Singleton |
IGuardCircuitBreaker | GuardCircuitBreaker | Singleton |
IGuardRailsAuditLogger | GuardRailsAuditLogger | Singleton |
ITransientFailureWindow | TransientFailureWindow | Singleton |
IPiiDetector | RegexPiiDetector | Singleton |
ISecretsRedactor | SecretsRedactor | Singleton |
IGuardRail (×6) | All 6 built-in guards | Singleton |
Custom Circuit Breaker Policy
To override the default circuit breaker policy, use the overload that accepts a CircuitBreakerPolicy:
builder.Services.AddGuardRailsExecution(new CircuitBreakerPolicy
{
FailureThreshold = 3, // open after 3 failures (default: 5)
OpenDurationSeconds = 30, // stay open for 30s (default: 60)
SuccessThresholdForHalfOpen = 2, // 2 successes to close again (default: 3)
FailSecure = true, // block on open circuit (default: true)
ResetOnTransient = true, // don't count transients (default: true)
FailureWindowSeconds = 120 // sliding window (default: 300)
});
Registering the PiiNodeGuard Composite
The PiiNodeGuard is a composite that wires PiiDetectionGuard (Pre) and PiiRedactionGuard (Post) into a single pluggable unit. Register it separately if you want the composite behavior:
builder.Services.AddGuardRailsExecution();
// Register PiiNodeGuard as an additional INodeGuardExecutor
// (complements the built-in guards, or replaces per-node PII config)
builder.Services.AddSingleton<PiiNodeGuard>();
Registering a Custom Guard
Custom guards register through DI as IGuardRail singletons. The GuardRegistry discovers them automatically on startup:
// After AddGuardRailsExecution():
builder.Services.AddSingleton<IGuardRail, ContentModerationGuard>();
// If ContentModerationGuard needs its own dependencies:
builder.Services.AddSingleton<IContentModerationClient, AzureContentModerationClient>();
builder.Services.AddSingleton<IGuardRail, ContentModerationGuard>();
Loading Plugin Assemblies at Startup
For external DLL plugins, call LoadPluginsAsync() from a hosted service or startup hook — after the DI container is built:
// IHostedService or app.Lifetime.ApplicationStarted:
var registry = serviceProvider.GetRequiredService<IGuardRegistry>();
await registry.LoadPluginsAsync(pluginDirectory: "/opt/guardrails/plugins");
// LoadPluginsAsync delegates to IGuardPluginLoader which:
// 1. Scans the directory for guard DLLs
// 2. Validates signatures via IPluginSignatureValidator
// 3. Checks review metadata via IPluginCodeReviewMetadata
// 4. Registers passing assemblies as GuardDefinitions
Guard Group Registration
Guard groups are registered via IGuardRegistry during startup. Groups bundle related guards for node-level reuse:
var registry = serviceProvider.GetRequiredService<IGuardRegistry>();
registry.RegisterGroup("PiiCompliance", new GuardGroupDefinition
{
Guards = new[]
{
new GuardEntry { Name = "PiiDetectionGuard", Order = 1 },
new GuardEntry { Name = "PiiRedactionGuard", Order = 2 }
}
});
registry.RegisterGroup("Resilience", new GuardGroupDefinition
{
Guards = new[]
{
new GuardEntry { Name = "TimeoutGuard", Order = 1, Config = new { TimeoutMs = 5000 } },
new GuardEntry { Name = "CircuitBreakerGuard", Order = 2 }
}
});
Once registered, these groups can be referenced by name in any node's guardRails.groups configuration.
Backward Compatibility: RateLimitingOrchestrator
Deployments that used the standalone rate limiting subsystem before GuardRails was introduced can continue to use IRateLimitingOrchestrator in parallel. BaseNodeExecutor checks for both:
// BaseNodeExecutor uses pluggable tier: either INodeGuardExecutor
// or IRateLimitingOrchestrator as a fallback, or both simultaneously.
// Both registered → both run (guards take precedence, orchestrator handles rate-limiting checks)
// Only orchestrator registered → legacy rate limiting, no guard pipeline
// Only NodeGuardExecutor registered → full guard pipeline (recommended)
builder.Services.AddGuardRailsExecution();
// Remove IRateLimitingOrchestrator registration to retire the legacy tier
Health Check Integration
GuardRails exposes a health check endpoint via the standard ASP.NET Core health check system. Register it alongside your other health checks:
builder.Services.AddHealthChecks()
.AddGuardRailsHealthCheck(); // registered by AddGuardRailsExecution()
// The health check reports:
// - Each guard's circuit state (Closed / Open / HalfOpen)
// - Plugin review metadata status
// - Configuration cache freshness
// GET /health/guardrails
{
"status": "healthy",
"guards": {
"TimeoutGuard": { "circuit": "Closed", "lastFailure": null },
"PiiDetectionGuard": { "circuit": "Closed", "lastFailure": null },
"RateLimitingGuard": { "circuit": "HalfOpen", "lastFailure": "2026-05-25T14:00:00Z" },
"CircuitBreakerGuard": { "circuit": "Closed", "lastFailure": null }
},
"plugins": {
"ContentModerationGuard": { "signed": true, "reviewed": true }
}
}
Full Startup Example
// Program.cs — complete GuardRails wiring
var builder = WebApplication.CreateBuilder(args);
// 1. Core GuardRails stack
builder.Services.AddGuardRailsExecution(new CircuitBreakerPolicy
{
FailureThreshold = 5,
OpenDurationSeconds = 60
});
// 2. Custom guard dependencies
builder.Services.AddHttpClient<IContentModerationClient, AzureContentModerationClient>();
builder.Services.AddSingleton<IGuardRail, ContentModerationGuard>();
// 3. Health checks
builder.Services.AddHealthChecks().AddGuardRailsHealthCheck();
var app = builder.Build();
// 4. Load plugin assemblies after container build
app.Lifetime.ApplicationStarted.Register(async () =>
{
var registry = app.Services.GetRequiredService<IGuardRegistry>();
await registry.LoadPluginsAsync("/opt/guardrails/plugins");
});
// 5. Health endpoint
app.MapHealthChecks("/health/guardrails");
app.Run();