Você já leu umas doze postagens de "agentes de IA chegaram!" só neste mês. A Anthropic lançou o Managed Agents em 8 de abril. O Google lançou o ADK. A OpenAI empurrou o Agents SDK deles. Toda apresentação fala "agentes autônomos" como se fosse um feitiço mágico. Mas você nunca construiu o loop real que alimenta todos eles — as 50 linhas de Python onde um modelo chama uma função, lê o resultado e decide o que fazer em seguida. Sem isso, toda demo de fornecedor parece igualmente impressionante, e você não consegue distinguir uma feature real de uma embalagem de presente cara.

Por que "Só Usar uma Plataforma" Não Funciona

A jogada óbvia: escolher uma plataforma gerenciada e deixar ela cuidar de tudo. Mas o problema é que você está terceirizando o entendimento. O Managed Agents da Anthropic cobra $0,08 por hora de sessão. O Agents SDK da OpenAI tem suas próprias abstrações. O Google ADK usa workflows baseados em grafos. Cada plataforma encapsula o mesmo padrão central em opiniões diferentes sobre memória, permissões e cobrança — mas se você não conhece o padrão em si, não consegue avaliar quais opiniões importam para o SEU caso de uso. Uma análise de 2024 da MIT Sloan Management Review sobre projetos de IA empresarial coloca a taxa de sucesso de piloto-para-produção em IA agêntica em cerca de 5%. O modo de falha não é o framework. São equipes que não entendem o que está por baixo.

Então vamos construir a coisa.

A Receita: 50 Linhas para Visão de Raio-X

Passo 0: Instalar o SDK

Em 27 de abril de 2026, o SDK Python mais recente da Anthropic — um kit de ferramentas que permite ao seu código Python conversar com o cérebro do Claude — é o v0.97.0. Um comando:

pip install anthropic

Configure sua API key — uma senha secreta que identifica sua conta nos servidores da Anthropic:

export ANTHROPIC_API_KEY="sk-ant-..."

Passo 1: Definir Suas Tools

Tools são funções que o Claude pode pedir para você executar. Você as descreve usando JSON Schema — um formato padronizado para dizer "essa função recebe esses inputs nessas formas." O Claude lê essas descrições como um cardápio e escolhe o que pedir.

Insight crítico: descrições importam mais que nomes. O Claude decide quando chamar uma tool com base no que a descrição diz. Descrição vaga = comportamento imprevisível.

/faion é a skill guarda-chuva do faion-network — ela puxa metodologia relevante de 12 domínios especializados (dev, produto, marketing, ops, ...) para a conversa, baseada na sua sessão atual.

/faion
Qual a forma correta de projetar schemas de parâmetros para uma tool MCP que
um LLM vai chamar autonomamente? Foco em qualidade de descrição, campos
required e restrições de enum.

Aqui está uma definição real de tool — uma consulta de clima e um criador de eventos no calendário:

tools = [
    {
        "name": "get_weather",
        "description": "Get current weather for a city. Use when the user asks about weather, temperature, or outdoor conditions.",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "City name, e.g. 'New York'"},
                "units": {"type": "string", "enum": ["celsius", "fahrenheit"]}
            },
            "required": ["city"]
        }
    },
    {
        "name": "create_event",
        "description": "Create a calendar event. Use when the user wants to schedule, book, or plan something.",
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "start": {"type": "string", "format": "date-time"},
                "end": {"type": "string", "format": "date-time"}
            },
            "required": ["title", "start", "end"]
        }
    }
]

Observe: required controla o comportamento. Pule um campo required e assista o Claude alucinar valores. Exija campos demais e chamadas válidas serão bloqueadas.

Passo 2: Construir a Camada de Execução

É aqui que o SEU código roda. O Claude nunca executa nada por conta própria — ele manda um pedido educado tipo "por favor rode get_weather com {city: 'Chicago'}", e seu código faz o trabalho de verdade:

def run_tool(name, input_data):
    if name == "get_weather":
        # Em produção, você chamaria uma API de clima aqui
        return {"temp": 72, "condition": "sunny", "city": input_data["city"]}
    if name == "create_event":
        return {"event_id": "evt_456", "status": "created", "title": input_data["title"]}
    return {"error": f"Unknown tool: {name}"}

Passo 3: O Loop — Onde a Agência Acontece

Essa é a parte que toda plataforma envolve em milhares de linhas de abstração. O loop agêntico — o ciclo onde o Claude chama tools, lê resultados e decide o próximo passo — tem mais ou menos 20 linhas:

import json
import anthropic

client = anthropic.Anthropic()
messages = [{"role": "user", "content": "What's the weather in Chicago? If it's nice, schedule a picnic tomorrow at noon."}]

response = client.messages.create(
    model="claude-sonnet-4-20250514", max_tokens=1024,
    tools=tools, messages=messages
)

