90% do código na Anthropic é escrito por agentes Claude. Não por engenheiros digitando em uma janela de chat. Por agentes autônomos executando loops, chamando ferramentas e enviando código enquanto a equipe dorme.
Siga meu Substack para receber insights frescos sobre IA:
Esta é a configuração exata. Passo a passo. Da primeira chamada de API a um agente funcional que você pode apontar para qualquer tarefa.
Este artigo abordará:
1 - por que a maioria dos "agentes" que as pessoas constroem não são agentes
2 - as 5 partes que todo agente funcional precisa
3 - como construir cada parte com Claude, com código
4 - os erros que matam agentes antes de serem enviados
Marque isto. Todos os blocos de código abaixo funcionam.
01. A maioria dos "agentes de IA" não são agentes
Construí e quebrei mais agentes do que consigo contar. Observei eles queimarem tokens a noite toda e não produzirem nada. Observei eles reescreverem o mesmo arquivo 30 vezes. Observei eles passarem no próprio teste ao deletar o teste.

Cada falha me ensinou a mesma lição: o modelo não é o problema. A arquitetura ao redor dele é. Este guia é tudo que aprendi, comprimido no caminho mais curto que posso te dar.
Aqui está o que a maioria das pessoas constrói quando diz "agente de IA":
1while True:2 user_input = input("> ")3 response = call_claude(user_input)4 print(response)
Isso é um chatbot. Ele espera por você. Ele faz o que você manda. Ele esquece tudo entre sessões. Quando você fecha a aba, ele para.
Um agente é um sistema que trabalha em direção a um objetivo sem você sentado na frente dele. Ele descobre o que precisa ser feito, faz um plano, executa, verifica o resultado e, se não estiver pronto, tenta novamente. Você define a direção. O agente faz o trabalho.
"Claude Code foi de zero a US$ 400 milhões em receita em alguns meses. Começou como um projeto de hackathon. E ainda usa apenas a API pública." -
Boris Cherny, Head of Claude Code
A mesma API que você tem acesso agora. Os mesmos modelos. A diferença é a arquitetura ao redor do modelo.

02. As 5 partes de um agente real
Todo agente funcional — Claude Code, Devin, Codex, ou qualquer coisa que você construa — é montado a partir de cinco partes. Faltou uma, ele quebra.

03. A camada de API
Tudo começa aqui. Você chama Claude, Claude responde. Mas a forma como você o chama determina se você obtém um chatbot ou um agente.

Três coisas importam: o prompt de sistema, a saída estruturada e a temperatura.
O prompt de sistema não é uma saudação. É o manual de operação do seu agente. Cada regra, restrição e comportamento vai aqui. Sem ele, Claude adivinha o que você quer. Com ele, Claude segue sua especificação.
1import anthropic23client = anthropic.Anthropic()45response = client.messages.create(6 model="claude-sonnet-4-6",7 max_tokens=4096,8 system="""Você é um agente de revisão de código.910Regras:11- Leia todo o diff antes de comentar12- Sinalize apenas bugs reais, não preferências de estilo13- Se nada estiver errado, diga "LGTM" e pare14- Nunca sugira mudanças que você não testou mentalmente15- Formato de saída: array JSON de {file, line, issue, fix}""",16 messages=[{"role": "user", "content": diff_content}]17)
A saída estruturada torna a resposta do seu agente legível por máquina. Se Claude retorna texto livre, seu código precisa analisá-lo. Se Claude retorna JSON, seu código pode usá-lo diretamente.
1# Force a saída JSON informando a Claude o formato exato2system = """Retorne APENAS JSON válido. Sem markdown. Sem explicação.3Schema:4{5 "status": "pass" | "fail",6 "issues": [{"file": str, "line": int, "issue": str}],7 "summary": str8}"""
Temperatura. Defina como 0 para agentes determinísticos. Defina como 0.3-0.5 para trabalho criativo. O padrão (1.0) adiciona aleatoriedade que você quase nunca quer em um agente.
04. Ferramentas
Um modelo sem ferramentas pode raciocinar, mas não pode agir. Ele pode te dizer qual arquivo editar, mas não pode editá-lo. Ele pode descrever uma consulta, mas não pode executá-la.

O uso de ferramentas do Claude permite que você defina funções que o modelo pode chamar. Você descreve a função. Claude decide quando chamá-la. Você a executa e retorna o resultado. Claude usa o resultado para continuar raciocinando.
1tools = [{2 "name": "run_sql",3 "description": "Execute uma consulta SQL somente leitura no banco de dados",4 "input_schema": {5 "type": "object",6 "properties": {7 "query": {8 "type": "string",9 "description": "Consulta SQL SELECT a ser executada"10 }11 },12 "required": ["query"]13 }14},15{16 "name": "write_file",17 "description": "Escreva conteúdo em um arquivo no disco",18 "input_schema": {19 "type": "object",20 "properties": {21 "path": {"type": "string"},22 "content": {"type": "string"}23 },24 "required": ["path", "content"]25 }26}]
A descrição da ferramenta importa mais do que você imagina. Claude a lê para decidir quando e como usar a ferramenta. Uma descrição vaga significa chamadas erradas. Uma descrição precisa significa chamadas precisas.
Comece com 3 a 5 ferramentas. Ler arquivo, escrever arquivo, executar comando, pesquisar e uma ferramenta específica de domínio para o seu caso de uso. Isso cobre 90% das tarefas de agente.

