Pular para o conteúdo
Cursos

DevClub

LógicaFront-endBack-endMobile

IA Club

IA na prática
Estudar programaçãoEstudar IA
LiçãoIntermediáriocódigo testado

Agentes de IA: construa o loop sem perder o controle

Entenda o que é um agente de IA, implemente o ciclo entre modelo e ferramentas, limite passos e mantenha autorização, estado e erros no código.

Rodolfo Mori6 min de leitura

Um agente de IA é um programa em ciclo: o modelo recebe uma tarefa, pode pedir uma ferramenta, observa o resultado e continua até responder ou atingir um limite. Nesta lição, você vai implementar esse loop, tornar os passos visíveis e interromper uma sequência que não consegue terminar.

O nome técnico agent não significa uma mente trabalhando sozinha. Na prática, é uma combinação de modelo, instruções, ferramentas, estado e regras de parada. O programa continua responsável por autenticação, efeitos colaterais, orçamento e decisões que exigem uma pessoa.

O código daqui usa decisões em fixtures locais para tornar o controle de fluxo determinístico. Ele foi executado no Node, mas não chamou a API OpenAI. Essa separação permite provar o loop sem fingir que uma lista escrita no código mede o comportamento de um modelo real.

O despachante escolhe a próxima parada, mas não dirige sem estrada

Imagine uma central de entregas. O despachante recebe o destino, consulta o estoque, manda um motorista buscar o pacote e confere o comprovante antes de encerrar. Há uma sequência, um registro e um limite de tentativas. Se a estrada não existe, insistir dez vezes não cria uma rota.

No paralelo, o modelo é o despachante; as ferramentas são veículos autorizados; os resultados são comprovantes; o histórico é o quadro da operação; e a regra de parada define quando a tarefa termina. O limite da analogia: o modelo não observa o mundo por conta própria. Ele conhece apenas o contexto e os resultados que a aplicação devolve.

Uma execução pode ser resumida assim:

text
tarefa
  -> modelo decide
     -> resposta: encerra
     -> ferramenta: aplicação valida e executa
        -> resultado volta ao contexto
           -> modelo decide novamente
Duas saídas possíveis por passo: responder ou solicitar ferramenta.

Antes de criar o ciclo, estude o protocolo da lição de function calling. Agente não corrige uma ferramenta insegura; ele apenas pode chamá-la mais vezes.

Estado explícito transforma conversa em execução auditável

Modele as duas decisões que interessam ao nosso laboratório:

ts
type Decisao =
  | { tipo: "ferramenta"; nome: "buscar_pedido"; argumentos: string }
  | { tipo: "resposta"; texto: string };

type Passo = {
  numero: number;
  tipo: Decisao["tipo"];
  detalhe: string;
};

const trajetoria: Passo[] = [];
console.log(trajetoria);
[]

O array vazio é o começo da trajetória. Em produção, um item de response.output com type: "function_call" representa a primeira decisão; uma mensagem final representa a segunda. Registrar o passo ajuda a explicar qual ferramenta foi usada e onde o sistema parou.

Estado não precisa significar guardar conversas para sempre. Preserve apenas o necessário, defina retenção e retire dados sensíveis dos logs. Na Responses API, você pode continuar com itens anteriores no input ou encadear uma resposta anterior, conforme o desenho de privacidade e estado do produto.

O loop mínimo precisa de uma porta de saída

Primeiro crie uma versão independente de provedor. As decisões entram como fixture para que a execução seja repetível:

ts
function executarLoop(decisoes: Decisao[], limite = 3) {
  const passos: string[] = [];

  for (let indice = 0; indice < limite; indice += 1) {
    const decisao = decisoes[indice] ?? decisoes.at(-1);
    if (!decisao) throw new Error("SEM_DECISAO");

    passos.push(decisao.tipo);

    if (decisao.tipo === "resposta") {
      return { passos, resposta: decisao.texto };
    }

    // Aqui a aplicação validaria e executaria a ferramenta.
  }

  throw new Error("LIMITE_DE_PASSOS_ATINGIDO");
}
Função carregada: limite padrão de 3 decisões.

