-
Notifications
You must be signed in to change notification settings - Fork 0
Response Validation & Guardrails
Arian Amiramjadi edited this page Dec 24, 2025
·
1 revision
Validate AI responses with built-in and custom validators.
// Ensure response isn't empty and has reasonable length
response, err := ai.Claude().
NoEmptyResponse().
MaxLength(1000).
Ask("Explain Go concurrency")ai.Claude().
MinLength(50). // At least 50 characters
MaxLength(500). // At most 500 characters
Ask("...")ai.Claude().
WordCount(10, 100). // Between 10-100 words
Ask("...")ai.Claude().
MustContain("conclusion"). // Must include this text
MustNotContain("I don't know"). // Must not include this
Ask("...")ai.Claude().
MustMatch(`\d{4}-\d{2}-\d{2}`). // Must contain date
MustNotMatch(`(?i)error|failed`). // No error messages
Ask("...")// Ensure valid JSON
ai.Claude().
JSON().
MustBeJSON().
Ask("Return JSON with name and age")
// Validate against schema (struct)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
ai.Claude().
MustBeJSONSchema(&Person{}).
Ask("Return person data")ai.Claude().
NoEmptyResponse().
Ask("...")Blocks common XSS/injection patterns:
ai.Claude().
SafeContent().
Ask("Generate HTML snippet")Limits response length:
ai.Claude().
ConciseResponse(200). // Max 200 words
Ask("...")Combines JSON mode with validation:
ai.Claude().
StrictJSON().
Ask("Return structured data")ai.Claude().
ValidateWith("no-profanity", func(content string) error {
badWords := []string{"bad", "words"}
for _, word := range badWords {
if strings.Contains(content, word) {
return fmt.Errorf("contains prohibited word: %s", word)
}
}
return nil
}).
Ask("...")type SentimentValidator struct {
requiredSentiment string
}
func (v *SentimentValidator) Name() string { return "SentimentCheck" }
func (v *SentimentValidator) Validate(content string) error {
// Check sentiment...
if !hasSentiment(content, v.requiredSentiment) {
return &ai.ValidationError{
Validator: v.Name(),
Message: "wrong sentiment",
Content: content,
}
}
return nil
}
ai.Claude().
Validate(&SentimentValidator{requiredSentiment: "positive"}).
Ask("...")lengthValidator := &ai.MinLengthValidator{MinChars: 100}
jsonValidator := &ai.JSONValidator{}
ai.Claude().
Validate(ai.AllOf("length-and-json", lengthValidator, jsonValidator)).
Ask("...")ai.Claude().
Validate(ai.AnyOf("flexible",
&containsValidator{substr: "yes"},
&containsValidator{substr: "agreed"},
)).
Ask("Do you agree?")response, err := ai.Claude().
MaxLength(10).
Ask("Tell me a long story")
if err != nil {
if ve, ok := err.(*ai.ValidationError); ok {
fmt.Printf("Validation failed: %s\n", ve.Validator)
fmt.Printf("Message: %s\n", ve.Message)
// Content is still available
fmt.Printf("Content was: %s\n", ve.Content[:100])
}
}Transform or filter content after response:
// Trim whitespace
ai.Claude().
WithFilter(ai.TrimFilter()).
Ask("...")
// Truncate if too long
ai.Claude().
WithFilter(ai.MaxLengthFilter(500)).
Ask("...")
// Custom filter
ai.Claude().
WithFilter(func(content string) (string, error) {
// Remove markdown
cleaned := stripMarkdown(content)
return cleaned, nil
}).
Ask("...")Validators run in order; first failure stops:
ai.Claude().
NoEmptyResponse(). // Check 1: not empty
MinLength(50). // Check 2: long enough
MaxLength(1000). // Check 3: not too long
MustContain("summary"). // Check 4: has summary
MustBeJSON(). // Check 5: valid JSON
Ask("...")builder := ai.Claude().
MaxLength(100).
MustContain("hello")
// Remove all validators
builder.ClearValidators()See validation results:
ai.Debug = true
ai.Claude().
NoEmptyResponse().
MaxLength(100).
Ask("Hello")
// Output:
// ✓ Validation passed [NoEmptyResponse]
// ✓ Validation passed [MaxLength]type APIResponse struct {
Status string `json:"status"`
Data any `json:"data"`
}
response, err := ai.Claude().
StrictJSON().
MustBeJSONSchema(&APIResponse{}).
Ask("Generate API response for user profile")response, err := ai.Claude().
SafeContent().
MustNotContain("confidential").
MustNotMatch(`(?i)password|secret|api.?key`).
ValidateWith("length-check", func(s string) error {
if len(s) > 10000 {
return errors.New("response too long")
}
return nil
}).
Ask("Generate documentation")type Entity struct {
Name string `json:"name"`
Type string `json:"type"`
Tags []string `json:"tags"`
}
ai.Claude().
StrictJSON().
MustBeJSONSchema(&Entity{}).
NoEmptyResponse().
Ask("Extract entity from: Apple Inc. is a technology company")