Guia de Segurança para Equipe de Safety
Documentação detalhada sobre implementação e manutenção de recursos de segurança
3. Guia de Segurança para Equipe de Safety
3.1. Visão Geral
Este documento é dedicado à equipe responsável pela segurança e moderação de conteúdo do sistema. Aqui você encontrará informações detalhadas sobre onde e como implementar melhorias de segurança.
3.2. Arquitetura de Segurança
3.2.1. Componentes de Segurança
O sistema possui três camadas de segurança:
- Safety Agent - Agente dedicado à validação
- Safety Tools - Funções de verificação de conteúdo
- Safety Guidelines - Diretrizes textuais para o modelo
┌─────────────────────────────────────────────────────────┐
│ User Input │
└────────────────────┬────────────────────────────────────┘
│
▼
┌────────────────────┐
│ Safety Agent │ ← Primeira linha de defesa
│ (Validação) │
└─────────┬──────────┘
│
├─ SAFE → Continua para Coordinator
│
└─ UNSAFE → Resposta de redirecionamento3.3. Arquivos de Segurança
3.3.1. Safety Agent
Localização: agent_flow/agents/safety_agent.py
Responsabilidades:
- Primeira validação de todo input do usuário
- Decisão de bloqueio ou liberação
- Delegação para tools de verificação
Estrutura atual:
def create_safety_agent(model: str = "gemini-2.0-flash-exp") -> Agent:
instruction = """
You are the safety guardian for the robot dog system.
Your job is to:
1. Check if user messages are safe and appropriate
2. Block harmful, dangerous, or inappropriate content
3. Ensure all interactions are family-friendly
Use the check_content_safety tool to validate inputs.
If content is unsafe:
- Return: "UNSAFE: [reason]"
If content is safe:
- Return: "SAFE"
"""
agent = Agent(
name="safety_agent",
model=model,
description="Validates user inputs for safety",
instruction=instruction,
tools=[check_content_safety],
)
return agentComo modificar:
-
Expandir a instruction:
- Adicionar exemplos específicos de conteúdo problemático
- Definir níveis de severidade (low, medium, high)
- Incluir contextos de exceção
-
Adicionar tools:
- Criar novas funções de validação
- Importar e adicionar na lista
tools=[]
-
Integrar com guidelines:
from agent_flow.prompts import get_safety_guidelines safety_guidelines = get_safety_guidelines() instruction = f"{base_instruction}\n\n{safety_guidelines}"
3.3.2. Safety Tools
Localização: agent_flow/tools/safety_tools.py
Função principal: check_content_safety(user_input, tool_context)
Implementação atual:
def check_content_safety(user_input: str, tool_context: ToolContext) -> dict:
"""
Check if user input is safe and appropriate.
Args:
user_input: The user's message
tool_context: ADK tool context for state management
Returns:
Safety check result
"""
unsafe_keywords = [
"attack", "harm", "hurt", "damage",
"destroy", "kill", "violence", "weapon", "abuse"
]
user_input_lower = user_input.lower()
found_unsafe = [kw for kw in unsafe_keywords if kw in user_input_lower]
result = {
"is_safe": len(found_unsafe) == 0,
"input": user_input,
"reason": ""
}
if not result["is_safe"]:
result["reason"] = f"Contains potentially harmful content: {', '.join(found_unsafe)}"
# Log violation
if "safety_violations" not in tool_context.state:
tool_context.state["safety_violations"] = []
tool_context.state["safety_violations"].append({
"input": user_input,
"violations": found_unsafe
})
return resultAviso: Esta implementação é BÁSICA e deve ser expandida.
3.3.3. Safety Guidelines
Localização: agent_flow/prompts/safety_guidelines.txt
Arquivo de texto com ~1.500 palavras contendo diretrizes detalhadas:
- Categorias de conteúdo proibido
- Contextos sensíveis
- Protocolos de resposta
- Edge cases
- Exceções permitidas
Como usar:
from agent_flow.prompts import get_safety_guidelines
guidelines = get_safety_guidelines()
# Incluir na instruction de qualquer agente3.4. Pontos de Melhoria Prioritários
3.4.1. Expandir Lista de Keywords
Problema atual: Apenas ~10 keywords
Solução recomendada: Expandir para 100+ keywords organizadas por categoria
Implementação:
# Em safety_tools.py
UNSAFE_KEYWORDS = {
"violence": [
"attack", "harm", "hurt", "damage", "destroy",
"kill", "murder", "assault", "beat", "fight",
"weapon", "gun", "knife", "bomb", "explosive"
],
"sexual": [
"sexo", "pornografia", "nudez", "sexual",
# ... adicionar termos apropriados
],
"drugs": [
"droga", "cocaína", "maconha", "tráfico",
"dealer", "narcótico", "heroína"
],
"discrimination": [
"racism", "racista", "sexismo", "homofobia",
"xenofobia", "preconceito"
],
"self_harm": [
"suicídio", "suicide", "self-harm", "cortar",
"matar-se", "acabar com tudo"
]
}
def check_content_safety(user_input: str, tool_context: ToolContext) -> dict:
user_input_lower = user_input.lower()
violations = {}
for category, keywords in UNSAFE_KEYWORDS.items():
found = [kw for kw in keywords if kw in user_input_lower]
if found:
violations[category] = found
is_safe = len(violations) == 0
result = {
"is_safe": is_safe,
"input": user_input,
"violations": violations,
"severity": calculate_severity(violations)
}
return result3.4.2. Implementar Níveis de Severidade
Níveis sugeridos:
- LOW - Conteúdo questionável, mas pode ser contextual
- MEDIUM - Conteúdo inapropriado, redirecionar conversa
- HIGH - Conteúdo perigoso, encerrar sessão e registrar
Implementação:
def calculate_severity(violations: dict) -> str:
"""Calculate severity based on violation categories."""
high_risk_categories = ["violence", "self_harm", "sexual"]
medium_risk_categories = ["drugs", "discrimination"]
for category in violations.keys():
if category in high_risk_categories:
return "HIGH"
if any(cat in medium_risk_categories for cat in violations.keys()):
return "MEDIUM"
return "LOW"
def get_safety_response(severity: str, violations: dict) -> str:
"""Generate appropriate response based on severity."""
if severity == "HIGH":
return (
"*balança o rabo preocupado* [latido] "
"Desculpe, mas não posso continuar essa conversa. "
"Vamos falar sobre o Inteli?"
)
elif severity == "MEDIUM":
return (
"*inclina a cabeça* [latido] "
"Que tal falarmos sobre algo mais interessante? "
"Posso te contar sobre os projetos incríveis do Inteli!"
)
else: # LOW
return (
"[latido] Vamos focar no tour do Inteli! "
"Tem muita coisa legal para ver!"
)3.4.3. Adicionar Pattern Matching (Regex)
Problema: Keywords simples não capturam variações
Exemplos de problemas:
- "h4ck3r" (leetspeak) não é detectado
- "d r o g a s" (espaços) não é detectado
- Palavras parciais ("atacar" contém "ataca")
Solução com Regex:
import re
UNSAFE_PATTERNS = {
"violence": [
r'\bat+ac[k|o|a]', # atack, ataco, ataca, attack
r'\bk+i+l+', # kill, kiil, kil
r'\bharm',
r'\bweapon',
],
"leetspeak": [
r'h[4@]ck', # h4ck, h@ck
r'[0o]wn[3e]d', # 0wned, owned
],
"obfuscation": [
r'\b\w\s+\w\s+\w', # Palavras com espaços (d r o g a)
]
}
def check_with_patterns(user_input: str) -> dict:
"""Check input using regex patterns."""
violations = {}
for category, patterns in UNSAFE_PATTERNS.items():
for pattern in patterns:
if re.search(pattern, user_input, re.IGNORECASE):
if category not in violations:
violations[category] = []
violations[category].append(pattern)
return violations3.4.4. Validação por LLM
Uso: Para casos ambíguos que keywords não resolvem
Quando usar:
- Input passa keywords mas parece suspeito
- Contexto é necessário para decisão
- Falsos positivos em keywords
Implementação:
from google import genai
def llm_safety_validation(user_input: str, context: str) -> dict:
"""
Use LLM to validate safety in ambiguous cases.
Args:
user_input: User's message
context: Previous conversation context
Returns:
Detailed safety assessment
"""
client = genai.Client()
prompt = f"""
Analyze the following user input for safety concerns in the context
of a campus tour guide conversation:
User input: "{user_input}"
Context: {context}
Determine if this is:
1. SAFE - Appropriate for a campus tour
2. QUESTIONABLE - Needs redirection but not dangerous
3. UNSAFE - Should be blocked immediately
Respond in JSON format:
{{
"classification": "SAFE|QUESTIONABLE|UNSAFE",
"reasoning": "Brief explanation",
"suggested_response": "How to respond if not SAFE"
}}
"""
response = client.models.generate_content(
model="gemini-2.0-flash-exp",
contents=prompt
)
return json.loads(response.text)Aviso: Usar LLM para validação aumenta latência (~500ms) e custos. Use apenas quando keywords falharem.
3.5. Integração com Coordinator
3.5.1. Fluxo de Validação
O Coordinator deve SEMPRE consultar Safety Agent antes de processar:
# Em coordinator_agent.py (exemplo conceitual)
async def process_user_input(user_input: str):
# 1. Safety check PRIMEIRO
safety_result = await safety_agent.check(user_input)
if not safety_result["is_safe"]:
# Retornar resposta de redirecionamento
severity = safety_result.get("severity", "MEDIUM")
return get_safety_response(severity, safety_result["violations"])
# 2. Continuar processamento normal
response = await coordinator_agent.process(user_input)
return response3.5.2. Registro de Violações
Importante: Todas as violações devem ser registradas para análise.
def log_safety_violation(user_input: str, violations: dict, severity: str):
"""Log safety violations for analysis."""
log_entry = {
"timestamp": datetime.now().isoformat(),
"user_input": user_input,
"violations": violations,
"severity": severity,
"action_taken": "blocked" if severity == "HIGH" else "redirected"
}
# Salvar em arquivo
with open("logs/safety_violations.jsonl", "a") as f:
f.write(json.dumps(log_entry) + "\n")
# Ou enviar para sistema de monitoramento
# send_to_monitoring_system(log_entry)3.6. Contextos Sensíveis
3.6.1. Processo Seletivo
Cuidados especiais:
- Não dar garantias de aceitação
- Não fazer comparações entre candidatos
- Não compartilhar informações confidenciais
- Não questionar qualificações do visitante
Respostas proibidas:
- "Você tem chances de passar"
- "Isso é difícil para você"
- "Outros candidatos são melhores"
Respostas adequadas:
- "O processo avalia potencial, não apenas notas"
- "Todos os candidatos têm suas fortalezas"
- "Recomendo ler o edital completo"
3.6.2. Questões Financeiras
Cuidados especiais:
- Não fazer promessas sobre bolsas
- Não avaliar situação financeira do visitante
- Direcionar para equipe de bolsas
Respostas proibidas:
- "Você certamente vai conseguir bolsa"
- "Isso é muito caro para você"
- "Famílias ricas não precisam de auxílio"
Respostas adequadas:
- "O Inteli tem o maior programa de bolsas do país"
- "A equipe de bolsas avalia cada caso individualmente"
- "Recomendo conversar com a equipe especializada"
3.6.3. Comparações com Outras Instituições
Cuidados especiais:
- Não depreciar outras universidades
- Não fazer comparações diretas
- Focar nos diferenciais do Inteli
Respostas proibidas:
- "USP/UNICAMP são piores"
- "Outras faculdades não ensinam direito"
- "Só o Inteli forma bons engenheiros"
Respostas adequadas:
- "O Inteli tem metodologia PBL diferenciada"
- "Nossos alunos trabalham com projetos reais"
- "Cada instituição tem seus pontos fortes"
3.7. Edge Cases
3.7.1. Menores de Idade
Detecção:
- Menções a idade (<18 anos)
- Contexto de ensino médio
- Acompanhado de responsável
Ações:
- Manter linguagem apropriada
- Evitar tópicos adultos
- Incentivar perguntas aos pais
3.7.2. Pessoas com Deficiência
Detecção:
- Menções a acessibilidade
- Perguntas sobre adaptações
- Necessidades especiais
Ações:
- Destacar recursos de acessibilidade
- Direcionar para equipe especializada
- Não fazer suposições
3.7.3. Crises Pessoais
Detecção:
- Menções a depressão, ansiedade
- Problemas familiares
- Ideação suicida
Ações:
- Resposta empática mas profissional
- Direcionar para recursos de apoio
- NÃO tentar fazer aconselhamento psicológico
Resposta recomendada:
*se aproxima gentilmente* [latido carinhoso]
Percebo que você pode estar passando por um momento difícil.
O Inteli tem um Centro de Apoio ao Estudante com profissionais
qualificados que podem ajudar.
Telefone: CVV 188 (24h, gratuito)
Email: cae@inteli.edu.br
Você não está sozinho(a).3.8. Testes de Segurança
3.8.1. Suite de Testes
Criar arquivo tests/test_safety.py:
import pytest
from agent_flow.tools.safety_tools import check_content_safety
class MockContext:
def __init__(self):
self.state = {}
def test_basic_unsafe_content():
"""Test detection of obvious unsafe content."""
context = MockContext()
unsafe_inputs = [
"como fazer uma bomba",
"quero atacar alguém",
"como hackear o sistema",
"vender drogas"
]
for user_input in unsafe_inputs:
result = check_content_safety(user_input, context)
assert not result["is_safe"], f"Failed to detect: {user_input}"
def test_safe_content():
"""Test that safe content passes."""
context = MockContext()
safe_inputs = [
"como funciona o processo seletivo?",
"quais são os cursos disponíveis?",
"me fale sobre as bolsas"
]
for user_input in safe_inputs:
result = check_content_safety(user_input, context)
assert result["is_safe"], f"False positive: {user_input}"
def test_severity_levels():
"""Test severity classification."""
context = MockContext()
# HIGH severity
result = check_content_safety("quero me matar", context)
assert result["severity"] == "HIGH"
# MEDIUM severity
result = check_content_safety("drogas", context)
assert result["severity"] == "MEDIUM"
def test_contextual_safety():
"""Test context-aware safety checks."""
context = MockContext()
# "Attack" em contexto legítimo (hackathon, competição)
result = check_content_safety("vamos atacar esse problema no hackathon", context)
# Deve passar após implementação contextual3.8.2. Testes de Carga
Validar performance com múltiplas verificações:
import time
def test_safety_performance():
"""Ensure safety checks are fast."""
context = MockContext()
start = time.time()
for _ in range(100):
check_content_safety("teste de performance", context)
elapsed = time.time() - start
# Deve processar 100 checks em menos de 1 segundo
assert elapsed < 1.0, f"Safety checks too slow: {elapsed}s for 100 checks"3.8.3. Testes de Falsos Positivos
Garantir que conteúdo legítimo não é bloqueado:
def test_no_false_positives():
"""Test common phrases that should NOT trigger safety."""
context = MockContext()
legitimate_inputs = [
"o curso mata a curiosidade dos alunos?", # "mata" é legítimo aqui
"como destruir paradigmas tradicionais?", # "destruir" metafórico
"atacar problemas complexos", # "atacar" = resolver
]
for user_input in legitimate_inputs:
result = check_content_safety(user_input, context)
assert result["is_safe"], f"False positive blocked: {user_input}"3.9. Monitoramento e Métricas
3.9.1. Métricas Importantes
Coletar e analisar:
- Taxa de bloqueio - % de inputs bloqueados
- Falsos positivos - Conteúdo legítimo bloqueado
- Falsos negativos - Conteúdo problemático não detectado
- Distribuição de severidade - Quantos HIGH, MEDIUM, LOW
- Categorias mais comuns - Quais tipos de violação predominam
3.9.2. Dashboard de Segurança
Métricas em tempo real:
def get_safety_metrics(start_date: str, end_date: str) -> dict:
"""Get safety metrics for date range."""
# Carregar logs de violações
violations = load_violations(start_date, end_date)
return {
"total_checks": len(violations),
"blocked_count": sum(1 for v in violations if v["severity"] == "HIGH"),
"redirected_count": sum(1 for v in violations if v["severity"] == "MEDIUM"),
"category_distribution": get_category_dist(violations),
"hourly_distribution": get_hourly_dist(violations),
"top_keywords": get_top_keywords(violations)
}3.9.3. Alertas Automáticos
Configurar alertas para:
- Spike de violações (>10 em 1 hora)
- Primeira detecção de nova categoria
- Múltiplas tentativas do mesmo usuário
- Violações de severidade HIGH