05. O loop
Esta é a parte que transforma um script em um agente. Sem um loop, seu código chama Claude uma vez e para. Com um loop, seu código chama Claude, verifica o resultado e chama novamente até o trabalho ser concluído.

Três componentes:
- Verificador. Algo que verifica se a saída é boa. Um conjunto de testes, um verificador de tipos, um linter, uma segunda chamada ao Claude com critérios rigorosos. Sem isso, você tem o agente concordando consigo mesmo repetidamente.
- Estado. Um registro do que aconteceu. O que funcionou, o que falhou, o que tentar a seguir. Sem estado, o agente comete o mesmo erro em cada passagem.
- Condição de parada. A meta é atingida, ou um limite rígido diz "após N tentativas, pare e relate". Sem isso, o loop roda para sempre e drena sua conta.
1import json2from pathlib import Path34def run_agent(task: str, max_attempts: int = 5):5 state = {"task": task, "attempts": [], "done": False}67 for i in range(max_attempts):8 # Construir contexto a partir do estado9 context = build_prompt(state)1011 # Chamar Claude com ferramentas12 result = call_claude(context, tools)1314 # Executar quaisquer chamadas de ferramenta15 output = execute_tools(result)1617 # Verificar o resultado18 check = verify(output)1920 # Atualizar estado21 state["attempts"].append({22 "attempt": i + 1,23 "action": result.summary,24 "passed": check.passed,25 "reason": check.reason26 })2728 if check.passed:29 state["done"] = True30 break3132 # Salvar estado para a próxima execução33 Path("state.json").write_text(json.dumps(state, indent=2))34 return state
Este é o esqueleto completo. Todo agente de produção é uma variação desse padrão. Os detalhes mudam. A forma não.
06. Memória
Sem memória, cada sessão começa do zero. O agente redescobre a estrutura do seu projeto. Reaprende suas convenções. Comete novamente os erros que cometeu ontem.

Os agentes Claude usam três camadas de memória:
CLAUDE.md é um arquivo markdown na raiz do seu projeto. O Claude Code o lê automaticamente no início de cada sessão. Suas regras, sua stack, suas convenções. Escreva uma vez, leia para sempre.
1# CLAUDE.md23## Projeto4API de gerenciamento de tarefas. Python 3.12, FastAPI, PostgreSQL.56## Regras7- Todas as respostas: schema {data, error, meta}8- Testes obrigatórios para cada novo endpoint9- Mensagens de commit: tipo(escopo): descrição10- Nunca use print() para logging. Use structlog.1112## Problemas conhecidos13- Middleware de autenticação espera x-auth-token, não Authorization14- Suite de testes leva 45s completo. Use --filter para iteração.
Habilidades capturam fluxos de trabalho inteiros. Não apenas prompts — a forma completa: formato de entrada, etapas, formato de saída, regras de validação. A primeira execução leva 20 minutos. A repetição leva 30 segundos.
Arquivo de aprendizados é um registro contínuo de erros. O agente escreve nele após cada sessão. A próxima sessão o lê. Erros se repetem até serem registrados. Então param.
1# learnings.md23- A API de pagamento espera chave de idempotência no cabeçalho, não no corpo4- PostgreSQL NOTIFY precisa de LISTEN explícito no pool de conexões5- O limitador de taxa conta por chave, não por IP. Testes precisam de chaves únicas.
07. A porta de verificação
A porta é a parte mais difícil de construir e a mais fácil de pular. A maioria das pessoas a pula. É por isso que a maioria dos agentes quebra em produção.