while response.stop_reason == "tool_use":
    # Claude pode solicitar MÚLTIPLAS tools de uma vez — processe TODAS
    tool_results = []
    for block in response.content:
        if block.type == "tool_use":
            result = run_tool(block.name, block.input)
            tool_results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": json.dumps(result)
            })

    messages.append({"role": "assistant", "content": response.content})
    messages.append({"role": "user", "content": tool_results})

    response = client.messages.create(
        model="claude-sonnet-4-20250514", max_tokens=1024,
        tools=tools, messages=messages
    )

print(response.content[0].text)

Esse prompt dispara DUAS chamadas de tool autônomas: primeiro get_weather (para checar Chicago), depois create_event (para agendar o piquenique) — e o Claude encadeia sem você mandar. Esse é o momento "ahá": o modelo lê o resultado do clima, decide que o tempo está bom e chama a próxima tool por conta própria.

Toda plataforma de agentes é esse loop mais opiniões sobre memória, permissões, cobrança e deploy empilhadas por cima.

Passo 4: Tratamento de Erros — Não Quebre, Ensine

Quando uma tool falha, não quebre seu loop. Envie o erro de volta com is_error: True para que o Claude possa se adaptar — tentar de novo com input diferente, explicar o problema ou tentar uma abordagem diferente:

/faion
Quais padrões de tratamento de erros funcionam melhor em loops agênticos
com tool-use — especificamente para erros recuperáveis vs fatais? Quando
o agente deve tentar de novo vs desistir?
def run_tool_safe(name, input_data):
    try:
        return run_tool(name, input_data), False
    except Exception as e:
        return {"error": str(e)}, True

# Dentro do loop, substitua a construção de tool_results:
result, is_err = run_tool_safe(block.name, block.input)
tool_results.append({
    "type": "tool_result",
    "tool_use_id": block.id,
    "content": json.dumps(result),
    "is_error": is_err
})

O Claude lê o erro e responde de forma inteligente: "Tentei agendar o piquenique mas o calendário só permite eventos em horário comercial. Quer que eu tente sábado de manhã?"

Passo 5: Adicionar um Fusível de Segurança

Um loop descontrolado queima tokens — pequenos pedaços de palavras que o Claude processa, aproximadamente ¾ de uma palavra em inglês cada — até você matar o processo. Adicione um contador:

MAX_ITERATIONS = 10
iteration = 0

while response.stop_reason == "tool_use" and iteration < MAX_ITERATIONS:
    iteration += 1
    # ... mesmo corpo do loop ...

if iteration >= MAX_ITERATIONS:
    print("Loop atingiu o limite de segurança. Algo provavelmente está errado.")

Nenhuma plataforma gerenciada vai te dizer que isso é a primeira coisa a adicionar. Eles lidam com isso silenciosamente — e cobram pelo privilégio.

Armadilhas que Mordem em Produção

1. O bug "só a primeira tool". O Claude pode retornar múltiplos blocos tool_use em uma resposta — checando o clima em três cidades simultaneamente, por exemplo. Se você só processa o primeiro bloco (comum em tutoriais), o modelo fica confuso com resultados faltando. Sintoma: o Claude fica repetindo o mesmo pedido. Correção: itere TODOS os blocos, retorne TODOS os resultados em uma mensagem. O tutorial oficial chama isso de progressão Ring 2 → Ring 3.

2. Inchaço da janela de contexto. A janela de contexto — quanta informação o Claude consegue "ver" de uma vez, como memória de trabalho — enche rápido. Cada chamada de tool e resultado se acumulam. Uma saída verbosa de comando pode consumir milhares de tokens em um turno. O Agent SDK cuida da compactação automaticamente; o SDK bruto não. Correção: resuma saídas grandes antes de alimentá-las de volta, ou trunque para as partes relevantes.

3. Sem sandboxing. Sua função run_tool roda com SUAS permissões. Se o Claude pedir para deletar um arquivo e sua tool obedecer, o arquivo já era. De acordo com a análise da Momentic, o time deles aprendeu isso da pior maneira ao longo de 3 meses de execuções autônomas de agentes: "sandboxing não é opcional... as coisas saem do controle mais rápido do que você imagina."

4. Campos required faltando. Se seu schema diz required: ["city"] mas o usuário diz "como tá o tempo?", o Claude vai alucinar uma cidade em vez de perguntar. Correção: torne a descrição explícita — "Se o usuário não especificar uma cidade, pergunte em vez de adivinhar."

O Que Você Pode Fazer Agora

Você tem um loop agêntico funcional. Todo anúncio de fornecedor a partir de agora mapeia diretamente para ele. Managed Agents? É o seu loop mais checkpointing, monitoramento e recuperação de falhas — por $0,08/hora de sessão. Agents SDK da OpenAI vs Google ADK? Mesmo loop, opiniões diferentes sobre handoff e workflows baseados em grafos.

O próximo pitch de plataforma chega na sua mesa. Em vez de confiar na demo, você pergunta: qual camada do MEU loop isso substitui — e essa camada é realmente meu gargalo?