OpenGuardrails Go Client - Context-aware AI guardrails based on LLM.
An LLM-based context-aware AI guardrail that understands conversation context for security, safety and data leakage detection.
- 🧠 Context-Aware - LLM-based conversation understanding, not just simple batch detection
- 🔍 Prompt Attack Detection - Identify malicious prompt injection and jailbreak attacks
- 📋 Content Compliance Detection - Meet the basic security requirements for generative AI services
- 🔐 Sensitive Data Leakage Prevention - Detect and prevent personal/corporate sensitive data leaks
- 🧩 User-Level Ban Policies - Support risk identification and ban policies based on user granularity
- 🖼️ Multimodal Detection - Support image content safety detection
- 🛠️ Easy Integration - Compatible with OpenAI API format, one-line code integration
- ⚡ OpenAI-style API - Familiar interface design, quick to get started
- 🚀 Sync/Async Support - Support both synchronous and asynchronous calling methods to meet different scenario requirements
- Go 1.18 or higher
go get https://github.com/openguardrails/openguardrails-gopackage main
import (
"context"
"fmt"
"log"
"https://github.com/openguardrails/openguardrails-go"
)
func main() {
// Initialize client
client := openguardrails.NewClient("your-api-key")
ctx := context.Background()
// Check user input (optionally pass user ID)
result, err := client.CheckPrompt(ctx, "User input question", "user-123") // user-123 is optional
if err != nil {
log.Fatal(err)
}
fmt.Println(result.OverallRiskLevel) // no_risk/low_risk/medium_risk/high_risk
fmt.Println(result.SuggestAction) // pass/reject/replace
fmt.Println(result.score) // confidence score
// Check output content (based on context)
ctxResult, err := client.CheckResponseCtx(ctx, "Teach me how to cook", "I can teach you some simple home-cooked dishes", "user-123")
if err != nil {
log.Fatal(err)
}
fmt.Println(ctxResult.OverallRiskLevel) // no_risk
fmt.Println(ctxResult.SuggestAction) // pass
}package main
import (
"context"
"fmt"
"log"
"https://github.com/openguardrails/openguardrails-go"
)
func main() {
client := openguardrails.NewClient("your-api-key")
ctx := context.Background()
// Check complete conversation context - core functionality
messages := []*openguardrails.Message{
openguardrails.NewMessage("user", "User's question"),
openguardrails.NewMessage("assistant", "AI assistant's answer"),
openguardrails.NewMessage("user", "User's follow-up question"),
}
result, err := client.CheckConversation(ctx, messages, "user-123") // user-123 is optional
if err != nil {
log.Fatal(err)
}
// Check detection result
if result.IsSafe() {
fmt.Println("Conversation is safe, can continue")
} else if result.IsBlocked() {
fmt.Println("Conversation has risks, recommend blocking")
} else if result.HasSubstitute() {
fmt.Printf("Recommend using safe answer: %s\n", *result.SuggestAnswer)
}
}package main
import (
"context"
"fmt"
"log"
"time"
"https://github.com/openguardrails/openguardrails-go"
)
func main() {
// Create async client
asyncClient := openguardrails.NewAsyncClient("your-api-key")
defer asyncClient.Close() // Remember to close resources
ctx := context.Background()
// Asynchronously check single prompt
resultChan := asyncClient.CheckPromptAsync(ctx, "User question")
select {
case result := <-resultChan:
if result.Error != nil {
log.Printf("Detection failed: %v", result.Error)
} else {
fmt.Printf("Async detection completed: %s\n", result.Result.OverallRiskLevel)
}
case <-time.After(5 * time.Second):
fmt.Println("Detection timeout")
}
// Asynchronous conversation detection
messages := []*openguardrails.Message{
openguardrails.NewMessage("user", "User question"),
openguardrails.NewMessage("assistant", "Assistant answer"),
}
conversationChan := asyncClient.CheckConversationAsync(ctx, messages)
result := <-conversationChan
if result.Error != nil {
log.Printf("Conversation detection failed: %v", result.Error)
} else {
fmt.Printf("Conversation detection completed: %s\n", result.Result.OverallRiskLevel)
}
// Batch async detection (high performance)
contents := []string{"Content 1", "Content 2", "Content 3"}
batchChan := asyncClient.BatchCheckPrompts(ctx, contents)
for result := range batchChan {
if result.Error != nil {
log.Printf("Batch detection failed: %v", result.Error)
} else {
fmt.Printf("Batch detection result: %s\n", result.Result.OverallRiskLevel)
}
}
}Supports multimodal detection functionality, supports image content safety detection, can combine prompt text semantics and image content semantic analysis to determine safety.
package main
import (
"context"
"fmt"
"log"
"https://github.com/openguardrails/openguardrails-go"
)
func main() {
client := openguardrails.NewClient("your-api-key")
ctx := context.Background()
// Check single image (local file)
result, err := client.CheckPromptImage(ctx, "Is this image safe?", "/path/to/image.jpg")
if err != nil {
log.Fatal(err)
}
fmt.Println(result.OverallRiskLevel)
fmt.Println(result.SuggestAction)
// Check single image (network URL)
result, err = client.CheckPromptImage(ctx, "", "https://example.com/image.jpg")
if err != nil {
log.Fatal(err)
}
// Check multiple images
images := []string{
"/path/to/image1.jpg",
"https://example.com/image2.jpg",
"/path/to/image3.png",
}
result, err = client.CheckPromptImages(ctx, "Are all these images safe?", images)
if err != nil {
log.Fatal(err)
}
fmt.Println(result.OverallRiskLevel)
}// Synchronous client
config := &openguardrails.ClientConfig{
APIKey: "your-api-key",
BaseURL: "https://api.openguardrails.com/v1", // Optional, default cloud service
Timeout: 30, // Request timeout (seconds), default 30
MaxRetries: 3, // Maximum retry count, default 3
}
client := openguardrails.NewClientWithConfig(config)
// Async client (custom concurrency)
asyncClient := openguardrails.NewAsyncClientWithConfig(config, 20) // Max concurrency 20
defer asyncClient.Close()// Use default configuration
client := openguardrails.NewClient("your-api-key")
// Use custom configuration
config := &openguardrails.ClientConfig{
APIKey: "your-api-key",
BaseURL: "https://api.openguardrails.com/v1",
Timeout: 30,
MaxRetries: 3,
}
client := openguardrails.NewClientWithConfig(config)Check safety of a single prompt.
func (c *Client) CheckPrompt(ctx context.Context, content string) (*GuardrailResponse, error)
func (c *Client) CheckPromptWithModel(ctx context.Context, content, model string) (*GuardrailResponse, error)Parameters:
ctx(context.Context): Contextcontent(string): Content to checkmodel(string, optional): Model name, default "OpenGuardrails-Text"
Check safety of conversation context (recommended).
func (c *Client) CheckConversation(ctx context.Context, messages []*Message) (*GuardrailResponse, error)
func (c *Client) CheckConversationWithModel(ctx context.Context, messages []*Message, model string) (*GuardrailResponse, error)Parameters:
ctx(context.Context): Contextmessages([]*Message): Conversation message listmodel(string, optional): Model name
Check API service health status.
func (c *Client) HealthCheck(ctx context.Context) (map[string]interface{}, error)Get available model list.
func (c *Client) GetModels(ctx context.Context) (map[string]interface{}, error)// Use default configuration (concurrency 10)
asyncClient := openguardrails.NewAsyncClient("your-api-key")
defer asyncClient.Close()
// Use custom configuration and concurrency
config := &openguardrails.ClientConfig{
APIKey: "your-api-key",
BaseURL: "https://api.openguardrails.com/v1",
Timeout: 30,
MaxRetries: 3,
}
asyncClient := openguardrails.NewAsyncClientWithConfig(config, 20) // Max concurrency 20
defer asyncClient.Close()Asynchronously check safety of a single prompt.
func (ac *AsyncClient) CheckPromptAsync(ctx context.Context, content string) <-chan AsyncResult[*GuardrailResponse]
func (ac *AsyncClient) CheckPromptWithModelAsync(ctx context.Context, content, model string) <-chan AsyncResult[*GuardrailResponse]Return Value:
<-chan AsyncResult[*GuardrailResponse]: Asynchronous result channel
Example:
resultChan := asyncClient.CheckPromptAsync(ctx, "User question")
select {
case result := <-resultChan:
if result.Error != nil {
log.Printf("Detection failed: %v", result.Error)
} else {
fmt.Printf("Detection completed: %s\n", result.Result.OverallRiskLevel)
}
case <-ctx.Done():
fmt.Println("Detection cancelled")
}Asynchronously check safety of conversation context.
func (ac *AsyncClient) CheckConversationAsync(ctx context.Context, messages []*Message) <-chan AsyncResult[*GuardrailResponse]
func (ac *AsyncClient) CheckConversationWithModelAsync(ctx context.Context, messages []*Message, model string) <-chan AsyncResult[*GuardrailResponse]Batch asynchronous prompt checking (high performance).
func (ac *AsyncClient) BatchCheckPrompts(ctx context.Context, contents []string) <-chan AsyncResult[*GuardrailResponse]
func (ac *AsyncClient) BatchCheckPromptsWithModel(ctx context.Context, contents []string, model string) <-chan AsyncResult[*GuardrailResponse]Example:
contents := []string{"Content 1", "Content 2", "Content 3"}
resultChan := asyncClient.BatchCheckPrompts(ctx, contents)
for result := range resultChan {
if result.Error != nil {
log.Printf("Detection failed: %v", result.Error)
} else {
fmt.Printf("Batch detection result: %s\n", result.Result.OverallRiskLevel)
}
}Batch asynchronous conversation checking.
func (ac *AsyncClient) BatchCheckConversations(ctx context.Context, conversations [][]*Message) <-chan AsyncResult[*GuardrailResponse]
func (ac *AsyncClient) BatchCheckConversationsWithModel(ctx context.Context, conversations [][]*Message, model string) <-chan AsyncResult[*GuardrailResponse]func (ac *AsyncClient) GetConcurrency() int // Get concurrency limit
func (ac *AsyncClient) GetActiveWorkers() int // Get current active worker count
func (ac *AsyncClient) Close() error // Close async clienttype Message struct {
Role string `json:"role"` // "user", "system", "assistant"
Content string `json:"content"` // Message content
}
// Create new message
func NewMessage(role, content string) *Messagetype GuardrailResponse struct {
ID string `json:"id"` // Request unique identifier
Result *GuardrailResult `json:"result"` // Detection result details
OverallRiskLevel string `json:"overall_risk_level"` // Overall risk level
SuggestAction string `json:"suggest_action"` // Suggested action
SuggestAnswer *string `json:"suggest_answer"` // Suggested answer
Score *float64 `json:"score"` // Detection confidence score (added in v2.4.1)
}
// Convenience methods
func (r *GuardrailResponse) IsSafe() bool // Check if safe
func (r *GuardrailResponse) IsBlocked() bool // Check if blocked
func (r *GuardrailResponse) HasSubstitute() bool // Check if has replace answer
func (r *GuardrailResponse) GetAllCategories() []string // Get all risk categoriestype GuardrailResult struct {
Compliance *ComplianceResult `json:"compliance"` // Compliance detection result
Security *SecurityResult `json:"security"` // Security detection result
Data *DataResult `json:"data"` // Data leakage prevention detection result (added in v2.4.0)
}type ComplianceResult struct {
RiskLevel string `json:"risk_level"` // Risk level
Categories []string `json:"categories"` // Risk category list
}
type SecurityResult struct {
RiskLevel string `json:"risk_level"` // Risk level
Categories []string `json:"categories"` // Risk category list
}
type DataResult struct {
RiskLevel string `json:"risk_level"` // Risk level
Categories []string `json:"categories"` // Detected sensitive data types (added in v2.4.0)
}{
"id": "guardrails-xxx",
"result": {
"compliance": {
"risk_level": "no_risk", // no_risk/low_risk/medium_risk/high_risk
"categories": [] // Compliance risk categories
},
"security": {
"risk_level": "no_risk", // no_risk/low_risk/medium_risk/high_risk
"categories": [] // Security risk categories
},
"data": {
"risk_level": "no_risk", // no_risk/low_risk/medium_risk/high_risk (added in v2.4.0)
"categories": [] // Detected sensitive data types (added in v2.4.0)
}
},
"overall_risk_level": "no_risk", // Overall risk level
"suggest_action": "pass", // pass/reject/replace
"suggest_answer": null // Suggested answer (contains desensitized content when data leakage prevention is triggered)
}import (
"errors"
"https://github.com/openguardrails/openguardrails-go"
)
result, err := client.CheckPrompt(ctx, "test content")
if err != nil {
var authErr *openguardrails.AuthenticationError
var rateErr *openguardrails.RateLimitError
var validationErr *openguardrails.ValidationError
var networkErr *openguardrails.NetworkError
switch {
case errors.As(err, &authErr):
fmt.Printf("Authentication failed, please check API key: %v\n", err)
case errors.As(err, &rateErr):
fmt.Printf("Request rate too high, please try again later: %v\n", err)
case errors.As(err, &validationErr):
fmt.Printf("Invalid input parameters: %v\n", err)
case errors.As(err, &networkErr):
fmt.Printf("Network connection error: %v\n", err)
default:
fmt.Printf("API error: %v\n", err)
}
return
}
fmt.Println(result)OpenGuardrailsError- Base error classAuthenticationError- Authentication failureRateLimitError- Rate limit exceededValidationError- Input validation errorNetworkError- Network connection errorServerError- Server error
func moderateContent(client *openguardrails.Client, userContent string) error {
ctx := context.Background()
result, err := client.CheckPrompt(ctx, userContent)
if err != nil {
return err
}
if !result.IsSafe() {
categories := result.GetAllCategories()
fmt.Printf("Content contains risks: %v\n", categories)
return fmt.Errorf("content moderation failed: %s", result.OverallRiskLevel)
}
return nil
}func safeChatResponse(client *openguardrails.Client, conversation []*openguardrails.Message) (string, error) {
ctx := context.Background()
result, err := client.CheckConversation(ctx, conversation)
if err != nil {
return "", err
}
if result.SuggestAction == "replace" && result.SuggestAnswer != nil {
// Use safe replace answer
return *result.SuggestAnswer, nil
} else if result.IsBlocked() {
// Block unsafe conversation
return "Sorry, I cannot answer this question", nil
}
// Conversation is safe, continue normal process
return "", nil
}package main
import (
"context"
"net/http"
"github.com/gin-gonic/gin"
"https://github.com/openguardrails/openguardrails-go"
)
func GuardrailMiddleware(client *openguardrails.Client) gin.HandlerFunc {
return func(c *gin.Context) {
var req struct {
Content string `json:"content"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
c.Abort()
return
}
result, err := client.CheckPrompt(context.Background(), req.Content)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
c.Abort()
return
}
if result.IsBlocked() {
c.JSON(http.StatusForbidden, gin.H{
"error": "Content blocked",
"risk_level": result.OverallRiskLevel,
"categories": result.GetAllCategories(),
})
c.Abort()
return
}
c.Set("guardrail_result", result)
c.Next()
}
}package main
import (
"context"
"fmt"
"sync"
"https://github.com/openguardrails/openguardrails-go"
)
func batchCheck(client *openguardrails.Client, contents []string) {
var wg sync.WaitGroup
results := make(chan *openguardrails.GuardrailResponse, len(contents))
for _, content := range contents {
wg.Add(1)
go func(content string) {
defer wg.Done()
result, err := client.CheckPrompt(context.Background(), content)
if err != nil {
fmt.Printf("Detection failed: %v\n", err)
return
}
results <- result
}(content)
}
wg.Wait()
close(results)
for result := range results {
fmt.Printf("Content: %s, Risk Level: %s\n",
result.ID, result.OverallRiskLevel)
}
}func checkWithTimeout(client *openguardrails.Client, content string, timeout time.Duration) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
result, err := client.CheckPrompt(ctx, content)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
fmt.Println("Detection timeout")
} else {
fmt.Printf("Detection failed: %v\n", err)
}
return
}
fmt.Printf("Detection result: %s\n", result.SuggestAction)
}-
Use Conversation Context Detection: Recommend using
CheckConversationinstead ofCheckPrompt, as context awareness provides more accurate detection results. -
Context Management: Properly use
context.Contextfor timeout control and cancellation operations. -
Error Handling: Implement appropriate error handling and retry mechanisms.
-
Client Reuse: Reuse the same
Clientinstance in your application, avoid frequent creation. -
Concurrency Safety:
Clientis concurrency-safe and can be used simultaneously in multiple goroutines. -
Resource Management:
Clientinternally uses connection pooling and typically doesn't require manual closing.
- Default configuration optimized for most usage scenarios
- Supports connection reuse and keep-alive
- Automatic retry and exponential backoff
- Context cancellation support
Apache 2.0
- Website: https://openguardrails.com
- Documentation: https://docs.openguardrails.com
- Issue Reporting: https://github.com/openguardrails/openguardrails-go/issues
- Email: wanglei@openguardrails.com
Welcome to submit Issues and Pull Requests!