Resumo
O vazamento do código-fonte do Claude expôs uma base de código TypeScript de 512.000 linhas em 31 de março de 2026. A arquitetura se resume a um loop `while` que chama a API do Claude, despacha chamadas de ferramentas e alimenta os resultados de volta. Você pode construir sua própria versão com Python, o SDK Anthropic e cerca de 200 linhas de código para o loop central. Este guia detalha cada componente e mostra como recriá-los.
Introdução
Em 31 de março de 2026, a Anthropic enviou um arquivo de mapa de origem de 59,8 MB dentro da versão 2.1.88 de seu pacote npm @anthropic-ai/claude-code. Mapas de origem são artefatos de depuração que revertem JavaScript minificado de volta ao código-fonte original. Como a ferramenta de construção da Anthropic (o bundler do Bun) os gera por padrão, toda a base de código TypeScript foi recuperável.
Em questão de horas, desenvolvedores espelharam o código em dezenas de repositórios GitHub. A comunidade rapidamente dissecou cada módulo, desde o loop do agente mestre até recursos ocultos como "modo disfarçado" e injeção de ferramenta falsa.
A reação foi dividida. Alguns criticaram as práticas de segurança da Anthropic. Outros ficaram fascinados pela arquitetura. Mas a resposta mais produtiva veio de desenvolvedores que perguntaram: "Posso construir isso sozinho?"
A resposta é sim. Os padrões centrais são simples. Este guia percorre cada camada arquitetônica, explica por que a Anthropic fez as escolhas que fez e fornece código funcional que você pode usar como ponto de partida. Você também aprenderá como testar as interações de API do seu agente personalizado com o Apidog, o que torna a depuração de conversas de API multi-turn muito mais fácil do que comandos curl brutos.
O que o vazamento revelou sobre a arquitetura do Claude Code
A base de código em um piscar de olhos
O Claude Code, internamente codinome "Tengu", abrange cerca de 1.900 arquivos. A organização do módulo se divide em camadas claras:
cli/ - Interface de Terminal (React + Ink)
tools/ - Mais de 40 implementações de ferramentas
core/ - Prompts de sistema, permissões, constantes
assistant/ - Orquestração de agente
services/ - Chamadas de API, compactação, OAuth, telemetria
O CLI em si é um aplicativo React renderizado via Ink, um renderizador React para saída de terminal. Ele usa Yoga (um motor flexbox CSS) para layout e códigos de escape ANSI para estilização. Cada visualização de conversação, área de entrada, exibição de chamada de ferramenta e caixa de diálogo de permissão é um componente React.
Isso é superprojetado para a maioria dos projetos DIY. Você não precisa de uma interface de terminal baseada em React para construir um agente de codificação funcional. Um loop REPL simples funciona bem.
O loop mestre do agente
Remova a interface do usuário, a telemetria e os sinalizadores de recursos, e o núcleo do Claude Code é um loop `while`. A Anthropic o chama internamente de "nO". Veja o que ele faz:
- Envia mensagens para a API do Claude (prompt de sistema + definições de ferramentas)
- Recebe uma resposta contendo texto e/ou blocos
tool_use - Executa cada ferramenta solicitada por meio de um mapa de despacho nome-para-manipulador
- Adiciona os resultados da ferramenta de volta à lista de mensagens
- Se a resposta contiver mais chamadas de ferramentas, volta para a etapa 1
- Se a resposta for texto simples sem chamadas de ferramentas, retorna para o usuário
Um "turn" (turno) é uma rodada completa. Os turnos continuam até que o Claude produza texto sem invocações de ferramentas. Esse é o padrão completo do agente.
Aqui está uma versão mínima em Python que captura o núcleo:
import anthropic
client = anthropic.Anthropic()
MODEL = "claude-sonnet-4-6"
def agent_loop(system_prompt: str, tools: list, messages: list) -> str:
"""The core agent loop - keep calling until no more tool use."""
while True:
response = client.messages.create(
model=MODEL,
max_tokens=16384,
system=system_prompt,
tools=tools,
messages=messages,
)
# Add assistant response to conversation
messages.append({"role": "assistant", "content": response.content})
# If the model stopped without requesting tools, we're done
if response.stop_reason != "tool_use":
# Extract the final text
return "".join(
block.text for block in response.content
if hasattr(block, "text")
)
# Execute each tool call and collect results
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result,
})
# Feed results back as a user message
messages.append({"role": "user", "content": tool_results})
Isso são cerca de 30 linhas. O restante da complexidade do Claude Code vem das próprias ferramentas, do sistema de permissão, do gerenciamento de contexto e da memória.
Construindo o sistema de ferramentas
Por que ferramentas dedicadas superam um único comando bash
Uma das decisões arquitetônicas mais claras no vazamento: o Claude Code usa ferramentas dedicadas para operações de arquivo em vez de rotear tudo via bash.
Existe uma ferramenta Read (não cat), uma ferramenta Edit (não sed), uma ferramenta Grep (não grep) e uma ferramenta Glob (não find). O prompt do sistema diz explicitamente ao modelo para preferir estas em vez de equivalentes bash.
Por quê? Três razões:
- Saída estruturada. Uma ferramenta
Grepdedicada retorna resultados em um formato consistente que o modelo pode analisar. Comandos bash em pipeline produzem uma saída imprevisível que o modelo tem dificuldade em interpretar. - Segurança. A
BashToolno Claude Code bloqueia backticks e sintaxe de subshell$()para evitar injeção. Ferramentas dedicadas contornam esse risco completamente. - Eficiência de tokens. Os resultados da ferramenta podem ser truncados, amostrados ou descarregados para o disco. Grandes saídas de
catdesperdiçam tokens da janela de contexto.
O conjunto de ferramentas essencial
Pelo vazamento, o Claude Code expõe menos de 20 ferramentas por padrão, com mais de 60 atrás de sinalizadores de recursos. Para um agente DIY, você precisa de cinco:
TOOLS = [
{
"name": "read_file",
"description": "Read a file from the filesystem. Returns contents with line numbers.",
"input_schema": {
"type": "object",
"properties": {
"file_path": {
"type": "string",
"description": "Absolute path to the file"
},
"offset": {
"type": "integer",
"description": "Line number to start reading from (0-indexed)"
},
"limit": {
"type": "integer",
"description": "Max lines to read. Defaults to 2000."
}
},
"required": ["file_path"]
}
},
{
"name": "write_file",
"description": "Write content to a file. Creates the file if it doesn't exist.",
"input_schema": {
"type": "object",
"properties": {
"file_path": {"type": "string", "description": "Absolute path"},
"content": {"type": "string", "description": "File content to write"}
},
"required": ["file_path", "content"]
}
},
{
"name": "edit_file",
"description": "Replace a specific string in a file. The old_string must be unique.",
"input_schema": {
"type": "object",
"properties": {
"file_path": {"type": "string", "description": "Absolute path"},
"old_string": {"type": "string", "description": "Text to find"},
"new_string": {"type": "string", "description": "Replacement text"}
},
"required": ["file_path", "old_string", "new_string"]
}
},
{
"name": "run_command",
"description": "Execute a shell command and return stdout/stderr.",
"input_schema": {
"type": "object",
"properties": {
"command": {"type": "string", "description": "Shell command to run"},
"timeout": {"type": "integer", "description": "Timeout in seconds. Default 120."}
},
"required": ["command"]
}
},
{
"name": "search_code",
"description": "Search for a regex pattern across files in a directory.",
"input_schema": {
"type": "object",
"properties": {
"pattern": {"type": "string", "description": "Regex pattern"},
"path": {"type": "string", "description": "Directory to search"},
"file_glob": {"type": "string", "description": "File pattern filter, e.g. '*.py'"}
},
"required": ["pattern"]
}
}
]
Despacho do manipulador de ferramentas
A função de execução da ferramenta mapeia nomes de ferramentas para funções manipuladoras:
import subprocess
import os
import re
def execute_tool(name: str, params: dict) -> str:
"""Dispatch tool calls to their handlers."""
handlers = {
"read_file": handle_read_file,
"write_file": handle_write_file,
"edit_file": handle_edit_file,
"run_command": handle_run_command,
"search_code": handle_search_code,
}
handler = handlers.get(name)
if not handler:
return f"Error: Unknown tool '{name}'"
try:
return handler(params)
except Exception as e:
return f"Error: {str(e)}"
def handle_read_file(params: dict) -> str:
path = params["file_path"]
offset = params.get("offset", 0)
limit = params.get("limit", 2000)
with open(path, "r") as f:
lines = f.readlines()
selected = lines[offset:offset + limit]
numbered = [f"{i + offset + 1}\t{line}" for i, line in enumerate(selected)]
return "".join(numbered)
def handle_write_file(params: dict) -> str:
path = params["file_path"]
os.makedirs(os.path.dirname(path), exist_ok=True)
with open(path, "w") as f:
f.write(params["content"])
return f"Successfully wrote to {path}"
def handle_edit_file(params: dict) -> str:
path = params["file_path"]
with open(path, "r") as f:
content = f.read()
old = params["old_string"]
if content.count(old) == 0:
return f"Error: '{old[:50]}...' not found in {path}"
if content.count(old) > 1:
return f"Error: '{old[:50]}...' matches {content.count(old)} locations. Be more specific."
new_content = content.replace(old, params["new_string"], 1)
with open(path, "w") as f:
f.write(new_content)
return f"Successfully edited {path}"
def handle_run_command(params: dict) -> str:
cmd = params["command"]
timeout = params.get("timeout", 120)
# Basic safety: block dangerous patterns
blocked = ["rm -rf /", "mkfs", "> /dev/"]
for pattern in blocked:
if pattern in cmd:
return f"Error: Blocked dangerous command pattern: {pattern}"
result = subprocess.run(
cmd, shell=True, capture_output=True, text=True,
timeout=timeout, cwd=os.getcwd()
)
output = ""
if result.stdout:
output += result.stdout
if result.stderr:
output += f"\nSTDERR:\n{result.stderr}"
if not output.strip():
output = f"Command completed with exit code {result.returncode}"
# Truncate large outputs to save context tokens
if len(output) > 30000:
output = output[:15000] + "\n\n... [truncated] ...\n\n" + output[-15000:]
return output
def handle_search_code(params: dict) -> str:
pattern = params["pattern"]
path = params.get("path", os.getcwd())
file_glob = params.get("file_glob", "")
cmd = ["grep", "-rn", "--include", file_glob, pattern, path] if file_glob else \
["grep", "-rn", pattern, path]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
if not result.stdout.strip():
return f"No matches found for pattern: {pattern}"
lines = result.stdout.strip().split("\n")
if len(lines) > 50:
return "\n".join(lines[:50]) + f"\n\n... ({len(lines) - 50} more matches)"
return result.stdout
Gerenciamento de contexto: o problema difícil
Por que o contexto importa mais do que a engenharia de prompt
O código-fonte vazado revela que o Claude Code dedica mais esforço de engenharia ao gerenciamento de contexto do que ao próprio prompt do sistema. O compressor de contexto (chamado internamente de "wU2") possui cinco estratégias.
Para uma construção DIY, você precisa de duas:
Auto-compactação é acionada quando a conversa se aproxima do limite da janela de contexto. O Claude Code dispara em aproximadamente 92% de uso, reservando um buffer de 13.000 tokens para o próprio resumo.
A reinjeção de CLAUDE.md garante que as diretrizes do projeto não se desviem durante longas sessões. O Claude Code reinjeta a configuração do projeto a cada turno, não na inicialização. Este é o padrão mais impactante para manter um agente de codificação no caminho certo.
Construindo um compressor simples
def maybe_compact(messages: list, system_prompt: str, max_tokens: int = 180000) -> list:
"""Compact conversation when it gets too long."""
# Rough estimate: 4 chars per token
total_chars = sum(
len(str(m.get("content", ""))) for m in messages
)
estimated_tokens = total_chars // 4
if estimated_tokens < max_tokens * 0.85:
return messages # Not yet at the limit
# Ask the model to summarize the conversation so far
summary_response = client.messages.create(
model=MODEL,
max_tokens=4096,
system="Summarize this conversation. Keep all file paths, decisions made, errors encountered, and current task state. Be specific about what was changed and why.",
messages=messages,
)
summary_text = summary_response.content[0].text
# Replace conversation with summary + recent messages
compacted = [
{"role": "user", "content": f"[Conversation summary]\n{summary_text}"},
{"role": "assistant", "content": "I have the context from our previous conversation. What should I work on next?"},
]
# Keep the last 4 messages for immediate context
compacted.extend(messages[-4:])
return compacted
Reinjetando contexto do projeto
O Claude Code lê .claude/CLAUDE.md e o injeta em cada turno. Veja como replicá-lo:
def build_system_prompt(project_dir: str) -> str:
"""Build system prompt with project context re-injection."""
base_prompt = """You are a coding assistant that helps with software engineering tasks.
You have access to tools for reading, writing, editing files, running commands, and searching code.
Always read files before modifying them. Prefer edit_file over write_file for existing files.
Keep responses concise. Focus on the code, not explanations."""
# Look for project guidelines
claude_md_path = os.path.join(project_dir, ".claude", "CLAUDE.md")
if os.path.exists(claude_md_path):
with open(claude_md_path, "r") as f:
project_context = f.read()
base_prompt += f"\n\n# Project guidelines\n{project_context}"
# Also check for a root CLAUDE.md
root_md = os.path.join(project_dir, "CLAUDE.md")
if os.path.exists(root_md):
with open(root_md, "r") as f:
root_context = f.read()
base_prompt += f"\n\n# Repository guidelines\n{root_context}"
return base_prompt
O sistema de memória de três camadas
O código-fonte vazado mostra que o Claude Code usa uma arquitetura de memória de três níveis. Esta é uma das partes mais subestimadas do sistema.
Camada 1: MEMORY.md (sempre carregado)
Um índice leve que permanece no prompt do sistema o tempo todo. Cada entrada tem uma linha, com menos de 150 caracteres. Atua como um sumário apontando para um conhecimento mais profundo. Limitado a 200 linhas / 25KB.
- [User preferences](memory/user-prefs.md) - prefers TypeScript, uses Vim keybindings
- [API conventions](memory/api-conventions.md) - REST with JSON:API spec, snake_case
- [Deploy process](memory/deploy.md) - uses GitHub Actions, deploys to AWS EKS
Camada 2: arquivos de tópico (carregados sob demanda)
Arquivos de conhecimento detalhados carregados quando o índice sugere relevância. Estes contêm convenções de projeto, decisões arquitetônicas e padrões aprendidos.
Camada 3: transcrições de sessão (pesquisadas, nunca lidas)
Logs de sessão completos que nunca são carregados integralmente. O agente os pesquisa por identificadores específicos. Isso evita o inchaço do contexto, preservando a capacidade de pesquisa.
Construindo um sistema de memória mínimo
import json
MEMORY_DIR = ".agent/memory"
def load_memory_index() -> str:
"""Load the memory index for system prompt injection."""
index_path = os.path.join(MEMORY_DIR, "MEMORY.md")
if os.path.exists(index_path):
with open(index_path, "r") as f:
return f.read()
return ""
def save_memory(key: str, content: str, description: str):
"""Save a memory entry and update the index."""
os.makedirs(MEMORY_DIR, exist_ok=True)
# Write the memory file
filename = f"{key.replace(' ', '-').lower()}.md"
filepath = os.path.join(MEMORY_DIR, filename)
with open(filepath, "w") as f:
f.write(f"---\nname: {key}\ndescription: {description}\n---\n\n{content}")
# Update the index
index_path = os.path.join(MEMORY_DIR, "MEMORY.md")
index_lines = []
if os.path.exists(index_path):
with open(index_path, "r") as f:
index_lines = f.readlines()
# Add or update entry
new_entry = f"- [{key}]({filename}) - {description}\n"
updated = False
for i, line in enumerate(index_lines):
if filename in line:
index_lines[i] = new_entry
updated = True
break
if not updated:
index_lines.append(new_entry)
with open(index_path, "w") as f:
f.writelines(index_lines)
Adicione uma ferramenta save_memory à sua lista de ferramentas para que o agente possa persistir o conhecimento entre as sessões.
Adicionando um sistema de permissões
O vazamento revela cinco modos de permissão: default (prompts interativos), auto (aprovação baseada em ML), bypass, yolo (aprovar tudo) e deny. Cada ação da ferramenta é classificada como risco BAIXO, MÉDIO ou ALTO.
Para um agente DIY, um sistema simples de três níveis funciona:
# Risk levels for operations
RISK_LEVELS = {
"read_file": "low",
"search_code": "low",
"edit_file": "medium",
"write_file": "medium",
"run_command": "high",
}
def check_permission(tool_name: str, params: dict, auto_approve_low: bool = True) -> bool:
"""Check if the user approves this tool call."""
risk = RISK_LEVELS.get(tool_name, "high")
if risk == "low" and auto_approve_low:
return True
# Show the user what's about to happen
print(f"\n--- Permission check ({risk.upper()} risk) ---")
print(f"Tool: {tool_name}")
for key, value in params.items():
display = str(value)[:200]
print(f" {key}: {display}")
response = input("Allow? [y/n/always]: ").strip().lower()
if response == "always":
RISK_LEVELS[tool_name] = "low" # Auto-approve this tool going forward
return True
return response == "y"
Testando as chamadas de API do seu agente com o Apidog
Construir um agente de codificação significa fazer centenas de chamadas de API para o Claude. Depurar essas interações, especialmente conversas multi-turn com uso de ferramentas, é doloroso com logs brutos.

