Do Prompt ao Agente: Construa um Assistente de IA com Memória e Ferramentas em Python (2026)
Se você já chamou a API da OpenAI ou do Google para fazer um chatbot responder perguntas, sabe como é fácil chegar até ali. O problema vem depois: o chatbot não lembra da conversa anterior, não consegue pesquisar na web, não executa código, não faz nada além de texto.
Isso não é um agente. É uma demo.
Um agente de IA de verdade combina quatro componentes: um modelo de linguagem que raciocina, ferramentas que ele pode chamar, memória que persiste entre turnos, e um loop de orquestração que decide o próximo passo. Em 2026, frameworks como LangGraph (126 mil estrelas no GitHub), Vercel AI SDK e Claude Agent SDK tornaram isso acessível para qualquer desenvolvedor.
Neste tutorial, você vai construir um agente funcional em Python em duas abordagens: primeiro o loop ReAct puro para entender o mecanismo, depois com LangGraph para produção. No final, seu agente vai pesquisar na web, calcular expressões, lembrar de conversas anteriores e até persistir estado entre sessões.
O Que Separa um Chatbot de um Agente
Um chatbot recebe uma mensagem e devolve outra. Fim.
Um agente recebe um objetivo, planeja os passos, executa ferramentas, observa os resultados, e repete até concluir a tarefa. A diferença está no loop.
Seu ciclo básico — chamado ReAct (Reasoning + Acting) — funciona assim:
- O LLM recebe o histórico + a pergunta do usuário
- Ele decide: responder diretamente ou chamar uma ferramenta
- Se chamar ferramenta, executa e retorna o resultado para o LLM
- O LLM analisa o resultado e decide o próximo passo
- Repete até ter resposta final
É enganosamente simples. A maior parte dos erros em agentes de produção vem de implementações apressadas desse loop.
Pense em um cenário real: um assistente de suporte que precisa consultar a base de conhecimento, verificar o status do pedido no sistema e depois responder ao cliente. Sem o loop ReAct, você teria que hardcodar cada etapa. Com o loop, o LLM decide a sequência sozinho baseado nas ferramentas disponíveis.
O Detalhe que Faz Toda a Diferença: tool_choice
No código acima, usei tool_choice="auto". Isso permite que o LLM decida entre responder ou chamar ferramenta. Mas existem duas outras opções importantes:
tool_choice="none": força o LLM a responder sem ferramentas — útil quando você quer garantir uma resposta diretatool_choice="required": força o LLM a chamar pelo menos uma ferramenta — bom para pipelines onde toda consulta precisa passar por validação primeiro
A escolha errada aqui é uma das fontes mais comuns de loops infinitos em agentes. Se o LLM fica chamando ferramentas sem nunca chegar a uma resposta final, você precisa de um limite de iterações (como o max_iteracoes=10 no exemplo acima) e um fallback bem definido.
Abordagem 1: Loop ReAct Puro (Sem Framework)
Antes de usar LangGraph, vale a pena escrever o loop manualmente. Você entende o que o framework faz por baixo dos panos.
import json
from openai import OpenAI
client = OpenAI()
TOOLS = [ { "type": "function", "function": { "name": "pesquisar_web", "description": "Pesquisa na web e retorna resumo dos resultados", "parameters": { "type": "object", "properties": { "query": {"type": "string"} }, "required": ["query"] } } }, { "type": "function", "function": { "name": "calcular", "description": "Executa expressão matemática", "parameters": { "type": "object", "properties": { "expressao": {"type": "string"} }, "required": ["expressao"] } } } ]
def executar_ferramenta(nome, args): if nome == "calcular": return str(eval(args["expressao"])) if nome == "pesquisar_web": return f"Resultados simulados para: {args['query']}" return "Ferramenta não encontrada"
def agente_react(mensagem_usuario, max_iteracoes=10): mensagens = [{"role": "user", "content": mensagem_usuario}]
for _ in range(max_iteracoes):
resposta = client.chat.completions.create(
model="gpt-4o-mini",
messages=mensagens,
tools=TOOLS,
tool_choice="auto"
)
msg = resposta.choices[0].message
mensagens.append(msg)
if not msg.tool_calls:
return msg.content
for chamada in msg.tool_calls:
resultado = executar_ferramenta(
chamada.function.name,
json.loads(chamada.function.arguments)
)
mensagens.append({
"role": "tool",
"tool_call_id": chamada.id,
"content": resultado
})
return "Número máximo de iterações atingido"
Esse código funciona. Mas tem problemas: não persiste estado entre sessões, não tem checkpoint para retomar após falha, e o loop linear fica frágil em tarefas com múltiplas ramificações. É aqui que o LangGraph entra.
Abordagem 2: Agente com LangGraph
LangGraph substitui o loop linear por um grafo direcionado com estados tipados, checkpoint nativo e suporte a condicionais. Cada nó do grafo é uma etapa do processamento; cada aresta define como a execução flui.
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
import json
class EstadoAgente(TypedDict): mensagens: List[dict] proximo_passo: str
def node_llm(estado: EstadoAgente): resposta = client.chat.completions.create( model="gpt-4o-mini", messages=estado["mensagens"], tools=TOOLS ) msg = resposta.choices[0].message estado["mensagens"].append(msg) if msg.tool_calls: estado["proximo_passo"] = "ferramentas" else: estado["proximo_passo"] = "fim" return estado
def node_ferramentas(estado: EstadoAgente): ultima_msg = estado["mensagens"][-1] for chamada in ultima_msg.tool_calls: resultado = executar_ferramenta( chamada.function.name, json.loads(chamada.function.arguments) ) estado["mensagens"].append({ "role": "tool", "tool_call_id": chamada.id, "content": resultado }) estado["proximo_passo"] = "llm" return estado
def router(estado: EstadoAgente): if estado["proximo_passo"] == "ferramentas": return "ferramentas" elif estado["proximo_passo"] == "fim": return END return "llm"
grafo = StateGraph(EstadoAgente) grafo.add_node("llm", node_llm) grafo.add_node("ferramentas", node_ferramentas) grafo.set_entry_point("llm") grafo.add_conditional_edges("llm", router) grafo.add_edge("ferramentas", "llm") app = grafo.compile()
A diferença fundamental: com LangGraph, o ciclo llm → ferramentas → llm é explícito no grafo, e cada execução passa por checkpoint automaticamente. Se o processo cair no meio de uma chamada de ferramenta, ele retoma de onde parou.
Por que Grafos São Melhores que Loops Lineares?
O loop ReAct puro é sequencial: uma chamada de ferramenta por vez, sempre na mesma ordem. Um grafo permite:
- Ramificações condicionais: dependendo da saída do LLM, o fluxo vai para nós diferentes
- Nós paralelos: múltiplas ferramentas executando ao mesmo tempo
- Human-in-the-loop: um nó de aprovação que pausa a execução até um humano autorizar
- Subgrafos: agentes especializados dentro do agente principal, cada um com seu próprio grafo
Em produção, essa flexibilidade não é luxo — é necessidade. Um agente de suporte, por exemplo, pode precisar consultar o banco de clientes e o estoque ao mesmo tempo (paralelo), e só prosseguir se o gerente aprovar um desconto (human-in-the-loop).
Memória Persistente com Checkpoint
O checkpoint nativo do LangGraph é um dos seus diferenciais. Com uma linha, você conecta um banco SQLite e seu agente passa a lembrar de tudo entre sessões:
from langgraph.checkpoint.sqlite import SqliteSaver
with SqliteSaver.from_conn_string("memoria.db") as saver: app = grafo.compile(checkpointer=saver) config = {"configurable": {"thread_id": "usuario-123"}}
resultado = app.invoke(
{"mensagens": [{"role": "user", "content": "Qual era aquele artigo que discutimos ontem?"}]},
config
)
Cada thread_id representa uma sessão independente. O agente recupera automaticamente o histórico completo daquele usuário. Isso resolve o problema mais comum de chatbots em produção: a amnésia entre conversas.
Ferramentas Reais: Conectando o Agente ao Mundo
Um agente sem ferramentas é um chatbot fancy. Com ferramentas, ele se torna útil. Veja como adicionar uma busca real na web usando a API de busca do DuckDuckGo:
from duckduckgo_search import DDGS
def pesquisar_web(query: str) -> str: with DDGS() as ddgs: resultados = list(ddgs.text(query, max_results=3)) return "\n".join( f"{r['title']}: {r['body'][:200]}" for r in resultados )
Basta registrar a ferramenta no array TOOLS com a descrição correta. O LLM decide quando usá-la com base na descrição — por isso docstrings claras são essenciais.
Próximos Passos
Seu agente já funciona com ferramentas e memória persistente. A partir daqui, você pode:
- Adicionar mais ferramentas: calculadora, acesso a banco de dados, envio de e-mail, consulta a APIs externas
- Multi-agentes: use o padrão supervisor + sub-agentes do LangGraph para delegar tarefas complexas
- Human-in-the-loop: adicione nós de aprovação antes de ações críticas (enviar e-mail, executar código)
- Streaming: implemente
astream_eventsdo LangGraph para mostrar o raciocínio do agente em tempo real - Observabilidade: conecte LangSmith para rastrear cada chamada de ferramenta e custo de tokens
Colocando o Agente no Ar
Com o checkpoint do LangGraph, seu agente já persiste estado. Falta expor ele como uma API. O jeito mais simples é com FastAPI:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Pergunta(BaseModel): mensagem: str sessao: str
@app.post("/chat") async def chat(req: Pergunta): config = {"configurable": {"thread_id": req.sessao}} resultado = app.invoke( {"mensagens": [{"role": "user", "content": req.mensagem}]}, config ) return {"resposta": resultado["mensagens"][-1]["content"]}
Com isso, qualquer frontend — React, Streamlit, até um bot do Telegram — pode conversar com seu agente. Cada sessao vira uma conversa independente com seu próprio histórico.
Resumo: O Mapa para Construir Agentes em 2026
| Abordagem | Complexidade | Produção | Ideal para |
|---|---|---|---|
| Loop ReAct puro | Baixa | Não | Aprender o mecanismo |
| LangGraph básico | Média | Sim | Agentes com ferramentas |
| LangGraph + checkpoint | Média | Sim | Agentes com memória persistente |
| LangGraph + subgrafos | Alta | Sim | Sistemas multi-agentes |
Comece pelo loop puro, entenda cada peça, e só então migre para o framework. Em 2026, construir agentes não é mais magia. É engenharia de software com um novo tipo de API. Seu eu do futuro — quando o agente quebrar às 3 da manhã — vai agradecer por ter começado com a abordagem certa.
NeuralPulse
Blog profissional sobre Inteligencia Artificial. Exploramos tendencias, ferramentas, tutoriais e analises profundas sobre como a IA esta transformando negocios, tecnologia e o dia a dia.
Receba as novidades sobre IA
Junte-se a milhares de leitores que acompanham as ultimas tendencias em inteligencia artificial.
Artigos Relacionados
Automação de Licitações com IA: Guia Prático para Órgãos Públicos
Aprenda a usar IA gratuita para automatizar a análise de editais e propostas em licitações públicas com Python, dados abertos e modelos como Sabiá-4 e Gemini.
Function Calling na Prática: Tutorial Python para Chatbots com LLMs que Executam Ações em 2026
Aprenda a implementar function calling em Python com OpenAI, Anthropic Claude e Google Gemini. Tutorial completo com código para integrar APIs, bancos de dad...
Árvore de Decisão vs Random Forest vs XGBoost: Tutorial Prático de Machine Learning em 2026 (com Código Python e Dados Reais)
Comparação prática entre Árvore de Decisão, Random Forest e XGBoost para classificação em 2026, com implementação passo a passo em Python e análise de perfor...
Comentarios
Powered by Disqus
Para ativar os comentarios, configure seu shortname do Disqus no componente.
<div id="disqus_thread"></div>