TL;DR
Você para de supervisionar agentes de IA construindo três coisas: guardrails (restrições que impedem falhas catastróficas), observabilidade (logs e métricas que informam o que aconteceu) e checkpoints (pausas automáticas onde humanos verificam decisões). Configure-os uma vez, e seus agentes poderão rodar autonomamente por horas em vez de minutos. Ferramentas como o Apidog ajudam, permitindo que você defina contratos de API que os agentes não podem violar, transformando sua camada de API em uma rede de segurança.
Introdução
Na semana passada, observei um desenvolvedor passar 4 horas supervisionando um agente de IA que deveria economizar seu tempo. A cada poucos minutos, ele o interrompia, corrigia um erro e reiniciava. No final, ele havia feito mais trabalho manual do que se tivesse escrito o código ele mesmo.
Este é o problema da supervisão constante (babysitting problem), e é a principal razão pela qual os agentes de IA não cumprem suas promessas. As ferramentas funcionam. Os modelos são capazes. Mas a maioria das equipes nunca supera a fase de supervisão constante.
O que está acontecendo é o seguinte: a maioria das configurações de agentes de IA trata o LLM como um desenvolvedor júnior que precisa de acompanhamento em cada tarefa. Mas os LLMs não são juniores. Eles são mais como estagiários extremamente rápidos e ocasionalmente alucinantes que farão a coisa errada com confiança se você não definir limites.
Defina contratos de API que seus agentes de IA podem seguir
Ao final deste guia, você terá:
- Um modelo mental para pensar sobre a autonomia do agente
- Padrões concretos para guardrails, observabilidade e checkpoints
- Exemplos de código que você pode copiar para seus projetos hoje
- Uma lista de verificação para avaliar se um agente está pronto para rodar sem supervisão
Por que os agentes precisam de supervisão constante
Agentes de IA falham de maneiras previsíveis. Compreender esses modos de falha é o primeiro passo para corrigi-los.
Modo de falha 1: Expansão de escopo (Scope creep)
Você pede a um agente para “adicionar autenticação ao endpoint da API.” Ele adiciona autenticação. Em seguida, adiciona limitação de taxa (rate limiting). Depois, refatora o esquema do banco de dados. Em seguida, exclui o que ele pensa serem arquivos “não utilizados”, que acabam sendo importantes.
O agente continuou porque ninguém o mandou parar. LLMs não têm um senso inato de “pronto”. Eles continuarão fazendo alterações até atingirem um limite de tokens ou você os interromper.
Modo de falha 2: Abstrações incorretas
Um agente encarregado de “melhorar o tratamento de erros” pode adicionar blocos try-catch em todos os lugares. Tecnicamente correto. Praticamente terrível. O código se torna ilegível, o registro é inconsistente e os casos de erro reais não são tratados.
O agente entendeu a requisição literalmente, mas perdeu a intenção. Sem exemplos de bom tratamento de erros, ele se baseou na interpretação mais óbvia (e pior).
Modo de falha 3: Falhas em cascata
Um agente comete um pequeno erro na etapa 1. Na etapa 10, esse erro se propagou por todas as decisões subsequentes. O que começou como um erro de digitação em um nome de função se torna uma API quebrada, testes quebrados e um desenvolvedor confuso tentando descobrir o que deu errado.
Este é o modo de falha mais perigoso porque o agente não sabe que falhou. Cada etapa parece razoável isoladamente. Somente o resultado final revela o problema.
Modo de falha 4: Exaustão de recursos
Deixados sem supervisão, alguns agentes entrarão em loop infinito. Eles tentarão novamente chamadas de API falhas indefinidamente, gerarão novos subagentes sem limite, ou continuarão a gerar código até atingirem seu limite de faturamento.
Sem restrições de recursos, os agentes não sabem quando parar.
A estrutura de autonomia: guardrails, observabilidade, checkpoints
Você resolve esses problemas com três camadas. Pense nelas como uma pirâmide: guardrails na base (prevenindo falhas), observabilidade no meio (detectando falhas) e checkpoints no topo (recuperando-se de falhas).
Camada 1: Guardrails (prevenção)
Guardrails são restrições que impedem falhas catastróficas. São regras que seu agente não pode quebrar, impostas por código, não por prompts.
Restrições rígidas via código:
# Não: Confie que o agente seguirá as instruções
agent.run("Modifique apenas arquivos no diretório src/")
# Sim: Imponha restrições no código
import os
from pathlib import Path
ALLOWED_DIRECTORIES = {"src", "tests", "docs"}
def validate_file_path(path: str) -> bool:
"""O agente não pode escrever fora dos diretórios permitidos."""
abs_path = Path(path).resolve()
return any(
str(abs_path).startswith(str(Path(d).resolve()))
for d in ALLOWED_DIRECTORIES
)
# Use nas operações de arquivo do seu agente
def agent_write_file(path: str, content: str):
if not validate_file_path(path):
raise ValueError(f"Não é possível escrever em {path}: fora dos diretórios permitidos")
with open(path, 'w') as f:
f.write(content)
Restrições de esquema de API:
Quando seu agente chama APIs, use esquemas para evitar requisições malformadas. É aqui que o Apidog se destaca. Defina seu contrato de API uma vez, e seu agente não poderá enviar o formato de dados errado.
// apidog-schema.ts
export const CreateUserSchema = {
type: 'object',
required: ['email', 'name'],
properties: {
email: { type: 'string', format: 'email' },
name: { type: 'string', minLength: 1, maxLength: 100 },
role: { type: 'string', enum: ['user', 'admin', 'guest'] }
},
additionalProperties: false
}
// O agente deve validar antes de chamar a API
function validateRequest(schema: object, data: unknown): void {
const valid = ajv.validate(schema, data)
if (!valid) {
throw new Error(`Requisição inválida: ${JSON.stringify(ajv.errors)}`)
}
}
Restrições de orçamento:
import time
from dataclasses import dataclass
@dataclass
class AgentBudget:
max_steps: int = 50
max_tokens: int = 100000
max_time_seconds: int = 600 # 10 minutos
max_api_calls: int = 100
class BudgetEnforcer:
def __init__(self, budget: AgentBudget):
self.budget = budget
self.start_time = time.time()
self.steps = 0
self.tokens_used = 0
self.api_calls = 0
def check(self) -> bool:
"""Retorna False se o orçamento for excedido."""
elapsed = time.time() - self.start_time
if self.steps >= self.budget.max_steps:
raise RuntimeError(f"Limite de passos atingido: {self.steps}")
if self.tokens_used >= self.budget.max_tokens:
raise RuntimeError(f"Limite de tokens atingido: {self.tokens_used}")
if elapsed >= self.budget.max_time_seconds:
raise RuntimeError(f"Limite de tempo atingido: {elapsed:.0f}s")
if self.api_calls >= self.budget.max_api_calls:
raise RuntimeError(f"Limite de chamadas de API atingido: {self.api_calls}")
return True
def record_step(self, tokens: int, api_calls: int = 0):
self.steps += 1
self.tokens_used += tokens
self.api_calls += api_calls
self.check()
Camada 2: Observabilidade (detecção)
Quando os agentes rodam por horas, você precisa saber o que eles estão fazendo sem observar cada passo. A observabilidade oferece uma linha do tempo das decisões.
Registro estruturado (Structured logging):
import json
from datetime import datetime
from typing import Any
class AgentLogger:
def __init__(self, log_file: str = "agent_trace.jsonl"):
self.log_file = log_file
self.entries = []
def log(self, event: str, data: dict[str, Any] | None = None):
entry = {
"timestamp": datetime.utcnow().isoformat(),
"event": event,
"data": data or {}
}
self.entries.append(entry)
# Anexa ao arquivo imediatamente (não perde logs em caso de falha)
with open(self.log_file, 'a') as f:
f.write(json.dumps(entry) + '\n')
def log_decision(self, decision: str, reasoning: str, confidence: float):
"""Registra quando o agente toma uma decisão significativa."""
self.log("decision", {
"decision": decision,
"reasoning": reasoning,
"confidence": confidence
})
def log_action(self, action: str, params: dict, result: str):
"""Registra ações do agente e seus resultados."""
self.log("action", {
"action": action,
"params": params,
"result": result[:200] # Trunca resultados longos
})
def log_error(self, error: str, context: dict):
"""Registra erros com contexto completo."""
self.log("error", {
"error": error,
"context": context
})
# Uso no agente
logger = AgentLogger()
logger.log_decision(
decision="Adicionar limitação de taxa à API",
reasoning="O endpoint atual não possui proteção contra abuso",
confidence=0.85
)
logger.log_action(
action="write_file",
params={"path": "src/middleware/rate-limit.ts"},
result="Escreveu 45 linhas com sucesso"
)
Painel de métricas:
Para agentes de longa duração, você deseja métricas agregadas, não apenas logs individuais.
from collections import Counter
from dataclasses import dataclass, field
@dataclass
class AgentMetrics:
actions_taken: Counter = field(default_factory=Counter)
files_modified: list[str] = field(default_factory=list)
api_calls: dict[str, int] = field(default_factory=dict)
errors: list[str] = field(default_factory=list)
decisions_by_confidence: dict[str, int] = field(default_factory=lambda: {
"alta (>0.9)": 0,
"média (0.7-0.9)": 0,
"baixa (<0.7)": 0
})
def record_action(self, action: str):
self.actions_taken[action] += 1
def record_file_modification(self, path: str):
if path not in self.files_modified:
self.files_modified.append(path)
def record_api_call(self, endpoint: str):
self.api_calls[endpoint] = self.api_calls.get(endpoint, 0) + 1
def record_error(self, error: str):
self.errors.append(error)
def record_decision(self, confidence: float):
if confidence > 0.9:
self.decisions_by_confidence["alta (>0.9)"] += 1
elif confidence >= 0.7:
self.decisions_by_confidence["média (0.7-0.9)"] += 1
else:
self.decisions_by_confidence["baixa (<0.7)"] += 1
def summary(self) -> str:
return f"""
Resumo das Métricas do Agente
=====================
Ações: {dict(self.actions_taken)}
Arquivos modificados: {len(self.files_modified)}
Chamadas de API: {self.api_calls}
Erros: {len(self.errors)}
Decisões por confiança: {self.decisions_by_confidence}
"""
Camada 3: Checkpoints (recuperação)
Checkpoints são pausas automáticas onde o agente aguarda a verificação humana. Eles permitem que você detecte problemas cedo, sem supervisão constante.
Checkpoints automáticos:
from enum import Enum
from typing import Callable
class CheckpointTrigger(Enum):
BEFORE_FILE_WRITE = "antes_da_escrita_do_arquivo"
BEFORE_API_CALL = "antes_da_chamada_da_api"
BEFORE_GIT_COMMIT = "antes_do_commit_git"
BEFORE_DELETE = "antes_da_exclusao"
AFTER_N_STEPS = "apos_n_passos"
@dataclass
class Checkpoint:
trigger: CheckpointTrigger
description: str
data: dict
requires_approval: bool = True
class CheckpointManager:
def __init__(self, auto_approve: set[CheckpointTrigger] | None = None):
self.auto_approve = auto_approve or set()
self.pending: list[Checkpoint] = []
def create_checkpoint(
self,
trigger: CheckpointTrigger,
description: str,
data: dict
) -> bool:
"""Retorna True se aprovado, False se rejeitado."""
# Aprova automaticamente certos gatilhos
if trigger in self.auto_approve:
return True
checkpoint = Checkpoint(
trigger=trigger,
description=description,
data=data
)
self.pending.append(checkpoint)
# Em um sistema real, isso notificaria o humano e aguardaria
# Por enquanto, retornamos False para pausar a execução
return False
def approve(self, checkpoint_id: int) -> None:
"""Humano aprova um checkpoint pendente."""
if 0 <= checkpoint_id < len(self.pending):
self.pending.pop(checkpoint_id)
def reject(self, checkpoint_id: int) -> None:
"""Humano rejeita um checkpoint pendente."""
raise RuntimeError(f"Checkpoint rejeitado: {self.pending[checkpoint_id]}")
# Uso no agente
checkpoints = CheckpointManager(
auto_approve={CheckpointTrigger.BEFORE_FILE_WRITE} # Confiar nas escritas de arquivo
)
# Antes de uma ação destrutiva
if not checkpoints.create_checkpoint(
trigger=CheckpointTrigger.BEFORE_DELETE,
description="Prestes a excluir o diretório src/legacy/",
data={"path": "src/legacy/", "files": ["old_handler.ts", "deprecated.ts"]}
):
# Aguarda aprovação humana
agent.pause("Aguardando aprovação para excluir arquivos")
Construindo agentes autônomos com Apidog
Quando seu agente de IA interage com APIs, o maior risco são requisições malformadas que causam falhas a jusante. O Apidog ajuda, permitindo que você defina esquemas de API exatos que seu agente deve seguir.
Configurando contratos de API:
- Importe ou defina sua especificação OpenAPI no Apidog
- Gere código cliente com validação integrada
- Forneça ao seu agente o cliente validado em vez de HTTP bruto
// Em vez de deixar o agente chamar APIs diretamente
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(data) // Sem validação
})
// Dê ao agente um cliente validado
import { UsersApi } from './generated/apidog-client'
const usersApi = new UsersApi()
// O agente só pode enviar requisições válidas - esquema imposto
const response = await usersApi.createUser({
email: 'user@example.com',
name: 'Usuário Teste',
role: 'user' // Deve ser um valor de enum válido
})
Isso transforma sua camada de API em um guardrail. O agente literalmente não pode enviar dados inválidos porque o cliente os rejeita antes que a requisição seja enviada.
Gere clientes de API validados para seus agentes de IA
Padrões comprovados e erros comuns
Padrão 1: O sanduíche de aprovação
Para operações arriscadas, exija aprovação ANTES E DEPOIS.
def risky_operation(agent, operation):
# Pré-aprovação
if not agent.checkpoint(f"Prestes a: {operation.description}"):
return "Cancelado pelo usuário"
# Executa a operação
result = operation.execute()
# Pós-aprovação (verifica o resultado)
if not agent.checkpoint(f"Verificar resultado de: {operation.description}"):
operation.rollback()
return "Revertido pelo usuário"
return result
Padrão 2: Limites de confiança
Não permita que agentes ajam com base em decisões de baixa confiança.
MIN_CONFIDENCE = 0.75
def agent_decide(options: list[dict]) -> dict:
best = max(options, key=lambda x: x.get('confidence', 0))
if best['confidence'] < MIN_CONFIDENCE:
# Escalar para humano
return {
'action': 'escalar',
'reason': f"A melhor opção tem confiança {best['confidence']:.2f} < {MIN_CONFIDENCE}",
'options': options
}
return best
Padrão 3: Operações idempotentes
Projete as ações do seu agente para serem repetíveis sem efeitos colaterais.
import hashlib
def idempotent_write(path: str, content: str) -> bool:
"""Escreve apenas se o conteúdo foi alterado."""
content_hash = hashlib.sha256(content.encode()).hexdigest()
existing_hash = None
if os.path.exists(path):
with open(path, 'r') as f:
existing_hash = hashlib.sha256(f.read().encode()).hexdigest()
if content_hash == existing_hash:
logger.log_action("write_file", {"path": path}, "Ignorado - sem alterações")
return False
with open(path, 'w') as f:
f.write(content)
logger.log_action("write_file", {"path": path}, f"Escreveu {len(content)} bytes")
return True
Erros comuns a evitar
Confiar em prompts como restrições. “Não exclua arquivos” em um prompt não é uma restrição. Permissões de arquivo são restrições.
Nenhum plano de reversão. Quando um agente comete um erro, você precisa desfazê-lo. Se você não estiver usando git ou backups, está confiando ao agente ações irrecuperáveis.
Ignorar pontuações de confiança. A maioria dos LLMs produz confiança ou pode ser solicitada a fazê-lo. Baixa confiança = pausa e pergunte ao humano.
Monitorar excessivamente. Se você está observando cada passo, você não construiu um sistema autônomo. Você construiu um sistema manual lento.
Subespecificar o sucesso. O agente precisa saber quando terminou. “Corrigir o bug” não tem condição de término. “Corrigir o bug E todos os testes passarem” tem.
Alternativas e comparações
| Abordagem | Autonomia | Risco | Melhor para |
|---|---|---|---|
| Codificação manual | Nenhuma | Baixo | Trabalho complexo e crítico |
| Programação em pares com IA | Baixa | Baixo | Aprendizado, exploração |
| Agentes supervisionados | Média | Médio | Tarefas rotineiras |
| Agentes autônomos com guardrails | Alta | Controlado | Operações em massa, migrações |
| Agentes totalmente autônomos | Muito alta | Alta | Fluxos de trabalho confiáveis e bem testados |
A maioria das equipes deve almejar “autônomos com guardrails”. É o ponto ideal onde você obtém 80% da economia de tempo com 10% do risco.
Casos de uso reais
Migração de codebase. Uma equipe usou um agente autônomo para migrar 200 endpoints de API de REST para GraphQL. Guardrails impediram mudanças de esquema. Checkpoints exigiram aprovação antes de excluir endpoints antigos. A migração levou 3 dias em vez de 3 semanas, com zero incidentes em produção.
Geração de documentação. Um agente gera automaticamente documentações de API a partir do código. Guardrails garantem que ele leia apenas de diretórios específicos. Checkpoints pausam antes da publicação. A equipe revisa uma vez por semana em vez de escrever as docs manualmente.
Cobertura de testes. Um agente analisa o código e escreve testes faltantes. Restrições de orçamento evitam a geração descontrolada de testes. Limites de confiança sinalizam testes incertos para revisão humana. A cobertura melhorou de 60% para 85% em um mês.
Conclusão
Aqui está o que você aprendeu:
- Agentes de IA falham de maneiras previsíveis: expansão de escopo, abstrações incorretas, falhas em cascata, exaustão de recursos
- Três camadas resolvem a maioria dos problemas: guardrails (prevenção), observabilidade (detecção), checkpoints (recuperação)
- Guardrails são código, não prompts. Imponha restrições programaticamente.
- Observabilidade significa logs e métricas estruturadas, não observar cada passo
- Checkpoints permitem que humanos verifiquem decisões sem supervisão constante
- Esquemas de API do Apidog transformam sua camada de API em um guardrail
Seus próximos passos:
- Identifique sua tarefa assistida por IA mais repetitiva
- Defina guardrails: o que o agente nunca deve fazer?
- Adicione registro estruturado para ver o que está acontecendo
- Crie checkpoints para operações de alto risco
- Deixe-o rodar por 30 minutos e verifique os logs
O objetivo não é remover humanos do ciclo. É colocar humanos no lugar certo do ciclo: tomando decisões de alto nível em vez de corrigir erros de baixo nível.
Construa guardrails de API para seus agentes de IA - grátis
FAQ
Qual a diferença entre um agente de IA e um assistente de IA?Um assistente responde às suas requisições e aguarda sua próxima instrução. Um agente recebe um objetivo e autonomamente planeja e executa passos para alcançá-lo. Assistentes precisam de você em cada ciclo. Agentes rodam até atingirem um checkpoint ou terminarem.
Como sei se meu agente está pronto para rodar autonomamente?Execute-o em modo supervisionado por 10 sessões. Registre cada vez que você teve que intervir. Se as intervenções caírem para menos de 2 por sessão e todas foram menores (esclarecimentos, não correções), ele está pronto. Se as intervenções forem frequentes ou exigirem desfazer o trabalho, adicione mais guardrails.
Qual é o maior risco com agentes autônomos?Falhas em cascata que o agente não reconhece. Um pequeno erro no início se torna um grande problema mais tarde, e o agente continua porque cada passo parece razoável isoladamente. Checkpoints quebram essas cascatas, forçando a verificação.
Posso usar esses padrões com qualquer LLM?Sim. Os padrões (guardrails, observabilidade, checkpoints) são agnósticos ao modelo. Eles funcionam com Claude, GPT-4, Gemini ou qualquer outro modelo. Os detalhes de implementação específicos podem variar, mas os conceitos se transferem.
Quanto a observabilidade atrasa o agente?Negligível. Escrever em um arquivo de log leva microssegundos. O atraso vem dos checkpoints que esperam a entrada humana. Para execuções verdadeiramente autônomas, você checkpoint apenas em momentos de alto risco, não em cada passo.
E se o agente tomar uma decisão com a qual eu discordo?É para isso que servem os checkpoints. Quando você vê uma decisão com a qual discorda, rejeite o checkpoint. O agente reverte ou tenta uma abordagem diferente. Melhor: inclua suas preferências nas instruções do agente para que ele aprenda seu estilo ao longo do tempo.
Devo começar com agentes supervisionados ou autônomos?Sempre comece supervisionado. Execute o agente com checkpoints em cada ação significativa até confiar nele. Remova gradualmente os checkpoints para ações de baixo risco. Isso constrói confiança incrementalmente, em vez de arriscar uma falha catastrófica em sua primeira execução autônoma.
Como o Apidog ajuda especificamente com agentes de IA?O Apidog gera clientes de API validados a partir de seus esquemas. Quando um agente usa esses clientes, requisições malformadas são rejeitadas antes de chegarem ao seu backend. Isso evita uma classe inteira de falhas onde o agente envia o formato de dados errado ou valores inválidos.
