Python + Anthropic API Projeto 1 de 4

Projeto 1: Agente do Zero

Construa um agente de IA funcional do zero, sem frameworks externos, usando apenas a Anthropic API. Você entenderá o loop agentic completo — Pensar, Agir, Observar — implementando manualmente o ciclo de function calling.

Iniciante
~2h estimado
Python 3.10+

Baixar Projeto Completo

Todos os arquivos prontos — extraia e comece em minutos

↓ Download ZIP

⚡ Execute em 3 passos

  1. 1

    Instale as dependências

    pip install -r requirements.txt
  2. 2

    Configure sua chave Anthropic

    cp .env.example .env # abra o .env e coloque sua ANTHROPIC_API_KEY
  3. 3

    Execute o agente

    python agent.py

Sem Python? Baixe em python.org. Sem chave Anthropic? Crie em console.anthropic.com.

Arquivos do Projeto

agent.py

Principal

Loop agentic + ferramentas + dispatcher

requirements.txt

Dependências

anthropic, python-dotenv

.env.example

Configuração

Template de variáveis de ambiente

index.html

Este guia

Documentação interativa do projeto

Guia Passo a Passo

Clique em cada tópico para expandir o conteúdo.

O que é

A etapa de instalação configura o ambiente Python isolado com as dependências corretas e a chave de API da Anthropic. Um ambiente limpo garante que seu agente rode de forma reproduzível em qualquer máquina — do seu laptop até servidores de produção.

Por que aprender

Gerenciar dependências e segredos de forma correta é a base de qualquer projeto de IA em produção. Variáveis de ambiente evitam que chaves de API sejam expostas em commits do Git — um erro que pode custar caro se sua chave for comprometida.

Conceitos-chave

Ambiente Virtual (venv)

Isola as dependências do projeto das bibliotecas globais do sistema.

python-dotenv

Carrega variáveis do arquivo .env para os.environ automaticamente.

ANTHROPIC_API_KEY

Chave de autenticação obtida em console.anthropic.com. Nunca commite no Git.

Comandos de instalação

# 1. Crie o ambiente virtual
python3 -m venv .venv
source .venv/bin/activate # Linux/Mac
# .venv\Scripts\activate # Windows
# 2. Instale as dependências
pip install -r requirements.txt
# 3. Configure as variáveis de ambiente
cp .env.example .env
# Edite .env e adicione sua ANTHROPIC_API_KEY

Estrutura de arquivos

projeto-1-agente-zero/
├── agent.py # Agente principal
├── requirements.txt # Dependências
├── .env.example # Template de secrets
├── .env # Seus secrets (não commite!)
└── index.html # Este guia

O que é

Ferramentas (tools) são capacidades externas que o modelo de linguagem pode invocar. Cada ferramenta é descrita por um schema JSON que especifica nome, descrição e parâmetros. O Claude decide quando e como chamar cada ferramenta com base no contexto da conversa.

Por que aprender

Ferramentas transformam um LLM passivo em um agente ativo. Sem elas, o modelo só pode gerar texto. Com ferramentas, ele pode buscar dados em tempo real, executar código, chamar APIs externas e persistir informações — tornando-o genuinamente útil.

Conceitos-chave

input_schema

JSON Schema que define os parâmetros aceitos pela ferramenta. O Claude gera inputs válidos automaticamente.

description

Texto em linguagem natural que explica ao modelo quando usar a ferramenta. Quanto mais clara, melhor a decisão.

tool_use block

Quando o Claude decide usar uma ferramenta, ele retorna um bloco tool_use com id, nome e inputs.

Exemplo de schema

tools = [
{
"name": "calcular",
"description": "Executa cálculos matemáticos",
"input_schema": {
"type": "object",
"properties": {
"expressao": {
"type": "string",
"description": "Ex: '2 + 2'"
}
},
"required": ["expressao"]
}
}
]

O que é

O dispatcher é a função responsável por receber o nome da ferramenta solicitada pelo modelo e rotear a execução para a função Python correta. Ele age como um intermediário entre as decisões do Claude e as implementações reais das ferramentas.

Por que aprender

Sem um dispatcher, o loop agentic seria caótico. Centralizar a lógica de roteamento facilita adicionar novas ferramentas, tratar erros de forma uniforme e registrar (logar) todas as chamadas para debugging e auditoria.

Conceitos-chave

Roteamento por nome

O dispatcher usa if/elif ou um dicionário de funções para mapear nomes de ferramentas para implementações.

Tratamento de erros

Sempre retorne uma string descritiva de erro — o modelo usará essa informação para corrigir a chamada na próxima iteração.

eval() seguro

Use eval(expr, {"__builtins__": {}}) para bloquear funções perigosas em avaliação de expressões matemáticas.

Implementação do dispatcher

