Guardrails
Guardrails validate input and output at runtime. They block content that violates policy before it reaches the model or after the model responds. Use them to enforce blocklists, length limits, PII filtering, and custom rules.
Guardrail Interface
Every guardrail implements the Guardrail interface:
type Guardrail interface {
Check(ctx context.Context, content string) Result
}
type Result struct {
Passed bool `json:"passed"`
Reason string `json:"reason,omitempty"`
}
- Passed:
trueif the content is acceptable;falseto block. - Reason: Human-readable explanation when
Passedisfalse.
Engine
The guardrails engine runs rules by position (input or output):
engine := guardrails.NewEngine()
engine.AddRule(guardrails.Rule{
Name: "blocklist",
Position: guardrails.Input,
Guardrail: &guardrails.BlocklistGuardrail{Blocklist: []string{"spam"}},
})
- CheckInput(ctx, content): Runs all input guardrails. Returns the first failure, or nil.
- CheckOutput(ctx, content): Runs all output guardrails. Returns the first failure, or nil.
Position
| Position | When Checked |
|---|---|
Input |
Before the model receives user content |
Output |
After the model produces a response |
Built-in Guardrails
BlocklistGuardrail
Rejects content containing any blocked term (case-insensitive).
g := &guardrails.BlocklistGuardrail{
Blocklist: []string{"password", "secret", "confidential"},
}
result := g.Check(ctx, "Please share your password")
// result.Passed == false, result.Reason == "blocked term: \"password\""
MaxLengthGuardrail
Rejects content exceeding a character limit.
g := &guardrails.MaxLengthGuardrail{MaxChars: 1000}
result := g.Check(ctx, longString)
// result.Passed == false if len(longString) > 1000
Adding via Builder
Use the agent builder to attach guardrails:
a, err := agent.New("my-agent", "My Agent").
WithModel(provider).
AddInputGuardrail("blocklist", &guardrails.BlocklistGuardrail{
Blocklist: []string{"spam", "malware"},
}).
AddOutputGuardrail("max_length", &guardrails.MaxLengthGuardrail{
MaxChars: 4000,
}).
Build()
- AddInputGuardrail(name, g): Adds input validation.
- AddOutputGuardrail(name, g): Adds output validation.
Where Guardrails Run
| Method | Input Checked | Output Checked |
|---|---|---|
Chat |
userMessage before model call |
resp.Content after model response |
ChatWithSession |
userMessage before model call |
resp.Content after model response |
Run |
input["message"] if present |
Not applicable |
When a guardrail fails, the method returns an error: "input guardrail failed: [input] blocklist: blocked term: \"...\"" or "output guardrail failed: ...".
Custom Guardrails
Implement the Guardrail interface for custom logic:
type PIIGuardrail struct {
Patterns []*regexp.Regexp
}
func (g *PIIGuardrail) Check(_ context.Context, content string) guardrails.Result {
for _, p := range g.Patterns {
if p.MatchString(content) {
return guardrails.Result{
Passed: false,
Reason: fmt.Sprintf("PII detected: %s", p.String()),
}
}
}
return guardrails.Result{Passed: true}
}
Register it:
a.AddInputGuardrail("pii", &PIIGuardrail{
Patterns: []*regexp.Regexp{
regexp.MustCompile(`\b\d{16}\b`), // credit card
regexp.MustCompile(`\b\d{3}-\d{2}-\d{4}\b`), // SSN
},
})
Example: Building a PII Guardrail
package main
import (
"context"
"fmt"
"regexp"
"github.com/spawn08/chronos/engine/guardrails"
"github.com/spawn08/chronos/engine/model"
"github.com/spawn08/chronos/sdk/agent"
)
type PIIGuardrail struct {
Patterns []struct {
Name string
Pattern *regexp.Regexp
}
}
func NewPIIGuardrail() *PIIGuardrail {
return &PIIGuardrail{
Patterns: []struct {
Name string
Pattern *regexp.Regexp
}{
{"credit_card", regexp.MustCompile(`\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b`)},
{"ssn", regexp.MustCompile(`\b\d{3}-\d{2}-\d{4}\b`)},
{"email", regexp.MustCompile(`\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b`)},
},
}
}
func (g *PIIGuardrail) Check(_ context.Context, content string) guardrails.Result {
for _, p := range g.Patterns {
if p.Pattern.MatchString(content) {
return guardrails.Result{
Passed: false,
Reason: fmt.Sprintf("PII pattern matched: %s", p.Name),
}
}
}
return guardrails.Result{Passed: true}
}
func main() {
ctx := context.Background()
provider := model.NewOpenAI("your-api-key")
a, err := agent.New("safe-agent", "Safe Agent").
WithModel(provider).
WithSystemPrompt("You are a helpful assistant.").
AddInputGuardrail("pii", NewPIIGuardrail()).
AddOutputGuardrail("max_length", &guardrails.MaxLengthGuardrail{MaxChars: 2000}).
Build()
if err != nil {
panic(err)
}
resp, err := a.Chat(ctx, "What is the capital of France?")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(resp.Content)
}