Guardrails

Validação de entrada/saída e segurança de conteúdo usando adk-guardrail.

Visão Geral

Guardrails validam e transformam as entradas e saídas do Agent para garantir segurança, conformidade e qualidade. Eles são executados em paralelo com a execução do Agent e podem:

  • Bloquear conteúdo prejudicial ou fora do tópico
  • Redigir PII (e-mails, telefones, SSNs, cartões de crédito)
  • Impor JSON schema nas saídas
  • Limitar o comprimento do conteúdo

Instalação

[dependencies]
adk-guardrail = "0.2.0"

# For JSON schema validation
adk-guardrail = { version = "0.2.0", features = ["schema"] }

Conceitos Centrais

GuardrailResult

Cada guardrail retorna um de três resultados:

pub enum GuardrailResult {
    Pass,                                    // O conteúdo é válido
    Fail { reason: String, severity: Severity },  // Conteúdo rejeitado
    Transform { new_content: Content, reason: String },  // Conteúdo modificado
}

Níveis de Severity

pub enum Severity {
    Low,      // Apenas aviso, não bloqueia
    Medium,   // Bloqueia, mas continua outras verificações
    High,     // Bloqueia imediatamente
    Critical, // Bloqueia e falha rapidamente
}

Redação de PII

Detecta e redige automaticamente informações de identificação pessoal:

use adk_guardrail::{PiiRedactor, PiiType};

// Padrão: e-mails, telefones, SSNs, cartões de crédito
let redactor = PiiRedactor::new();

// Ou selecione tipos específicos
let redactor = PiiRedactor::with_types(&[
    PiiType::Email,
    PiiType::Phone,
]);

// Redação direta
let (redacted, found_types) = redactor.redact("Email: test@example.com");
// redacted = "Email: [EMAIL REDACTED]"
// found_types = [PiiType::Email]

Tipos de PII Suportados:

TipoPadrãoRedação
Emailuser@domain.com[EMAIL REDACTED]
Phone555-123-4567[PHONE REDACTED]
Ssn123-45-6789[SSN REDACTED]
CreditCard4111-1111-1111-1111[CREDIT CARD REDACTED]
IpAddress192.168.1.1[IP REDACTED]

Filtragem de Conteúdo

Bloqueie conteúdo prejudicial ou imponha restrições de tópico:

use adk_guardrail::ContentFilter;

// Bloqueia padrões de conteúdo prejudicial
let filter = ContentFilter::harmful_content();

// Bloqueia palavras-chave específicas
let filter = ContentFilter::blocked_keywords(vec![
    "forbidden".into(),
    "banned".into(),
]);

// Garante relevância de tópico
let filter = ContentFilter::on_topic("cooking", vec![
    "recipe".into(),
    "cook".into(),
    "bake".into(),
]);

// Limita o comprimento do conteúdo
let filter = ContentFilter::max_length(1000);

Custom Content Filter

use adk_guardrail::{ContentFilter, ContentFilterConfig, Severity};

let config = ContentFilterConfig {
    blocked_keywords: vec!["spam".into()],
    required_topics: vec!["rust".into(), "programming".into()],
    max_length: Some(5000),
    min_length: Some(10),
    severity: Severity::High,
};

let filter = ContentFilter::new("custom_filter", config);

Validação de Schema

Impõe JSON schema nas saídas do Agent (requer o recurso schema):

use adk_guardrail::SchemaValidator;
use serde_json::json;

let schema = json!({
    "type": "object",
    "properties": {
        "name": { "type": "string" },
        "age": { "type": "integer", "minimum": 0 }
    },
    "required": ["name"]
});

let validator = SchemaValidator::new(&schema)?
    .with_name("user_schema")
    .with_severity(Severity::High);

O validator extrai JSON de:

  • Texto JSON bruto
  • Blocos de código Markdown (```json ... ```)

GuardrailSet

Combine vários guardrails:

use adk_guardrail::{GuardrailSet, ContentFilter, PiiRedactor};

let guardrails = GuardrailSet::new()
    .with(ContentFilter::harmful_content())
    .with(ContentFilter::max_length(5000))
    .with(PiiRedactor::new());