def executar_ferramenta(nome: str, inputs: dict) -> str:
"""Despacha a ferramenta correta."""
if nome == "calcular":
try:
resultado = eval(inputs["expressao"],
{"__builtins__": {}})
return f"Resultado: {resultado}"
except Exception as e:
return f"Erro: {str(e)}"
return f"Ferramenta '{nome}' não encontrada."

O que é

O loop agentic é o coração do agente. Ele repete o ciclo Pensar → Agir → Observar até que o modelo decida que tem informação suficiente para responder ao usuário sem chamar mais ferramentas. O sinal de término é o campo stop_reason == "end_turn".

Por que aprender

Entender o loop manual revela o que frameworks como LangChain e LlamaIndex fazem nos bastidores. Com esse conhecimento, você pode depurar comportamentos inesperados, otimizar o número de chamadas à API e implementar lógicas customizadas que frameworks genéricos não suportam.

Conceitos-chave

stop_reason

"end_turn" = resposta final. "tool_use" = o modelo quer executar ferramentas.

Histórico de mensagens

Cada iteração adiciona a resposta do assistente e os resultados das ferramentas ao array mensagens.

max_iteracoes

Limite de segurança para evitar loops infinitos e custos inesperados com a API.

Fluxo do loop

while iteracao < max_iteracoes:
# 1. PENSAR — LLM processa o contexto
resposta = client.messages.create(...)
# 2. Verificar se terminou
if resposta.stop_reason == "end_turn":
return resposta_final # Sai do loop
# 3. AGIR — Executa ferramentas
for bloco in resposta.content:
if bloco.type == "tool_use":
resultado = executar_ferramenta(...)
# 4. OBSERVAR — Adiciona ao histórico
mensagens.append({"role": "assistant", ...})
mensagens.append({"role": "user", ...}) # resultados

O que é

Memória é a capacidade do agente de reter e acessar informações entre chamadas de ferramentas. No projeto, usamos um dicionário Python simples (notas = {}) como memória de trabalho. Em produção, isso pode ser um banco de dados vetorial para RAG.

Por que aprender

Um agente sem memória recomeça do zero a cada sessão. Com memória, ele pode aprender preferências do usuário, acumular resultados de pesquisa e executar tarefas complexas de múltiplos passos que ultrapassam a janela de contexto de uma única conversa.

Conceitos-chave

Memória de curto prazo

O array mensagens da sessão atual — tudo que o modelo já viu nesta conversa.

Memória de longo prazo

O dicionário notas persiste entre chamadas dentro da mesma execução do processo.

RAG (Retrieval Augmented Generation)

Técnica de buscar documentos relevantes em uma base de conhecimento e injetar no contexto antes de chamar o modelo.

Ferramenta salvar_nota

notas = {} # Memória global
elif nome == "salvar_nota":
notas[inputs["titulo"]] = inputs["conteudo"]
return f"Nota '{inputs['titulo']}' salva."
# Evolução: persistir em JSON
import json
with open("memoria.json", "w") as f:
json.dump(notas, f, ensure_ascii=False)

O que é

A fase de execução e teste valida se o agente se comporta como esperado em diferentes cenários. Inclui testar chamadas únicas de ferramentas, encadeamento de múltiplas ferramentas e situações de erro onde o modelo precisa se recuperar.

Por que aprender

Agentes têm comportamento não-determinístico. Testar com casos variados revela quando o modelo escolhe ferramentas erradas, entra em loops ou falha silenciosamente. Bons testes identificam esses problemas antes da produção.

Conceitos-chave

Teste de ferramenta única

Peça algo simples como "Quanto é 125 * 8?" para verificar se a ferramenta calcular é acionada.

Encadeamento

Peça "Pesquise sobre Python e salve um resumo" — o agente deve usar buscar_na_web e depois salvar_nota.

Observar logs

Os prints do loop mostram cada iteração, ferramenta chamada e resultado — use para depurar comportamentos inesperados.

Como executar

# Ative o ambiente virtual
source .venv/bin/activate
# Execute o agente
python agent.py
# Exemplos de prompts para testar:
# "Qual é 15% de 3200?"
# "Pesquise sobre inteligência artificial generativa"
# "Calcule a área de um círculo com raio 7 e salve"
# "Pesquise Python e depois salve um resumo"

Saída esperada no terminal

============================================================
AGENTE INICIADO
============================================================
[Iteração 1] Pensando...
→ Usando ferramenta: calcular("expressao": "3200 * 0.15")
← Resultado: Resultado: 480.0...
[Iteração 2] Pensando...
============================================================
RESPOSTA FINAL:
============================================================
15% de 3200 é 480.

Código Completo — agent.py

"""
Agente do Zero — Agentic Engineering Masterclass
INEMA.CLUB — Projeto 1: Agente sem framework

Demonstra o loop agentic manual com Anthropic API:
- Tools (function calling)
- Loop Pensar → Agir → Observar
- Sem frameworks externos
"""
import os
import json
import anthropic
from dotenv import load_dotenv