Passe uma trajetória que usa ferramenta e depois responde:

ts
const concluido = executarLoop([
  {
    tipo: "ferramenta",
    nome: "buscar_pedido",
    argumentos: '{"pedidoId":1042}',
  },
  { tipo: "resposta", texto: "Pedido enviado." },
]);

console.log(concluido);
{ passos: [ 'ferramenta', 'resposta' ], resposta: 'Pedido enviado.' }

O primeiro passo não produziu uma frase ao cliente. Ele indicou que faltava um dado externo. A aplicação obteria esse dado, acrescentaria function_call_output ao contexto e faria a próxima chamada.

A Responses API ocupa o lugar das decisões da fixture

Num projeto novo da OpenAI, use a Responses API. O esqueleto do ciclo fica assim, com histórico carregado de maneira explícita e sem armazenamento remoto:

ts
const input: OpenAI.Responses.ResponseInput = [
  { role: "user", content: pergunta },
];

for (let passo = 1; passo <= maxPassos; passo += 1) {
  const response = await client.responses.create({
    model: "gpt-5.6-luna",
    instructions,
    input,
    tools,
    store: false,
  });

  input.push(...(response.output as OpenAI.Responses.ResponseInput));
  const chamadas = response.output.filter(
    (item) => item.type === "function_call",
  );

  if (chamadas.length === 0) return response.output_text;
  // Validar, executar e anexar cada function_call_output.
}
Não executado contra a API: assinatura compilada com OpenAI SDK 7.5.0; loop testado com fixtures locais.

Evite começar um projeto novo pela antiga Assistants API. A documentação atual recomenda Responses API para novas integrações e oferece uma migração para quem mantém sistemas anteriores. Isso não significa reescrever uma aplicação em produção sem planejamento; significa não copiar um fluxo legado num projeto que ainda nem começou.

Quando uma chamada aparece, a aplicação executa uma allowlist, confere a identidade real da sessão e devolve o mesmo call_id:

ts
for (const chamada of chamadas) {
  const output = executarFerramenta(
    chamada.name,
    chamada.arguments,
    usuarioIdDaSessao,
  );

  input.push({
    type: "function_call_output",
    call_id: chamada.call_id,
    output,
  });
}
Contrato do passo: nome e argumentos entram na allowlist; resultado sai ligado ao call_id.

O modelo pode selecionar uma ferramenta; ele não decide autorização. Também não entregue uma conexão de banco, um shell genérico ou um cliente HTTP sem restrições apenas para tornar o agente “mais capaz”. Capacidade sem fronteira aumenta a superfície de erro.

Três orçamentos impedem autonomia sem fim

Número de passos é apenas um limite. A execução também deve controlar tempo e operações com efeito:

ts
const limites = {
  maxPassos: 4,
  tempoTotalMs: 15_000,
  maxAcoesComEfeito: 0,
};

console.log(limites);
{ maxPassos: 4, tempoTotalMs: 15000, maxAcoesComEfeito: 0 }

Para um assistente que apenas consulta pedido, zero ações com efeito faz sentido. Se o sistema puder cancelar uma compra, crie uma etapa separada de confirmação, idempotência e auditoria. Não deixe o mesmo prompt que interpreta a intenção autorizar a consequência.

Você também pode limitar ferramentas por etapa. Um classificador não precisa ver cancelar_pedido; um fluxo de suporte financeiro talvez só possa abrir uma solicitação para uma pessoa. Privilégio mínimo continua sendo regra de software, mesmo quando um modelo está no meio.

O loop infinito aparece como erro útil, não como conta surpresa

Nossa função repete a última fixture quando as decisões acabam. Forneça apenas uma chamada de ferramenta, sem resposta final:

ts
try {
  executarLoop([
    {
      tipo: "ferramenta",
      nome: "buscar_pedido",
      argumentos: '{"pedidoId":1042}',
    },
  ], 3);
} catch (erro) {
  console.log({ erro: (erro as Error).message, limite: 3 });
}
{ erro: 'LIMITE_DE_PASSOS_ATINGIDO', limite: 3 }

