Aula 01 · Base

Sem loops, não há agente

Todo o segredo do Código Claude pode ser escrito em uma linha: while stop_reason == "tool_use"

⏱ ~10 min · 📝 3 componentes interativos · 🧑‍💻 Baseado em shareAI-lab · s01_agent_loop.py

O que exatamente um agente está fazendo?

Quando você executa o Claude Code no terminal e deixa-o "organizar todos os comentários TODO em uma lista", o que você vê é: ele decide por conta própria primeiro grep, depois cat alguns arquivos e então gerar Markdown. O modelo não executa o código em si - ele apenas solicita para ser executado. O que realmente faz com que pareça "com mãos e pés" são as cerca de 30 linhas de código de cola ao seu redor.

Esta lição consiste em desmontar o círculo de cola e ver claramente. É chamado de loop de agente (loop de agente) e sua estrutura é:

while response.stop_reason == "tool_use":
    resposta = LLM(mensagens, ferramentas) # 1. pergunte ao modelo
    execute_tools(response.tool_calls) # 2. execute o que foi solicitado
    messages.append(tool_results) #3. feed de resultados

É isso. Não mais. O Código de produção Claude tem permissões, ganchos, subagentes, isolamento de árvore de trabalho e compactação de memória empilhados em cima disso - mas o núcleo ainda são essas quatro linhas.

Intuição principal: cada vez que o modelo responde, é "Quero ajustar a ferramenta" ou "Terminei". O loop continua enquanto estiver no estado anterior; uma vez que entra no último estado, o loop termina. O critério é o campo stop_reason na resposta.

Veja as mensagens[] crescerem passo a passo

A tarefa da seguinte simulação de loop é: "Quais arquivos estão no diretório atual? Então leia package.json". Clique em Etapa. Cada vez que você pressiona, você avança uma ação no ciclo. À esquerda está o balão de fala visualizado por humanos, à direita está o array messages[] real inserido no modelo - observe como ele cresce.

Os resultados da ferramenta devem ser inseridos novamente no histórico de mensagens

A armadilha mais fácil para novatos é considerar a "ferramenta de execução" como um efeito colateral - uma vez executada, está concluída. No entanto, o modelo só pode ver mensagens[] na próxima rodada de inferência e ele não sabe que coisas que não estão nele aconteceram. Sem a etapa de acréscimo, todo o loop estaria errado.

Nem todos os erros são iguais. Dois tipos comuns:

  • Esqueça o acréscimo: o modelo não verá os resultados na próxima vez, ele pedirá a mesma ferramenta novamente - e você obterá um loop infinito.
  • Anexar, mas perder tool_use_id: a API Anthropic reportará diretamente um erro tool_result must have tool_use_id, e o loop entrará em colapso na etapa de chamada da API.

A mesma tarefa: "Contar quantos arquivos Python existem no projeto". Execute as duas versões lado a lado para ver a diferença nos finais.

Entenda stop_reason

Cada vez que o modelo retornar, ele trará um stop_reason. Para decidir se deseja continuar o loop, basta olhar este campo:

  • tool_use — O modelo deseja ajustar a ferramenta, continue o loop.
  • end_turn — O modelo sente que terminou e sai do loop.
  • max_tokens — Quando o limite superior de tokens é gerado, ele é truncado e sai do loop (geralmente tratado como uma exceção para avisar ao usuário que a saída está incompleta).
  • stop_sequence — Quando uma sequência de parada personalizada for encontrada, saia do loop.

Escrever incorretamente como "continuar enquanto não houver tool_use", ou ignorar max_tokens e tratá-lo diretamente como um fim normal, são erros comuns.

Tome uma atitude e corra

Clone local shareAI-lab/learn-claude-code:

git clone https://github.com/shareAI-lab/learn-claude-code
cd aprender-claude-código
pip instalar -r requisitos.txt
cp .env.example .env # preencha ANTHROPIC_API_KEY
agentes python/s01_agent_loop.py

Então deixe-o fazer algo real: Ajude-me a contar quantos arquivos .py estão neste repositório. Você verá enviar um ls -R, ver a saída, enviar outro find . -nome "*.py" | wc -l, e então lhe darei a resposta. Todo o processo é esse loop.

Interativo

Widget 1 · Loop Stepper · mensagens[] crescimento

Entenda: os resultados da ferramenta são recolocados em mensagens em um formato especial (bloco tool_result, com tool_use_id); esta é a única maneira de o modelo saber que “a ferramenta foi executada e o resultado é X” na próxima rodada de inferência.

对话视图未开始
点 Step 开始 →
messages[] JSONlength: 0
[]
stop_reason:
Interativo

Widget 2 · Quebre o Loop · Correto vs Esqueci de anexar

Entenda: Enquanto faltar uma linha messages.append(tool_results), todo o agente não é mais um agente - ele se torna uma máquina de leitura que esquece o anterior em cada rodada.

while True:
    resp = LLM(msgs, tools)
    msgs.append({"role":"assistant",
                 "content": resp.content})
    if resp.stop_reason != "tool_use":
        return
    results = execute(resp.tool_uses)
    msgs.append({"role":"user",
                 "content": results})
模拟运行
while True:
    resp = LLM(msgs, tools)
    msgs.append({"role":"assistant",
                 "content": resp.content})
    if resp.stop_reason != "tool_use":
        return
    results = execute(resp.tool_uses)
    # BUG: forgot to append results
    # msgs.append(...)
模拟运行
Interativo

Widget 3 · Identifique o stop_reason · Julgue 4 respostas verdadeiras

Cada um é um fragmento de uma resposta real possível do modelo. Clique em “Continuar” ou “Sair” para ver se você está certo ou errado.

答对 0 / 4