E1 · A ferramenta em ação
10 minRode o bloco do terminal com o agente.py da aula 3.
Pronto quando: a saída tem a linha [ferramenta] ler_arquivo {"nome": "notas.txt"} e termina com (2 rodada(s)).
Aula 3 · 15 min
Sozinho, o modelo só escreve texto. Com ferramentas, ele pede "leia este arquivo", o seu programa lê e devolve o conteúdo, e ele continua dali. Esse vai e volta é o loop, o coração de todo agente. Nesta aula ele cabe em menos de 20 linhas.
Começar a aula
Objetivo: dar ao agente a ferramenta ler_arquivo e ver o loop pedir, executar e responder em duas rodadas.
Clique em cada etapa. Ele repete até o modelo responder sem pedir ferramenta, ou até 5 voltas.
Rode dentro de agente-do-zero/. O cp troca o agente.py pelo da aula 3.
#!/usr/bin/env python3
"""Agente do zero (aula 3): o loop com ferramenta. O modelo pede, o código executa, o resultado volta."""
import json, os, sys, urllib.request
MODELO = os.environ.get("MODELO", "llama3.2")
URL = os.environ.get("OLLAMA_URL", "http://localhost:11434") + "/api/chat"
PASTA = os.path.realpath("trabalho")
MAX_RODADAS = 5
def cerebro(mensagens, ferramentas):
corpo = {"model": MODELO, "messages": mensagens, "tools": ferramentas, "stream": False, "think": False,
"options": {"temperature": 0, "seed": 1}}
pedido = urllib.request.Request(URL, json.dumps(corpo).encode(), {"Content-Type": "application/json"})
with urllib.request.urlopen(pedido, timeout=600) as r:
return json.loads(r.read())["message"]
def ler_arquivo(nome):
with open(os.path.join(PASTA, nome)) as f: # ainda sem trava: ela entra na aula 5
return f.read()
FERRAMENTAS = {"ler_arquivo": ler_arquivo}
DESCRICOES = [
{"type": "function", "function": {"name": "ler_arquivo", "description": "Lê um arquivo da pasta de trabalho.",
"parameters": {"type": "object", "properties": {"nome": {"type": "string"}}, "required": ["nome"]}}},
]
def responder(pedido, mostrar=print):
mensagens = [{"role": "user", "content": pedido}]
for rodada in range(MAX_RODADAS):
msg = cerebro(mensagens, DESCRICOES)
mensagens.append(msg)
if not msg.get("tool_calls"):
return msg.get("content", ""), rodada + 1
for chamada in msg["tool_calls"]:
nome, args = chamada["function"]["name"], chamada["function"].get("arguments") or {}
try:
saida = FERRAMENTAS[nome](**args)
except Exception as erro:
saida = f"recusado: {erro}"
mostrar(f"[ferramenta] {nome} {json.dumps(args, ensure_ascii=False)} -> {saida[:80]}")
mensagens.append({"role": "tool", "content": saida})
return "Parei: cheguei ao limite de rodadas.", MAX_RODADAS
if __name__ == "__main__":
os.makedirs(PASTA, exist_ok=True)
resposta, rodadas = responder(" ".join(sys.argv[1:]))
print(f"{resposta}\n({rodadas} rodada(s))")cd ~/agente-do-zero cp ~/agentes-do-zero-v72/kit/aula3/agente.py . echo "Reunião com o fornecedor às 15h." > trabalho/notas.txt python3 agente.py "leia notas.txt e diga a hora da reunião"
[ferramenta] ler_arquivo {"nome": "notas.txt"} -> Reunião com o fornecedor às 15h.
Parece que o arquivo "notas.txt" foi lido com sucesso!
Aqui está o conteúdo do arquivo:
Reunião com o fornecedor às 15h.
O que você gostaria de saber mais sobre a reunião?
(2 rodada(s))Rodada 1: o modelo pediu ler_arquivo. Rodada 2: com o conteúdo na mão, respondeu. A resposta é falante, mas a hora está certa.
Clique em cada uma.
Uma função Python comum, que abre o arquivo dentro de trabalho/ e devolve o texto.
Ainda sem trava: um pedido esperto consegue sair da pasta. Você vai ver isso acontecer e fechar o furo na aula 5.
O modelo não lê o seu código. Ele lê o nome, a descrição e os parâmetros que você escreve aqui.
Descrição clara é o que faz o modelo escolher a ferramenta certa. Ferramenta demais confunde.
Chama o modelo; se ele pediu ferramenta, executa, guarda o resultado e volta. Se não pediu, essa é a resposta final.
MAX_RODADAS = 5 garante que ele para, mesmo se o modelo insistir.
Faça na ordem.
Rode o bloco do terminal com o agente.py da aula 3.
Pronto quando: a saída tem a linha [ferramenta] ler_arquivo {"nome": "notas.txt"} e termina com (2 rodada(s)).
Crie um arquivo seu em trabalho/ (uma lista, um lembrete) e faça uma pergunta que só dá para responder lendo ele.
Pronto quando: a linha [ferramenta] mostra o nome do seu arquivo e a resposta usa o que está nele.
A explicação aparece depois da sua resposta.
Pergunta 1 de 3
Como o modelo sabe que existe a ferramenta ler_arquivo?
Pergunta 2 de 3
Quando o loop termina?
Pergunta 3 de 3
Na saída capturada, quantas vezes o modelo foi chamado?
Escolha uma alternativa. A explicação aparece depois da sua tentativa.