Agentes


Um agente é um modelo rodando em loop, escolhendo a próxima ferramenta a chamar até que uma tarefa seja concluída. O restante deste capítulo explica o que isso significa, onde essa abordagem vale a pena e onde ela custa caro sem você perceber.
O loop do agente
Em uso de ferramentas, o modelo chamava uma função e você devolvia o resultado. Mas algumas tarefas exigem várias etapas, e você não sabe quais são essas etapas de antemão. "Encontre o voo mais barato e reserve" pode significar pesquisar, comparar, verificar uma agenda e então reservar, e o modelo precisa descobrir essa sequência ao longo do caminho.
Então, em vez de lidar com uma única chamada de ferramenta, você coloca tudo isso dentro de um loop. Esse ciclo repetido é o loop do agente, um turno repetido até que a tarefa seja concluída:
- Envie a conversa e as ferramentas disponíveis para o modelo.
- O modelo chama uma ferramenta ou dá uma resposta final.
- Se ele chamou uma ferramenta, execute-a, adicione o resultado à conversa e volte para o passo 1.
- Se ele deu uma resposta final, pare.
A cada turno, o modelo vê tudo o que aconteceu até então, incluindo resultados anteriores de ferramentas, e decide o próximo passo. Essa é toda a diferença em relação ao uso de ferramentas: você continua repetindo o loop até que o modelo considere que terminou.
A verdadeira mudança está em quem assume o controle. Em todos os capítulos anteriores, era o seu código que decidia o fluxo de controle: você escolhia quando chamar o modelo, quando executar uma ferramenta, o que vinha a seguir. Um agente entrega essa decisão ao modelo. O loop fica perguntando "o que deve acontecer agora?" e a previsão do modelo é a resposta a cada vez. Você troca controle por flexibilidade, e essa troca é a fonte tanto do alcance quanto do risco.
No fundo, nada de novo está acontecendo. É a mesma previsão sobre um contexto que cresce, o ciclo de ida e volta do uso de ferramentas repetido continuamente. O modelo não elabora um plano e o segue. A cada turno, ele prevê o único próximo passo mais provável a partir do que consegue ver naquele momento, e então o loop roda de novo.
Quando isso funciona, parece um raciocínio direcionado a um objetivo. Quando não funciona, o agente entra em loop sobre si mesmo ou segue por um caminho sem saída, porque nenhuma parte do sistema está de fato guardando o plano geral.
Um agente mínimo
Aqui está o loop em código. Ele reaproveita as definições e implementações de ferramentas de uso de ferramentas e as envolve em um loop que roda até o modelo parar de pedir ferramentas.
import json
def run_agent(user_text, tools, tool_impls, max_steps=6):
messages = [{"role": "user", "content": user_text}]
step = 0
while step < max_steps:
response = client.chat.completions.create(model=MODEL, messages=messages, tools=tools)
message = response.choices[0].message
messages.append(message)
calls = message.tool_calls
if not calls:
return message.content # nenhuma ferramenta pedida: esta é a resposta final
# executa cada ferramenta solicitada e devolve os resultados
for call in calls:
args = json.loads(call.function.arguments)
result = tool_impls[call.function.name](args)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
step += 1
return "Parado: o agente atingiu o limite de passos." # rede de segurançaLeia de cima a baixo: chame o modelo, empurre a mensagem dele para a conversa e, se ele pediu ferramentas, execute todas e anexe os resultados, depois repita o loop. Quando o modelo retorna texto em vez de uma chamada de ferramenta, essa é a resposta final, e você a retorna.
O valor de max_steps define um limite de passos, a rede de segurança que evita que o loop saia do controle, assunto da próxima seção. A estrutura aqui corresponde ao SDK de um provedor específico; os nomes dos campos variam entre provedores, mas o loop é o mesmo em qualquer lugar.
Parando e guardrails
Um loop que deixa o modelo decidir quando parar pode simplesmente não parar. Ele pode chamar ferramentas para sempre, se repetir, ou seguir por um caminho sem saída. Como cada passo é uma chamada ao modelo cobrada por tokens, um agente fora de controle consome dinheiro e tempo rapidamente.
Por isso, guardrails, os limites que você coloca em torno do loop, fazem parte do design, não são um retoque que se adiciona no final:
- Um limite de passos. Limite o número de repetições do loop, como faz o
max_steps. Quando esse limite for atingido, pare e retorne. - Valide as entradas das ferramentas. O modelo escolhe os argumentos, então verifique-os antes de executar qualquer coisa com consequências reais.
- Limite o que as ferramentas podem fazer. Dê ao agente o mínimo de poder necessário. Uma ferramenta que só lê é mais segura do que uma que deleta.
- Fique atento ao custo. Várias chamadas ao modelo por tarefa se multiplicam rapidamente, então acompanhe os tokens e defina um orçamento.
O que une tudo isso: o modelo está improvisando o caminho, então cabe a você colocar os limites que ele não vai colocar. Assuma que o agente vai fazer a coisa errada pelo menos uma vez, e faça com que isso seja algo que você consiga sobreviver.
Quando um workflow é melhor que um agente
Agentes são empolgantes, o que torna tentador usar um mesmo quando você não precisa. A regra simples: se você já conhece os passos, não use um agente. Escreva-os como código simples, um workflow, em que cada passo roda em uma ordem fixa.
Um workflow é mais confiável, mais barato e muito mais fácil de depurar, porque você controla o caminho em vez de esperar que o modelo o encontre. Reserve os agentes para tarefas abertas, em que os passos dependem do que é descoberto ao longo do caminho.
Muitos recursos que parecem precisar de um agente ficam melhores como uma chamada de saída estruturada ou uma consulta de RAG montada manualmente com código. Recorra a um agente apenas quando você não conseguir escrever os passos com antecedência.
Na prática
A função run_agent acima é tudo o que existe. Dê a ela uma pergunta, um conjunto de ferramentas e suas implementações, e ela roda em loop até terminar ou até atingir o limite de passos. Uma tarefa pequena mostra o loop compensando o esforço:
answer = run_agent(
"What's the weather in Brasília and should I bring an umbrella?",
tools, # inclui get_weather do capítulo sobre uso de ferramentas
tool_impls, # {"get_weather": ...}
)
# O agente chama get_weather, lê "nublado", e então responde em um turno final:
# "Está nublado em Brasília, a 18 graus, então um guarda-chuva é uma boa ideia."Uma ferramenta, um loop, uma resposta. A mesma estrutura escala para várias ferramentas e vários passos sem mudar de formato. Uma vez que você consegue construir algo tão capaz, a próxima pergunta é como saber se isso realmente funciona, e é sobre isso que trata evals.
run_agent é todo o padrão: dê a ele uma pergunta, ferramentas e suas implementações, e ele roda em loop até o modelo parar de pedir ferramentas ou atingir o limite de passos. Uma ferramenta e um loop escalam para muitas sem mudar de formato. A próxima pergunta é como saber se isso realmente funciona, e é aí que entram os evals. 