Apidog ajuda você a inspecionar e testar as requisições exatas de API que seu agente envia. Veja como usá-lo durante o desenvolvimento:
Capture e repita requisições de API
Configure o Apidog como um proxy para interceptar as chamadas do seu agente para a API Anthropic:
- Abra o Apidog e crie um novo projeto para seu agente
- Importe o endpoint da API Anthropic Messages:
POST https://api.anthropic.com/v1/messages - Configure o corpo da requisição com seu prompt de sistema, array de ferramentas e mensagens
- Teste turnos individuais repetindo requisições capturadas com parâmetros modificados
Isso permite isolar turnos específicos de uso de ferramentas sem executar o loop completo do agente. Quando o modelo retorna uma chamada de ferramenta inesperada ou um parâmetro alucinado, você pode modificar o corpo da requisição no editor visual do Apidog e reenviá-lo para ver como diferentes entradas mudam a resposta.
Depure conversas multi-turn
A parte mais difícil da depuração de agentes é reproduzir um estado de conversa. As variáveis de ambiente do Apidog permitem salvar instantâneos da conversa:
- Salve o array completo de
messagescomo uma variável de ambiente após cada turno - Repita a partir de qualquer ponto da conversa
- Compare os resultados das ferramentas entre as execuções para encontrar onde o comportamento diverge
Valide esquemas de ferramentas
Suas definições de ferramentas (os esquemas JSON que você passa para a API) determinam o que o modelo pode solicitar. Esquemas malformados causam falhas silenciosas onde o modelo ignora uma ferramenta ou passa parâmetros errados.
Importe seus esquemas de ferramentas para o Apidog e use seu validador de Esquema JSON para identificar problemas antes que cheguem à API. Baixe o Apidog para começar a depurar as interações de API do seu agente.
Juntando tudo: o REPL completo
Aqui está o agente completo, conectado como um REPL funcional:
#!/usr/bin/env python3
"""A minimal Claude Code-style coding agent."""
import anthropic
import os
import sys
client = anthropic.Anthropic()
MODEL = "claude-sonnet-4-6"
PROJECT_DIR = os.getcwd()
def main():
system_prompt = build_system_prompt(PROJECT_DIR)
memory = load_memory_index()
if memory:
system_prompt += f"\n\n# Memory\n{memory}"
messages = []
print("Coding agent ready. Type 'quit' to exit.\n")
while True:
user_input = input("> ").strip()
if user_input.lower() in ("quit", "exit"):
break
if not user_input:
continue
messages.append({"role": "user", "content": user_input})
# Compact if needed
messages = maybe_compact(messages, system_prompt)
# Re-inject project context (Claude Code does this every turn)
current_system = build_system_prompt(PROJECT_DIR)
memory = load_memory_index()
if memory:
current_system += f"\n\n# Memory\n{memory}"
# Run the agent loop
result = agent_loop(current_system, TOOLS, messages)
print(f"\n{result}\n")
if __name__ == "__main__":
main()
Isso oferece um agente de codificação funcional em menos de 300 linhas de Python. Ele lê arquivos, edita código, executa comandos, pesquisa bases de código, gerencia o contexto e persiste a memória entre as sessões.
O que adicionar a seguir
O vazamento do código-fonte revela vários recursos que valem a pena construir assim que seu loop central estiver funcionando:
Subagentes para trabalho paralelo
O Claude Code gera subagentes (chamados de agentes "bifurcados") para tarefas independentes. O subagente recebe uma cópia do contexto pai, executa sua tarefa e retorna um resultado. Isso evita poluir a conversa principal com trabalho exploratório.
O padrão: gerar um novo agent_loop() com uma descrição de tarefa focada e um subconjunto de ferramentas. Retornar o resultado como uma string.
Deduplicação de leitura de arquivos
O Claude Code rastreia quais arquivos foram lidos e seus tempos de modificação. Se um arquivo não foi alterado desde a última leitura, ele ignora a leitura e informa ao modelo "arquivo inalterado desde a última leitura". Isso economiza tokens em releituras durante longas sessões.
Truncamento e amostragem de saída
Quando uma ferramenta retorna uma saída massiva (10.000+ linhas de resultados de grep, por exemplo), o Claude Code a trunca e informa ao modelo quantos resultados foram omitidos. Sem isso, um grande resultado de ferramenta pode consumir toda a sua janela de contexto.
Autocompactação com reinjeção de arquivos
O compressor vazado não descarta o conteúdo do arquivo. Após resumir a conversa, ele reinjeta o conteúdo dos arquivos acessados recentemente (até 5.000 tokens por arquivo). Isso significa que o modelo mantém conhecimento de trabalho da base de código mesmo após a compactação.
O que aprendemos com o vazamento
O vazamento do Claude Code confirmou vários padrões que a comunidade de agentes de IA havia teorizado:
O loop central é simples. Todo o padrão do agente se encaixa em 30 linhas. A complexidade reside nas ferramentas e no gerenciamento de contexto, não na engenharia de prompt.
Ferramentas dedicadas superam o bash. Ferramentas estruturadas e construídas para fins específicos fornecem ao modelo uma densidade de informações por token melhor do que o uso de comandos bash em pipeline.
A memória precisa de camadas. Um índice sempre carregado, arquivos de tópicos sob demanda e transcrições apenas pesquisáveis equilibram a recuperação de informações com os custos de contexto.
O arcabouço é o produto, não o modelo. O modelo fornece inteligência. O arcabouço fornece percepção (leitura de arquivos, pesquisa de código), ação (escrita de arquivos, execução de comandos) e memória. Construir um agente de codificação é construir o arcabouço.
Se você deseja testar e depurar as interações de API do seu agente personalizado, incluindo conversas multi-turn com uso de ferramentas, esquemas de solicitação complexos e validação de resposta, experimente o Apidog gratuitamente. Ele cuida da depuração da API para que você possa se concentrar na lógica do agente.
Perguntas Frequentes
Posso usar legalmente padrões do vazamento do Claude Code?
O vazamento expôs padrões arquitetônicos, não algoritmos proprietários. Construir um agente de codificação que usa um loop `while` com despacho de ferramentas é um padrão padrão documentado na própria documentação da API da Anthropic. Você não deve copiar o código da Anthropic literalmente, mas recriar a arquitetura com seu próprio código é uma prática padrão.
Qual modelo devo usar para um agente de codificação DIY?
Claude Sonnet 4.6 oferece o equilíbrio certo de velocidade e capacidade para tarefas de codificação. Claude Opus 4.6 produz melhores resultados em decisões de arquitetura complexas, mas custa mais e é mais lento. Para edições e pesquisas de arquivos simples, Claude Haiku 4.5 funciona e custa 90% menos.
Quanto custa para rodar seu próprio agente de codificação?
Uma sessão de codificação típica (30-50 turnos) com Claude Sonnet 4.6 custa de $1-5 em taxas de API. O principal fator de custo é o tamanho da janela de contexto; a compactação agressiva mantém os custos baixos. O código-fonte vazado do Claude Code mostra que ele aciona a compactação em 92% do uso de contexto para controlar isso.
Por que o Claude Code usa React para um aplicativo de terminal?
O Ink (React para terminais) permite que a equipe reutilize o modelo de componente e o gerenciamento de estado do React para interações complexas da UI, como caixas de diálogo de permissão, saída de streaming e exibições de chamadas de ferramentas. Para um projeto DIY, um simples REPL input() / print() é suficiente.
Qual é o recurso mais importante a ser construído após o loop principal?
O sistema de permissões. Sem ele, o modelo pode sobrescrever arquivos e executar comandos arbitrários sem a supervisão do usuário. Mesmo uma simples barreira "confirmar antes de gravar/executar" evita a maioria dos danos acidentais.
Como o Claude Code lida com erros de chamadas de ferramentas?
Os erros da ferramenta são retornados como conteúdo de texto na mensagem tool_result. O modelo vê o erro e decide se deve tentar novamente, tentar uma abordagem diferente ou perguntar ao usuário. Não há tratamento de erro especial; o raciocínio do modelo lida com a recuperação.
Posso usar isso com modelos diferentes do Claude?
Sim. O padrão de uso de ferramentas funciona com qualquer modelo que suporte chamadas de função: GPT-4, Gemini, Llama e outros. Você precisará adaptar o formato da chamada da API, mas o loop do agente, as ferramentas e o sistema de memória são agnósticos ao modelo.
Como evito que o agente execute comandos perigosos?
Comece com uma lista negra de padrões perigosos (rm -rf /, mkfs, etc.) e exija aprovação explícita para todas as chamadas run_command. O Claude Code classifica cada operação como risco BAIXO, MÉDIO ou ALTO e bloqueia ou solicita com base na classificação. Construa o mesmo para suas ferramentas.