GuardrailExecutor

Execute guardrails e obtenha resultados detalhados:

use adk_guardrail::{GuardrailExecutor, GuardrailSet, PiiRedactor};
use adk_core::Content;

let guardrails = GuardrailSet::new()
    .with(PiiRedactor::new());

let content = Content::new("user")
    .with_text("Contact: test@example.com");

let result = GuardrailExecutor::run(&guardrails, &content).await?;

if result.passed {
    // Use transformed content if available
    let final_content = result.transformed_content.unwrap_or(content);
    println!("Content passed validation");
} else {
    for (name, reason, severity) in &result.failures {
        println!("Guardrail '{}' failed: {} ({:?})", name, reason, severity);
    }
}

ExecutionResult

pub struct ExecutionResult {
    pub passed: bool,                              // Aprovação/reprovação geral
    pub transformed_content: Option<Content>,      // Conteúdo modificado (se houver)
    pub failures: Vec<(String, String, Severity)>, // (nome, razão, severidade)
}

Guardrails Personalizados

Implemente o trait Guardrail:

use adk_guardrail::{Guardrail, GuardrailResult, Severity};
use adk_core::Content;
use async_trait::async_trait;

pub struct ProfanityFilter {
    words: Vec<String>,
}

#[async_trait]
impl Guardrail for ProfanityFilter {
    fn name(&self) -> &str {
        "profanity_filter"
    }

    async fn validate(&self, content: &Content) -> GuardrailResult {
        let text: String = content.parts
            .iter()
            .filter_map(|p| p.text())
            .collect();

        for word in &self.words {
            if text.to_lowercase().contains(word) {
                return GuardrailResult::Fail {
                    reason: format!("Contains profanity: {}", word),
                    severity: Severity::High,
                };
            }
        }

        GuardrailResult::Pass
    }

    // Executar em paralelo com outros guardrails (padrão: true)
    fn run_parallel(&self) -> bool {
        true
    }

    // Falhar rapidamente na falha deste guardrail (padrão: true)
    fn fail_fast(&self) -> bool {
        true
    }
}

Integração com Agentes

Guardrails se integram com LlmAgentBuilder:

use adk_agent::LlmAgentBuilder;
use adk_guardrail::{GuardrailSet, ContentFilter, PiiRedactor};

let input_guardrails = GuardrailSet::new()
    .with(ContentFilter::harmful_content())
    .with(PiiRedactor::new());

let output_guardrails = GuardrailSet::new()
    .with(SchemaValidator::new(&output_schema)?);

let agent = LlmAgentBuilder::new("assistant")
    .model(model)
    .instruction("You are a helpful assistant.")
    .input_guardrails(input_guardrails)
    .output_guardrails(output_guardrails)
    .build()?;

Fluxo de Execução

Entrada do Usuário
    │
    ▼
┌─────────────────────┐
│  Guardrails de Entrada │ ← Redação de PII, filtragem de conteúdo
│  (paralelo)         │
└─────────────────────┘
    │
    ▼ (transformado ou bloqueado)
┌─────────────────────┐
│  Execução do Agente    │
└─────────────────────┘
    │
    ▼
┌─────────────────────┐
│  Guardrails de Saída  │ ← Validação de esquema, verificações de segurança
│  (paralelo)         │
└─────────────────────┘
    │
    ▼
Resposta Final

Exemplos

# Filtragem básica de PII e conteúdo
cargo run --example guardrail_basic --features guardrails

# Validação de esquema JSON
cargo run --example guardrail_schema --features guardrails

# Integração completa do agente
cargo run --example guardrail_agent --features guardrails

Melhores Práticas

PráticaDescrição
Camadas de guardrailsUse guardrails de entrada para segurança, de saída para qualidade
PII na entradaRedija PII antes que chegue ao modelo
Schema na saídaValide saídas estruturadas com JSON schema
Severidade apropriadaUse Critical com moderação, Low para avisos
Teste exaustivamenteGuardrails são código crítico de segurança

Anterior: ← Controle de Acesso | Próximo: Memória →