A mensagem traduz o problema: três decisões ocorreram sem estado final. Em uma integração real, guarde a trajetória, ids de resposta, ferramentas chamadas e motivo da interrupção. Mostre ao usuário uma saída segura, como “não consegui concluir; encaminhei para revisão”, sem expor detalhes internos.

Retentar cegamente o mesmo contexto pode repetir a mesma falha. Uma retentativa precisa de condição: erro transitório, limite de tentativas, intervalo e idempotência. Erro lógico ou falta de permissão deve parar imediatamente.

Quando um agente é exagero

Se a ordem das etapas já é conhecida — validar formulário, consultar pedido, calcular frete e responder — escreva um fluxo determinístico. Ele é mais simples de testar e explicar. Use decisão do modelo quando a linguagem realmente muda o caminho e há mais de uma próxima ação plausível.

Compare as escolhas:

problema desenho inicial motivo
extrair três campos uma chamada estruturada não há ciclo
consultar pedido quando citado modelo + uma ferramenta caminho depende da mensagem
aprovação de reembolso workflow com humano consequência financeira
pesquisa em várias fontes agente com limites próximos passos variam

Frameworks e SDKs de agentes podem ajudar com tracing, handoffs e orquestração. Adote-os quando essas necessidades aparecerem, não para esconder o loop que a equipe ainda não entende. O tutorial de assistente com Responses API mantém o ciclo visível justamente para você conseguir depurá-lo.

Missão: encerre por falta de permissão

Acrescente uma terceira decisão bloqueio e faça o loop terminar sem chamar outra ferramenta:

ts
type ResultadoBloqueado = {
  passos: string[];
  resposta: string;
  precisaDeHumano: true;
};

const bloqueado: ResultadoBloqueado = {
  passos: ["ferramenta", "bloqueio"],
  resposta: "Esta ação precisa de revisão humana.",
  precisaDeHumano: true,
};

console.log(bloqueado);
{ passos: [ 'ferramenta', 'bloqueio' ], resposta: 'Esta ação precisa de revisão humana.', precisaDeHumano: true }

O critério de sucesso é objetivo: uma tarefa de consulta ainda conclui; uma ação financeira encerra em bloqueio; e a fixture que só chama ferramenta continua falhando no limite. Em seguida, coloque os três caminhos numa avaliação de aplicações de IA para que uma mudança de prompt não remova silenciosamente a parada humana.

  • agentes de ia
  • agentic ai
  • function calling
  • responses api
  • seguranca de ia

Perguntas frequentes

O que transforma uma chamada de modelo em agente?
O ciclo. O sistema permite que o modelo solicite ferramentas, observa o resultado, atualiza o estado e decide entre continuar ou devolver uma resposta dentro de limites definidos pela aplicação.
Um agente de IA trabalha sozinho?
Ele só age dentro das ferramentas, credenciais e regras que o programa disponibiliza. Autonomia é uma configuração de software, não consciência nem autoridade ilimitada.
Preciso de um framework para criar um agente?
Não. Um loop com Responses API e function calling já cobre muitos casos. Frameworks e SDKs de agentes ajudam com rastreamento, handoffs e orquestração quando essa complexidade realmente aparece.
Como impedir um agente de entrar em loop infinito?
Defina número máximo de passos, tempo total, orçamento, ferramentas permitidas e condições de parada. Registre a trajetória para diagnosticar por que ele não conseguiu encerrar.

Dúvidas e comentários

Travou em algum passo? Pergunte aqui — a equipe e outros alunos respondem.

Todo o código deste artigo foi executado em Node 26.3.0 e TypeScript 7.0.2; loop, limites e fixtures executados localmente, sem chamada à API, e as saídas exibidas são as reais — como produzimos este conteúdo.

Fontes consultadas

  1. OpenAI Docs — Agents — developers.openai.com
  2. OpenAI Docs — Function calling — developers.openai.com
  3. OpenAI Docs — Migrate to the Responses API — developers.openai.com
  4. OpenAI Docs — Safety best practices — developers.openai.com

Continue por aqui