Uma porta de verificação é algo que verifica o trabalho do agente sem que o agente se avalie. O modelo que escreveu o código é generoso demais ao corrigir seu próprio dever de casa. Você precisa de uma segunda verificação.
Três padrões que funcionam:
1. Testes automatizados. O agente escreve código. A suíte de testes é executada. Se os testes falharem, o agente recebe a saída do erro e tenta novamente. É assim que o Claude Code funciona internamente.
1def verify(output):2 # Executar a suíte de testes3 result = subprocess.run(4 ["pytest", "tests/", "-x", "--tb=short"],5 capture_output=True, text=True6 )7 return {8 "passed": result.returncode == 0,9 "reason": result.stdout if result.returncode != 0 else "all tests pass"10 }
2. Verificador de tipos / linter. Execute mypy, ruff ou tsc --noEmit após cada alteração. Captura categorias inteiras de bugs sem escrever um único teste.
3. Segundo modelo como revisor. Use uma chamada separada ao Claude com um prompt de sistema rigoroso que apenas procura problemas. O escritor é rápido e barato. O revisor é lento e rigoroso. Essa separação é a maior parte da qualidade.
1# Prompt do revisor - separado do construtor2reviewer_system = """Você é um revisor de código rigoroso.3Seu ÚNICO trabalho é encontrar problemas.45Verifique:6- O código corresponde à especificação?7- Existem casos extremos não capturados?8- Todos os testes realmente testam a coisa certa?910Se tudo estiver correto, responda: {"passed": true}11Se algo estiver errado, responda: {"passed": false, "issues": [...]}1213Não sugira melhorias. Apenas sinalize bugs reais."""
O escritor é rápido e barato. O revisor é lento e rigoroso. Essa separação é a maior parte da qualidade.
08. Juntando tudo
Aqui está um agente completo que pega a URL de uma issue do GitHub, lê a issue, escreve o código, executa os testes e abre um PR. Cinco partes trabalhando juntas.
1import anthropic, subprocess, json2from pathlib import Path34client = anthropic.Anthropic()5CLAUDE_MD = Path("CLAUDE.md").read_text()6LEARNINGS = Path("learnings.md").read_text()78SYSTEM = f"""Você é um agente de codificação.9Leia a issue. Escreva a correção. Execute os testes.1011Contexto do projeto:12{CLAUDE_MD}1314Problemas conhecidos:15{LEARNINGS}1617Regras:18- Leia a base de código completa antes de alterar qualquer coisa19- Escreva testes para cada alteração20- Se os testes falharem, corrija o código, não os testes21- Pare quando todos os testes passarem"""2223TOOLS = [24 read_file_tool,25 write_file_tool,26 run_command_tool,27 search_codebase_tool,28]2930def run(issue_text, max_attempts=5):31 messages = [{"role": "user", "content": issue_text}]3233 for attempt in range(max_attempts):34 # Chamar Claude35 response = client.messages.create(36 model="claude-sonnet-4-6",37 max_tokens=8192,38 system=SYSTEM,39 tools=TOOLS,40 messages=messages41 )4243 # Executar chamadas de ferramenta44 messages = handle_tool_use(response, messages)4546 # Verificar: executar testes47 test_result = subprocess.run(48 ["pytest", "-x", "--tb=short"],49 capture_output=True, text=True50 )5152 if test_result.returncode == 0:53 print(f"Concluído em {attempt + 1} tentativas")54 return True5556 # Alimentar falha de volta no loop57 messages.append({58 "role": "user",59 "content": f"Testes falharam:\n{test_result.stdout}\nCorrija e tente novamente."60 })6162 return False
Isso é um agente funcional. Camada de API com prompt de sistema e CLAUDE.md. Ferramentas para operações de arquivo. Um loop com repetição. Memória do learnings.md. Uma porta de verificação via pytest.
Menos de 50 linhas. A mesma arquitetura que o Claude Code usa internamente.
**
09. Os 5 erros que quebram todo agente
- Sem porta de verificação. O agente corrige seu próprio dever de casa. Ele escreve código, diz "parece bom" e segue em frente. A saída parece certa e quebra em produção.
- Sem condição de parada. O loop roda até sua conta da API chegar a US$ 200. Sem um limite rígido, o agente tenta para sempre, reescrevendo o mesmo arquivo 40 vezes. Sempre defina max_attempts. Sempre.
- Sem arquivo de estado. Mesmo erro na tentativa #1 e na tentativa #50. O agente não sabe o que já tentou. Ele propõe a mesma correção quebrada três vezes seguidas porque nada registra a falha.
- Ferramentas demais. Você dá 20 ferramentas a Claude e ele escolhe a errada. Um modelo com 5 ferramentas claras faz escolhas melhores do que um modelo com 20 sobrepostas. Comece pequeno. Adicione ferramentas apenas quando o agente bater em uma parede.
- Prompt de sistema vago. "Seja um bom assistente de codificação" te dá uma saída genérica. "Todas as respostas devem ser JSON válido, testes obrigatórios para cada alteração, nunca modifique arquivos fora de /src" te dá um agente que se comporta.
Conclusão:
Um agente funcional não é um prompt melhor. É um sistema: API + ferramentas + loop + memória + porta de verificação. Cinco partes. Faltou uma, ele quebra.
A maioria das pessoas lerá isto, marcará e continuará usando Claude como chatbot. Elas vão colar uma pergunta de cada vez e copiar a resposta para a base de código manualmente.
Aqueles que construírem o loop vão entregar trabalho enquanto dormem. Mesmo modelo. Mesma API. Mesmo preço. Arquitetura diferente.
Os blocos de código acima funcionam. Copie-os. Execute-os. Modifique-os para seu caso de uso.
Construa um agente esta semana. Aponte-o para uma tarefa que você faz todos os dias. Deixe-o rodar.