load_dotenv()
client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

# ─── FERRAMENTAS ──────────────────────────────────────────────────────────────

tools = [
    {
        "name": "buscar_na_web",
        "description": "Busca informações na web sobre qualquer tema",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "O que buscar. Seja específico."
                }
            },
            "required": ["query"]
        }
    },
    {
        "name": "calcular",
        "description": "Executa cálculos matemáticos. Recebe expressão Python válida.",
        "input_schema": {
            "type": "object",
            "properties": {
                "expressao": {
                    "type": "string",
                    "description": "Expressão matemática. Ex: '2 + 2' ou '100 * 0.15'"
                }
            },
            "required": ["expressao"]
        }
    },
    {
        "name": "salvar_nota",
        "description": "Salva uma nota ou resultado importante em memória",
        "input_schema": {
            "type": "object",
            "properties": {
                "titulo": {"type": "string"},
                "conteudo": {"type": "string"}
            },
            "required": ["titulo", "conteudo"]
        }
    }
]

# ─── DISPATCHER ───────────────────────────────────────────────────────────────

notas = {}  # Memória simples em dicionário

def executar_ferramenta(nome: str, inputs: dict) -> str:
    """Despacha a ferramenta correta e retorna o resultado."""

    if nome == "buscar_na_web":
        query = inputs["query"]
        return f"[Resultado de busca para '{query}']: Encontrado 3 resultados relevantes."

    elif nome == "calcular":
        try:
            resultado = eval(inputs["expressao"], {"__builtins__": {}})
            return f"Resultado: {resultado}"
        except Exception as e:
            return f"Erro no cálculo: {str(e)}"

    elif nome == "salvar_nota":
        notas[inputs["titulo"]] = inputs["conteudo"]
        return f"Nota '{inputs['titulo']}' salva com sucesso."

    return f"Ferramenta '{nome}' não encontrada."

# ─── LOOP AGENTIC ─────────────────────────────────────────────────────────────

def executar_agente(mensagem_usuario: str, max_iteracoes: int = 10) -> str:
    """
    Loop agentic principal:
    1. Envia mensagem ao LLM
    2. Se o LLM chamar ferramentas → executa e retorna resultados
    3. Repete até stop_reason == end_turn
    """
    mensagens = [{"role": "user", "content": mensagem_usuario}]
    iteracao = 0

    print(f"\n{'='*60}")
    print(f"AGENTE INICIADO")
    print(f"{'='*60}")

    while iteracao < max_iteracoes:
        iteracao += 1
        print(f"\n[Iteração {iteracao}] Pensando...")

        resposta = client.messages.create(
            model="claude-opus-4-6",
            max_tokens=4096,
            system="Você é um assistente inteligente com acesso a ferramentas.",
            tools=tools,
            messages=mensagens
        )

        if resposta.stop_reason == "end_turn":
            resposta_final = next(
                (b.text for b in resposta.content if hasattr(b, "text")),
                "Sem resposta."
            )
            print(f"\n{'='*60}")
            print(f"RESPOSTA FINAL:")
            print(f"{'='*60}")
            print(resposta_final)
            return resposta_final

        resultados_ferramentas = []
        for bloco in resposta.content:
            if bloco.type == "tool_use":
                print(f"  → Usando: {bloco.name}({json.dumps(bloco.input)})")
                resultado = executar_ferramenta(bloco.name, bloco.input)
                print(f"  ← Resultado: {resultado[:100]}...")
                resultados_ferramentas.append({
                    "type": "tool_result",
                    "tool_use_id": bloco.id,
                    "content": resultado
                })

        mensagens.append({"role": "assistant", "content": resposta.content})
        mensagens.append({"role": "user", "content": resultados_ferramentas})

    return "Máximo de iterações atingido."

# ─── MAIN ─────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("Agente do Zero — INEMA.CLUB")
    print("Pressione Ctrl+C para sair\n")

    while True:
        try:
            mensagem = input("Você: ").strip()
            if not mensagem:
                continue
            if mensagem.lower() in ["sair", "exit", "quit"]:
                break
            executar_agente(mensagem)
        except KeyboardInterrupt:
            print("\nAté logo!")
            break
        except Exception as e:
            print(f"Erro: {e}")

Próximos Passos

Continue sua jornada na Agentic Engineering Masterclass com os próximos projetos.

2
Claude Code

Agente com Claude Code

Use Claude Code como agente de engenharia autônomo no seu terminal.

3
Antigravity

Agente Multi-Step

Planejamento e execução de tarefas complexas com múltiplos sub-agentes.

4
Codex

Agente de Código

Gere, revise e refatore código automaticamente com agentes especializados.