Guardrails para agentes de IA: validando o que entra e o que sai
Um agente sem guardrails é um estagiário com acesso de admin e nenhuma supervisão. Funciona até o dia em que não funciona. E quando não funciona, não é um bug bonitinho no log: é um e-mail enviado pro cliente errado, um registro deletado, um dado sensível vazado na resposta.
Guardrails para agentes são as cercas que você coloca em volta do modelo: validam o que entra, restringem o que as ferramentas podem fazer e checam o que sai antes de devolver pro usuário. Não é firula de compliance. É a diferença entre um agente que você deixa rodar em produção e um que fica preso eternamente no "demo na minha máquina".
Neste post você vai ver os três tipos de guardrail, onde encaixar cada um no fluxo do agente e como implementar isso com código que roda — não com slide de arquitetura.
TL;DR
- O que é: camadas de validação que cercam um agente de IA — na entrada, nas ferramentas e na saída.
- Por que importa: modelo é não-determinístico. Sem cerca, qualquer entrada estranha ou alucinação vira ação real no seu sistema.
- Stack/Modelos: exemplos em Python com o OpenAI Agents SDK; o conceito vale para qualquer stack (Laravel, Node, o que for).
- Custo/Acesso: padrão de arquitetura, não produto. Você implementa com o que já tem.
O que são guardrails para agentes (e por que o nome confunde)
Pequeno aviso de SEO e de vida: se você jogar "guardrails" puro no Google, vai cair em barreira de estrada e defensa metálica. O termo cru é dominado por engenharia civil. Quando a gente fala de guardrails para agentes, está falando de outra coisa: controles programáticos que cercam um modelo de linguagem para garantir que ele só faça o que deveria.
A ideia é velha em engenharia de software. Você nunca confiou em input de usuário. Validou formulário, sanitizou query, checou permissão antes de executar. Guardrail de agente é o mesmo princípio aplicado a um componente novo e estranho: um modelo que é não-determinístico por natureza.
E é aí que muita gente erra. Trata o LLM como se fosse uma função pura — entra texto, sai texto, confia no resultado. Não é. O modelo pode alucinar, interpretar mal a intenção, ser manipulado por uma entrada maliciosa. A Anthropic descreve tools como "contratos entre sistemas determinísticos e agentes não-determinísticos" — e o trabalho do guardrail é fazer esse contrato valer mesmo quando o agente tenta furá-lo.
As três cercas: entrada, ferramentas e saída
Pensa no agente como um processo com três fronteiras. Cada fronteira pede um tipo de guardrail.
- Entrada (input guardrail). Roda antes do modelo começar a processar. Protege o agente do usuário — pega tentativa de jailbreak, PII no prompt, pedido fora de escopo.
- Ferramentas (tool guardrail). Roda toda vez que o agente chama uma function tool. Restringe o que aquela ação pode fazer e valida os argumentos antes da execução.
- Saída (output guardrail). Roda depois que o agente gerou a resposta, antes de entregar. Protege o usuário do agente — segura vazamento de dado, formato inválido, conteúdo que não devia sair.
O OpenAI Agents SDK organiza exatamente assim: input guardrails "protegem seu agente dos usuários" e output guardrails "protegem os usuários do seu agente". As três cercas são independentes. Você pode ter uma forte e duas fracas — e é justamente aí que o agente se queima.
Guardrail de entrada: validando o que chega
A entrada é a primeira linha de defesa. Tudo que chega no agente é potencialmente hostil: um prompt tentando sobrescrever as instruções, dado de cliente que não devia estar ali, ou só um pedido completamente fora do que o agente deveria atender.
Um guardrail de entrada pode ser de dois tipos:
- Baseado em regra — regex, limite de tamanho, lista de termos proibidos. Barato, rápido, determinístico.
- Baseado em LLM — um modelo pequeno e barato classifica a intenção da entrada (isso é jailbreak? isso é off-topic?). Mais caro, mas pega coisa que regex não pega.
No Agents SDK, o guardrail devolve um GuardrailFunctionOutput. Se ele marcar tripwire_triggered=True, o SDK levanta uma exceção (InputGuardrailTripwireTriggered) e interrompe a execução na hora — antes de gastar um token sequer no modelo principal:
from agents import (
Agent, Runner, GuardrailFunctionOutput,
input_guardrail, RunContextWrapper, TResponseInputItem,
)
@input_guardrail
async def jailbreak_guardrail(
ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
# guardrail_agent é um modelo pequeno e barato que só classifica a intenção
result = await Runner.run(guardrail_agent, input, context=ctx.context)
return GuardrailFunctionOutput(
output_info=result.final_output,
tripwire_triggered=result.final_output.is_jailbreak_attempt,
)
support_agent = Agent(
name="Suporte",
instructions="Você é o agente de suporte da loja...",
input_guardrails=[jailbreak_guardrail],
)
Sacou o detalhe? O guardrail roda antes do agente caro. Se a entrada é lixo, você corta ali e economiza a chamada inteira. Guardrail de entrada não é só segurança — é controle de custo.
Guardrail de ferramentas: restringindo o que o agente pode fazer
Aqui mora o perigo de verdade. Input e output são texto. Ferramenta é ação no mundo real: query no banco, chamada de API, envio de e-mail, transferência de dinheiro.
A regra de ouro é o velho least privilege. O agente só pode chamar as ferramentas que a tarefa exige, e cada ferramenta valida seus próprios argumentos. Um tool guardrail envolve a function tool e roda toda vez que ela é invocada — checando os argumentos antes da execução e, se preciso, o resultado depois.
@function_tool
async def reembolsar(ctx, order_id: str, valor_centavos: int) -> str:
# guardrail dentro da própria tool: o agente pode pedir,
# mas a regra de negócio decide se executa
if valor_centavos > 50_000:
raise ValueError("Reembolso acima de R$500 exige aprovação humana")
if not pedido_pertence_ao_usuario(ctx.context.user_id, order_id):
raise PermissionError("Pedido não pertence a este usuário")
return processar_reembolso(order_id, valor_centavos)
Repara que a permissão (user_id) vem do contexto da requisição, não do que o agente disse. Isso é fundamental: nunca deixe o modelo decidir de quem é o pedido. Amarre identidade e permissão na borda, fora do alcance do prompt.
Para ações de alto risco, o padrão é human-in-the-loop: o agente pausa e pede aprovação antes de executar algo irreversível — transação financeira, deletar dado, mandar comunicação externa. Mas tem um detalhe contraintuitivo aqui. A Anthropic relatou no re:Invent 2025 que desenvolvedores aprovam 93% dos prompts de permissão — e que, a centenas de ações por sessão, a aprovação por ação vira fadiga de consentimento. Você clica "aprovar" no automático e o checkpoint perde o sentido.
A lição: não peça aprovação pra tudo. Case o nível de supervisão ao risco da ação. Tarefa de baixo risco roda sozinha. Ação irreversível pausa e pede confirmação de verdade. Um checkpoint que dispara o tempo todo é igual a checkpoint nenhum. É a mesma régua que separa os 4 níveis de autonomia em agentic code: não é o que o agente faz, é quem aprova, quem reverte e quem audita cada ação.
Guardrail de saída: checando o que volta
O modelo terminou, gerou a resposta. Antes de mandar pro usuário, mais uma cerca. O output guardrail protege o usuário (e a sua empresa) do que o agente acabou de produzir.
Dois usos clássicos:
- Vazamento de dado. O agente puxou informação de um sistema interno e enfiou na resposta sem perceber. O guardrail de saída checa antes de entregar.
- Formato. Se a resposta tem que ser um JSON com campos específicos, valida o schema. Saída malformada não chega no front.
A mecânica é simétrica à da entrada — tripwire_triggered, exceção (OutputGuardrailTripwireTriggered), execução interrompida:
from pydantic import BaseModel
from agents import output_guardrail, GuardrailFunctionOutput
class RespostaSuporte(BaseModel):
mensagem: str
contem_dado_sensivel: bool
@output_guardrail
async def vazamento_guardrail(
ctx, agent, output: RespostaSuporte
) -> GuardrailFunctionOutput:
return GuardrailFunctionOutput(
output_info=output,
tripwire_triggered=output.contem_dado_sensivel,
)
Validar saída com um schema tipado (Pydantic, Zod, o que sua stack tiver) resolve metade dos problemas de graça. O agente é forçado a devolver uma estrutura, e o que não bate é rejeitado antes de virar resposta.
Limitações e pontos de atenção
Guardrail não é bala de prata. Onde você se queima:
- Nenhuma cerca isolada basta. Proteção de verdade é em camadas — entrada, ferramentas, identidade, acesso a dado e saída. Quem confia só no prompt de sistema ("não faça X") já perdeu. Prompt é sugestão, não controle.
- Guardrail de LLM custa e adiciona latência. Cada classificador é uma chamada de modelo a mais. Para coisa simples, regra/regex é melhor: mais rápido, determinístico, de graça. Use o modelo só onde a regra não alcança.
- Falso positivo irrita o usuário. Cerca muito agressiva bloqueia pedido legítimo. Você vai ter que medir, ajustar threshold e olhar os logs do que foi barrado. Guardrail sem observabilidade é chute.
- Argumento de tool é tão suspeito quanto input de usuário. O agente pode alucinar um
order_idou um valor. Valide os argumentos da ferramenta com o mesmo rigor que você valida um formulário.
FAQ rápido
Preciso de uma lib de guardrails ou dá pra fazer na mão? Dá pra fazer na mão, e na maioria dos casos é o certo. Guardrail é validação de entrada, checagem de permissão e validação de schema — coisas que você já faz. Lib ajuda quando você quer classificadores prontos (PII, toxicidade, jailbreak) sem treinar nada.
Guardrail de entrada não deixa o agente mais lento? Se for baseado em regra, o custo é desprezível. Se for um classificador LLM, sim, adiciona uma chamada. Mas roda antes do modelo principal e corta entrada ruim cedo — muitas vezes economiza mais do que custa.
Onde a maioria dos times erra primeiro? Na ferramenta. Investe em filtrar entrada e saída, mas deixa a tool executar qualquer argumento que o agente mandar. É o ponto onde o estrago é real — porque ali vira ação, não texto.
Isso vale só pra Python / OpenAI SDK? Não. O SDK é uma forma concreta de mostrar o padrão. As três cercas — entrada, ferramentas, saída — valem em qualquer stack. Em Laravel você faz com Form Requests, Policies e validação de DTO. O conceito é agnóstico.
Conclusão
Agente em produção não é um modelo solto respondendo prompt. É um sistema com fronteiras, e cada fronteira pede uma cerca: valida o que entra, restringe o que as ferramentas fazem, checa o que sai. As três juntas. Nenhuma sozinha.
O próximo passo é parar de tratar guardrail como item de checklist de segurança e começar a tratá-lo como parte da arquitetura — decidido no desenho do agente, não remendado depois do primeiro incidente. É exatamente esse tipo de decisão de arquitetura que a gente coloca na mesa no Workshop Arquitetando Soluções de IA: como desenhar soluções de software com agentes que aguentam produção, do fluxo às cercas.
Porque, no fim, a diferença entre o estagiário com acesso de admin e um engenheiro de confiança não é inteligência. É supervisão bem colocada.
{AI Engineer} — apaixonado por Laravel, arquitetura de software e construir produtos com impacto. Compartilho aqui tutoriais, descobertas e reflexões sobre o dia a dia de engenharia.