Agentes de IA vs Chatbots: A Diferença Fundamental
Se você já usou o ChatGPT ou qualquer LLM via API, você criou um chatbot. Mas um agente de IA é uma categoria completamente diferente.
Um chatbot recebe uma mensagem, processa, devolve uma resposta. Ponto final. O modelo não toma decisões sobre o que fazer a seguir, não acessa sistemas externos por conta própria, não executa código, não itera sobre um problema até resolvê-lo.
Um agente, por outro lado, é um sistema que:
- Recebe um objetivo (não apenas uma pergunta)
- Decide quais ações tomar para atingir esse objetivo
- Executa essas ações usando ferramentas (tools)
- Observa os resultados de cada ação
- Itera até que o objetivo seja atingido
| Característica | Chatbot | Agente de IA |
|---|---|---|
| Tipo de input | Pergunta/mensagem | Objetivo/tarefa |
| Número de passos | Único | Múltiplos (plan → act → observe → repeat) |
| Acesso a ferramentas | Não (ou limitado) | Sim, dinâmico |
| Capacidade de iteração | Não | Sim |
| Exemplos de uso | FAQ, suporte básico | Pesquisa autônoma, execução de código |
A virada conceitual é esta: você não pergunta "qual a capital da França?" para um agente. Você diz "pesquise os 5 maiores aeroportos europeus, encontre as tarifas médias e gere um relatório CSV". O agente planeja, usa ferramentas de busca, executa código Python, e entrega o resultado.
---
A Arquitetura de um Agente: ReAct e Tool Use
O padrão de raciocínio mais usado é o ReAct (Reasoning + Acting). O modelo intercala raciocínio com ações reais:
Thought: Preciso saber o preço atual do Bitcoin.
Action: web_search
Action Input: "Bitcoin price USD today"
Observation: Bitcoin está cotado a $67.450 USD.
Thought: Agora tenho o preço. Posso responder ao usuário.
Final Answer: O preço atual do Bitcoin é $67.450 USD.
O padrão moderno é o Tool Calling (Function Calling), disponível em GPT-4o e Claude. Em vez de parsear texto livre, o modelo emite chamadas de função estruturadas em JSON. É mais confiável e é o padrão recomendado:
{
"name": "web_search",
"arguments": { "query": "Bitcoin price USD today" }
}
---
Configurando o Ambiente: LangChain + OpenAI
python -m venv venv && source venv/bin/activate
pip install langchain langchain-openai langchain-community \
langchain-experimental duckduckgo-search \
python-dotenv langgraph langsmith
# .env
OPENAI_API_KEY=sk-...
LANGCHAIN_API_KEY=ls__...
LANGCHAIN_TRACING_V2=true
LANGCHAIN_PROJECT=meu-agente
# config.py
from langchain_openai import ChatOpenAI
def get_llm(model="gpt-4o-mini", temperature=0):
# temperature=0 para agentes: decisoes consistentes, nao criativas
return ChatOpenAI(model=model, temperature=temperature)
---
Suas Primeiras Tools: Web Search e Python REPL
Tools são funções Python decoradas com metadados que o LLM usa para decidir quando e como chamá-las. A docstring é literalmente o que o modelo lê para decidir se deve usar a tool.
DuckDuckGo Search Tool
from langchain_community.tools import DuckDuckGoSearchResults
def get_search_tool(max_results: int = 5):
return DuckDuckGoSearchResults(
num_results=max_results,
backend="text"
)
# Testando isoladamente
if __name__ == "__main__":
tool = get_search_tool()
resultado = tool.run("LangChain agentes IA 2025")
print(resultado)
Python REPL Tool
from langchain_experimental.tools import PythonREPLTool
def get_repl_tool():
# ATENCAO: executa codigo real na sua maquina
# Em producao, use sandboxing (Docker, subprocess com timeout)
return PythonREPLTool()
# Testando
if __name__ == "__main__":
repl = get_repl_tool()
resultado = repl.run("""
import statistics
dados = [23, 45, 12, 67, 34, 89, 56]
print(f"Media: {statistics.mean(dados):.2f}")
print(f"Desvio padrao: {statistics.stdev(dados):.2f}")
""")
print(resultado)
Criando uma Tool Customizada
from langchain_core.tools import tool
import json
import datetime
@tool
def buscar_cotacao_moeda(moeda_origem: str, moeda_destino: str) -> str:
"""
Busca a cotacao atual entre duas moedas.
Use quando precisar converter valores monetarios ou verificar taxas de cambio.
Args:
moeda_origem: Codigo ISO da moeda de origem (ex: 'USD', 'BRL', 'EUR')
moeda_destino: Codigo ISO da moeda de destino (ex: 'BRL', 'USD', 'EUR')
"""
# Em producao: usar API real como exchangerate-api.com
taxas = {
("USD", "BRL"): 5.12,
("EUR", "BRL"): 5.54,
("BRL", "USD"): 0.195,
}
par = (moeda_origem.upper(), moeda_destino.upper())
if par in taxas:
taxa = taxas[par]
ts = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
return f"1 {moeda_origem.upper()} = {taxa} {moeda_destino.upper()} (atualizado em {ts})"
return f"Cotacao nao disponivel para {moeda_origem}/{moeda_destino}"
---
Construindo um Agente de Pesquisa Completo
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.tools import DuckDuckGoSearchResults
from langchain_core.tools import tool
from datetime import datetime
@tool
def formatar_relatorio(titulo: str, secoes: str) -> str:
"""
Formata o relatorio final em Markdown. Use como ULTIMO passo da pesquisa.
Args:
titulo: Titulo principal do relatorio
secoes: Conteudo das secoes em formato de texto corrido
"""
data = datetime.now().strftime("%d/%m/%Y")
return f"# {titulo}\n*Relatorio gerado em {data}*\n\n---\n\n{secoes}"
def criar_agente_pesquisa(verbose=True):
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
tools = [
DuckDuckGoSearchResults(num_results=5),
formatar_relatorio,
]
system_prompt = """Voce e um agente de pesquisa especializado em tecnologia e IA.
Processo de trabalho:
1. Para cada topico, realize 2-3 buscas com queries diferentes e complementares
2. Sintetize as informacoes, eliminando redundancias
3. Use a tool formatar_relatorio para gerar o documento final
IMPORTANTE: Nunca invente dados. Use apenas o que encontrou nas buscas."""
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
MessagesPlaceholder(variable_name="chat_history", optional=True),
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
agent = create_tool_calling_agent(llm=llm, tools=tools, prompt=prompt)
return AgentExecutor(
agent=agent,
tools=tools,
verbose=verbose,
max_iterations=10,
handle_parsing_errors=True,
return_intermediate_steps=True,
)
if __name__ == "__main__":
agente = criar_agente_pesquisa(verbose=True)
resultado = agente.invoke({
"input": "Pesquise sobre o estado atual dos agentes de IA em 2025."
})
print("\n=== RELATORIO FINAL ===")
print(resultado["output"])
print(f"\nPassos executados: {len(resultado['intermediate_steps'])}")
---
Memória em Agentes: Conversation, Entity e Summary
Por padrão, agentes LangChain são stateless — cada invocação começa do zero. Para criar agentes que lembram de conversas, adicione memória explicitamente.
| Tipo | Como funciona | Quando usar | Custo de tokens |
|---|---|---|---|
ConversationBufferWindowMemory |
Mantém últimas N trocas | Balance custo/contexto | Controlável |
ConversationSummaryMemory |
Resume o histórico com LLM | Conversas longas | Médio |
ConversationEntityMemory |
Extrai e mantém entidades | Contexto com dados específicos | Baixo |
from langchain.memory import ConversationBufferWindowMemory
memory = ConversationBufferWindowMemory(
k=5, # ultimas 5 trocas
memory_key="chat_history",
return_messages=True,
)
# Adicionando memoria ao executor
executor = AgentExecutor(
agent=agent,
tools=tools,
memory=memory,
verbose=True,
max_iterations=8,
)
# Testando continuidade
r1 = executor.invoke({"input": "Pesquise sobre LangChain."})
r2 = executor.invoke({"input": "Quais as principais novidades que voce mencionou?"})
# O agente lembra do contexto anterior
---
Construindo um Agente com Múltiplas Tools
from langchain_experimental.tools import PythonREPLTool
from langchain.memory import ConversationBufferWindowMemory
def criar_agente_financeiro():
llm = ChatOpenAI(model="gpt-4o", temperature=0)
tools = [
DuckDuckGoSearchResults(num_results=4, name="web_search"),
PythonREPLTool(name="python_repl"),
buscar_cotacao_moeda,
]
memory = ConversationBufferWindowMemory(
k=6, memory_key="chat_history", return_messages=True
)
system_prompt = """Voce e um analista financeiro especializado.
Capacidades:
- web_search: para buscar noticias e dados de mercado atualizados
- python_repl: para calculos, graficos e analises quantitativas
- buscar_cotacao_moeda: para obter taxas de cambio
SEMPRE inclua disclaimers: analises passadas nao garantem resultados futuros."""
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
agent = create_tool_calling_agent(llm=llm, tools=tools, prompt=prompt)
return AgentExecutor(
agent=agent, tools=tools, memory=memory,
verbose=True, max_iterations=12, handle_parsing_errors=True,
)
if __name__ == "__main__":
agente = criar_agente_financeiro()
resposta = agente.invoke({
"input": "Compare as perspectivas do dolar frente ao real para os "
"proximos 3 meses baseado em analises recentes."
})
print(resposta["output"])
---
Introdução ao LangGraph: Agentes Multi-Step
O LangGraph é a evolução natural para agentes complexos. Em vez de um único agente com N tools, você cria um grafo de agentes, onde cada nó é um agente especializado.
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
from typing import TypedDict, List, Annotated
import operator
class EstadoPesquisa(TypedDict):
mensagens: Annotated[List, operator.add]
topico: str
dados_brutos: str
relatorio_final: str
# Tres nos especializados
def no_pesquisa(estado):
print("Pesquisando...")
resultado = pesquisador.invoke({"input": f"Pesquise: {estado['topico']}"})
return {"dados_brutos": resultado["output"]}
def no_analise(estado):
print("Analisando...")
resultado = analista.invoke({
"input": f"Analise e extraia metricas:\n{estado['dados_brutos']}"
})
return {"analise": resultado["output"]}
def no_redacao(estado):
print("Redigindo...")
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.3)
resposta = llm.invoke([HumanMessage(
content=f"Escreva relatorio sobre '{estado['topico']}':\n{estado['dados_brutos'][:1500]}"
)])
return {"relatorio_final": resposta.content}
# Construindo o grafo
grafo = StateGraph(EstadoPesquisa)
grafo.add_node("pesquisa", no_pesquisa)
grafo.add_node("analise", no_analise)
grafo.add_node("redacao", no_redacao)
grafo.set_entry_point("pesquisa")
grafo.add_edge("pesquisa", "analise")
grafo.add_edge("analise", "redacao")
grafo.add_edge("redacao", END)
pipeline = grafo.compile()
resultado = pipeline.invoke({
"mensagens": [],
"topico": "Adocao de IA generativa em empresas brasileiras em 2025",
"dados_brutos": "",
"relatorio_final": "",
})
print(resultado["relatorio_final"])
O LangGraph brilha com fluxos condicionais — se a pesquisa retornar poucos dados, redirecionar para uma busca mais ampla antes de analisar. Isso se faz com add_conditional_edges.
---
Monitorando Agentes com LangSmith
import os
# Com estas variaveis, TODOS os agentes LangChain sao rastreados automaticamente
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "ls__sua_chave_aqui"
os.environ["LANGCHAIN_PROJECT"] = "swen-agentes-producao"
Com o tracing ativo, acesse smith.langchain.com e veja cada execucao em tempo real: qual tool foi chamada, com que parametros, quanto demorou, e o custo exato em tokens.
---
Erros Comuns e Como Evitá-los em Produção
1. Loops Infinitos
Sempre configure:
executor = AgentExecutor(
agent=agent,
tools=tools,
max_iterations=10, # nunca deixe sem limite
max_execution_time=60, # timeout em segundos
early_stopping_method="generate",
handle_parsing_errors=True,
)
2. Custo de Tokens Explosivo
# RUIM: memoria cresce infinitamente
from langchain.memory import ConversationBufferMemory
memory = ConversationBufferMemory()
# BOM: janela controlada
memory = ConversationBufferWindowMemory(k=5)
3. Tools sem Tratamento de Erro
@tool
def buscar_api_externa(query: str) -> str:
"""Busca dados em API externa."""
try:
import httpx
response = httpx.get("https://api.exemplo.com/search",
params={"q": query}, timeout=10.0)
response.raise_for_status()
return response.json()["result"]
except httpx.TimeoutException:
return "Erro: API nao respondeu em 10 segundos. Tente query mais especifica."
except Exception as e:
# Nunca deixe a excecao subir - retorne erro legivel para o LLM
return f"Erro ao buscar dados: {str(e)[:200]}"
Quando NÃO Usar Agentes
| Situacao | Use Agente? | Alternativa |
|---|---|---|
| Transformacao simples de texto | Nao | LLM call direto |
| Pipeline ETL com passos fixos | Nao | LangChain Chain sequencial |
| Classificacao de intencao | Nao | Prompt engineering + JSON |
| Pesquisa com ferramentas externas | Sim | Agente |
| Execucao de codigo baseado em contexto | Sim | Agente |
Regra de ouro: use agentes quando o LLM precisa decidir quais ferramentas usar e em que ordem, com base em resultados intermediarios. Se o fluxo e fixo, uma Chain simples e mais barata, rapida e confiavel.
---
Perguntas Frequentes sobre Agentes IA
O agente pode usar quantas tools por iteracao?
Com Tool Calling (GPT-4o, Claude), o modelo pode chamar multiplas tools em paralelo numa unica iteracao. Habilite com parallel_tool_calls=True no ChatOpenAI.
Qual a diferenca entre create_tool_calling_agent e create_react_agent?
create_tool_calling_agent usa a API nativa de function calling do modelo (estruturado, confiavel, mais rapido). create_react_agent usa prompts de texto e parseia no formato Thought/Action/Observation (compativel com modelos sem function calling). Para GPT-4o e Claude, use sempre create_tool_calling_agent.
Como limitar o custo de um agente em producao?
Tres camadas: (1) max_iterations no AgentExecutor, (2) max_execution_time em segundos, (3) usar gpt-4o-mini para o agente e reservar gpt-4o apenas para o no de sintese final. Um agente de pesquisa bem otimizado com gpt-4o-mini custa menos de $0,01 por execucao.
Agentes LangChain funcionam com modelos open-source?
Sim, via ChatOllama (local) ou ChatGroq/ChatTogether (cloud). Para agentes complexos com muitas tools, use modelos de 70B+ ou os modelos comerciais.
Vale a pena usar LangGraph para todos os agentes?
Nao. Para agentes simples com 2-5 tools e fluxo linear, AgentExecutor e suficiente e mais simples de manter. LangGraph se justifica quando voce tem: multiplos agentes especializados, fluxos condicionais complexos, necessidade de paralelismo entre nos, ou checkpointing de estado para retomada de execucao.

