26 de set. de 2026
Coloque um guardrail tipado na frente de tool calls de agentes
Pergunte ao Jev se uma chamada de ferramenta proposta corresponde à intenção do usuário e quão destrutiva ela é, e deixe código simples decidir. Um passo a passo com montagem de state, thresholds e uma matriz de testes.
O modo de falha para o qual guardrails existem
Agentes falham de uma forma específica: emitem uma tool call que parece razoável localmente e é globalmente errada. Um SELECT em uma tabela de produção que era para ser de staging. Um DROP TABLE onde um DELETE estava implícito. Perguntar a um modelo de chat um segundo prompt — “isso é seguro?” — é lento, sem estrutura, e transforma sua política de segurança em texto livre que o próximo release pode mudar silenciosamente.
Um guardrail tipado faz três perguntas em vez disso: esta chamada corresponde ao que o usuário pediu (noul), um humano deve confirmar antes de executar (noul), e quão destrutiva ela é se for errada (score). As três cabem em uma única requisição, e cada resposta volta dentro do espaço de respostas que você definiu — sua política fica no código, não em prosa.
Montando o state
Envie a requisição do usuário e a chamada proposta como state. Aqui, um state em objeto lê melhor do que uma string longa, porque cada fato mantém seu nome e os criteria podem referenciá-los.
{
"state": {
"user_request": "Clean up the old test data in the staging database.",
"proposed_tool_call": {
"tool": "sql.execute",
"args": { "query": "DROP TABLE customers;" },
"environment": "production"
}
},
"questions": {
"matches_intent": {
"type": "noul",
"instructions": "Does `proposed_tool_call` match what `user_request` asked for?"
},
"needs_confirmation": {
"type": "noul",
"instructions": "Should a human confirm this tool call before it runs?",
"criteria": {
"true": "Touches live data, is destructive, or the environment does not match the request",
"false": "Read-only, staging-only, and exactly what was asked"
}
},
"risk": {
"type": "score",
"instructions": "How destructive is this action if it is wrong?",
"criteria": ["Harmless", "Recoverable", "Irreversible data loss"]
}
}
}Corpo da requisição do guardrailMantendo a política no seu código
O Jev apenas julga; ele nunca executa a ferramenta. Seu wrapper transforma probabilidades em ações:
const a = answers;
const must_confirm =
a.matches_intent.noul < 0.8 ||
a.needs_confirmation.noul > 0.7 ||
a.risk.score >= 1.5; // past "Recoverable", toward the red end
if (a.risk.score >= 2.0 && a.matches_intent.noul < 0.5) {
blockOrFlag(a.request_id); // never execute, log for review
} else if (must_confirm) {
confirmWith(a.request_id); // ask the human
} else {
execute(call);
}Política como códigoOs thresholds são seus para definir. 0.8 é uma linha de confiança razoável para começar o match de intenção; aperte-a para ferramentas irreversíveis (DROP, deploy, envio de e-mail) e afrouxe-a para as somente leitura. Rode dez exemplos reais do seu próprio tráfego — não casos de brinquedo — e mova um threshold apenas onde o modelo discorda do que você teria decidido de qualquer forma.
A matriz de testes antes de confiar nele
- Chamada benigna no ambiente certo — espere risco baixo, match de intenção alto, sem confirmação.
- Intenção certa, ambiente errado (pediram staging, chamou produção) — espere o match de intenção continuar alto e needs_confirmation subir. Leia a divergência honestamente: o modelo só pode sinalizar o que o state permitir que ele veja.
- Intenção errada, chamada inofensiva — espere needs_confirmation continuar baixo; inofensivo é inofensivo.
- Intenção errada, chamada destrutiva (o exemplo acima) — espere todos os sinais dispararem.
- Requisição do usuário ambígua — espere confiança baixa; encaminhe a um humano em vez de adivinhar.
Se um caso sair errado duas vezes, não ajuste um threshold para escondê-lo — reescreva o wording dos criteria, ou coloque no state o fato que falta (como o ambiente do chamador).
O custo na prática
Esse corpo de três perguntas pesa cerca de 350–500 tokens, confortavelmente dentro do mínimo de 1 crédito, então filtrar toda tool call custa $0.0001 por chamada no Starter e proporcionalmente menos nos pacotes maiores. A latência adiciona um round trip: 400–600 ms em medições típicas contra o gateway em produção. Isso é aceitável na maioria dos loops de agente. Se suas tool calls envolvem menos de 100 ms e cada milissegundo conta, filtre apenas as ferramentas cujo blast radius justifica — escritas no filesystem, SQL, pagamentos, e-mail — e deixe o restante passar.
Onde guardrails tipados deixam de funcionar
Seja claro sobre os limites: um modelo de guardrail não vê o que não está no state. Se você não incluir o ambiente de destino, ele não percebe o erro de ambiente. Ele também não substitui controles determinísticos — use allowlists, checagens de caminho e escopos de rede para aquilo em que são bons, e deixe a camada de decisão tipada tratar da pergunta semântica: este plano corresponde à requisição?
O Jev pode executar a tool call ele mesmo?
Não. Ele retorna apenas julgamentos — probabilidades sobre as perguntas que você fez. Seu código executa ou recusa. Essa separação é o que mantém a trilha de auditoria nas suas mãos.
Isso captura toda chamada perigosa?
Nenhum modelo é um sistema de segurança completo. Use o guardrail como uma camada. Ele é mais forte onde o perigo é semântico (divergência de intenção, confusão de ambiente). Mantenha regras determinísticas para allowlists e escopos, e mantenha um humano no caminho irreversível.
O playground tem este exemplo?
Sim — o preset Tool-call risk gate na página /playground é exatamente esse formato de requisição, gratuito para rodar.
Teste o playground do Jev AI para enviar sua primeira decisão gratuita depois de terminar este guia.