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:
1. Recebe um objetivo (não apenas uma pergunta)
2. Decide quais ações tomar para atingir esse objetivo
3. Executa essas ações usando ferramentas (tools)
4. Observa os resultados de cada ação
5. 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.
