LangChain é o framework mais popular para construção de aplicações com LLMs. Toda documentação de IA parece referenciar LangChain, todo tutorial começa com pip install langchain. E no entanto, é comum encontrar times de engenharia que começaram com LangChain e migraram para implementações mais simples depois de alguns meses.
Por quê? E quando LangChain realmente faz sentido?
O que LangChain resolve
LangChain surgiu para resolver um problema real: construir aplicações com LLMs envolve muitas peças que precisam se conectar — chamadas de API, gerenciamento de histórico de conversa, busca em bases de conhecimento, execução de ferramentas, orquestração de agentes.
Fazer tudo isso do zero é trabalhoso. LangChain fornece abstrações para cada uma dessas peças.
Onde LangChain genuinamente ajuda:
Prototipagem rápida: para explorar um caso de uso novo, LangChain permite montar algo funcional em poucas horas. A variedade de integrações prontas (com dezenas de vector databases, LLMs, ferramentas) elimina o trabalho de implementação inicial.
Pipelines RAG padronizados: o fluxo de RAG (carregamento de documentos, chunking, embedding, armazenamento, recuperação, geração) está tão bem estabelecido que as abstrações do LangChain fazem sentido para a maioria dos casos.
Ecosistema: LangChain tem integração pronta com a maioria dos provedores relevantes. Quando você quer testar um novo vector database ou um novo modelo, provavelmente já tem um adapter.
LangGraph: para sistemas multi-agente com controle de estado, LangGraph (parte do ecossistema LangChain) é genuinamente útil e difícil de substituir por algo mais simples.
Onde LangChain adiciona complexidade sem valor
Abstração excessiva para casos simples: para um chatbot simples ou um sistema de extração de dados, LangChain introduz camadas de abstração que tornam o código mais difícil de entender e de debugar, sem benefício real. Uma chamada direta para a API da OpenAI é mais clara e mais fácil de manter.
Debugging obscuro: quando algo dá errado em uma chain do LangChain, o traceback frequentemente não aponta claramente onde está o problema. Em implementações diretas, o erro é muito mais óbvio.
Versioning instável: o LangChain passou por múltiplas refatorações (a transição para o pacote langchain-core + langchain-community é um exemplo). Projetos que dependiam de versões antigas quebraram com as atualizações.
Performance desnecessária: as abstrações do LangChain têm overhead. Para sistemas de alta frequência, esse overhead pode ser significativo.
O teste da implementação direta
Uma heurística útil antes de adicionar LangChain a um projeto: você consegue implementar o que precisa diretamente com o SDK oficial do provedor de LLM em menos de 100 linhas de código?
# Implementação direta de RAG simples — sem LangChain
from openai import OpenAI
import chromadb
def rag_query(question: str, top_k: int = 3) -> str:
# 1. Embed a pergunta
client = OpenAI()
query_embedding = client.embeddings.create(
input=question,
model="text-embedding-3-small"
).data[0].embedding
# 2. Buscar documentos relevantes
db = chromadb.Client()
collection = db.get_collection("documentos")
results = collection.query(
query_embeddings=[query_embedding],
n_results=top_k
)
# 3. Construir contexto e gerar resposta
context = "\n".join(results["documents"][0])
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": f"Responda com base no contexto:\n{context}"},
{"role": "user", "content": question}
]
)
return response.choices[0].message.content
Isso é um RAG funcional em ~30 linhas. Se o seu caso de uso cabe aqui, você provavelmente não precisa de LangChain.
Quando LangChain definitivamente faz sentido
Sistemas multi-agente complexos com LangGraph: o controle de estado com grafos direcionados é difícil de implementar bem do zero. LangGraph resolve isso.
Prototipagem de MVP para validação de negócio: quando o objetivo é validar rapidamente se o caso de uso funciona, LangChain permite ir mais rápido. Depois de validado, considere refatorar para implementação mais simples.
Times que precisam de consistência: em equipes maiores, as convenções do LangChain podem ajudar a manter consistência entre desenvolvedores. Mas isso só funciona se o time realmente conhece o framework bem.
Integrações com sistemas menos comuns: se você precisa de integração com um vector database mais exótico ou com um provedor de LLM menor, LangChain pode ter o adapter pronto quando o SDK oficial não existe.
Caso real: Migração de LangChain para implementação direta
Uma startup B2B construiu um assistente de vendas com LangChain. Após 6 meses em produção, migraram para implementação direta. Por quê?
Situação com LangChain:
- Sistema baseado em
ConversationalRetrievalChain - Latência P95: 3,2 segundos (inaceitável para chat)
- Debugging de erros levava horas
- Testes unitários difíceis (muitos mocks necessários)
- Refatoração para adicionar features era trabalhosa
- 800 linhas de código com LangChain
Após migração para implementação direta:
- Reimplementação usando SDK da OpenAI + ChromaDB diretamente
- Latência P95: 1,1 segundos (-66%)
- Debugging simples (stack trace claro)
- Cobertura de testes passou de 35% para 85%
- Refatorações levam 1/3 do tempo
- 450 linhas de código (44% menor)
Por que funcionou? O caso de uso era simples (RAG + conversação). LangChain adicionava abstração sem valor.
Comparação prática: Com e sem LangChain
Vamos comparar implementações reais lado a lado.
Exemplo 1: RAG básico com histórico de conversa
Com LangChain (~80 linhas):
from langchain.chat_models import ChatOpenAI
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory
# Setup
llm = ChatOpenAI(model="gpt-4o-mini")
embeddings = OpenAIEmbeddings()
vectorstore = Chroma(
collection_name="docs",
embedding_function=embeddings
)
# Memory
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="answer"
)
# Chain
chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=vectorstore.as_retriever(),
memory=memory,
return_source_documents=True
)
# Uso
response = chain({"question": "Qual a política de reembolso?"})
print(response["answer"])
Sem LangChain (~60 linhas):
from openai import OpenAI
import chromadb
client = OpenAI()
db = chromadb.Client()
collection = db.get_collection("docs")
history = [] # Gerenciar memória manualmente
def query(question: str) -> str:
# 1. Buscar contexto relevante
query_embedding = client.embeddings.create(
input=question,
model="text-embedding-3-small"
).data[0].embedding
results = collection.query(
query_embeddings=[query_embedding],
n_results=3
)
context = "\n\n".join(results["documents"][0])
# 2. Construir mensagens com histórico
messages = [
{"role": "system", "content": f"Use este contexto:\n{context}"}
]
messages.extend(history)
messages.append({"role": "user", "content": question})
# 3. Gerar resposta
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages
)
answer = response.choices[0].message.content
# 4. Atualizar histórico
history.append({"role": "user", "content": question})
history.append({"role": "assistant", "content": answer})
return answer
# Uso
print(query("Qual a política de reembolso?"))
Análise:
- Clareza: Implementação direta é mais explícita sobre o que acontece
- Debugging: Stack trace vai direto ao ponto na versão sem LangChain
- Performance: Implementação direta tem menos overhead (~100ms menos latência)
- Trade-off: LangChain poupa 20 linhas, mas adiciona dependência e complexidade
Exemplo 2: Agent com ferramentas (function calling)
Com LangChain (~120 linhas):
from langchain.agents import initialize_agent, Tool, AgentType
from langchain.chat_models import ChatOpenAI
from langchain.tools import StructuredTool
# Definir ferramentas
def buscar_cliente(cpf: str) -> dict:
# Lógica de busca
return {"nome": "João", "email": "joao@example.com"}
def criar_ticket(titulo: str, descricao: str) -> str:
# Lógica de criação
return f"Ticket #{1234} criado"
tools = [
StructuredTool.from_function(
func=buscar_cliente,
name="buscar_cliente",
description="Busca informações de cliente por CPF"
),
StructuredTool.from_function(
func=criar_ticket,
name="criar_ticket",
description="Cria ticket de suporte"
)
]
# Inicializar agente
llm = ChatOpenAI(model="gpt-4o-mini")
agent = initialize_agent(
tools,
llm,
agent=AgentType.OPENAI_FUNCTIONS,
verbose=True
)
# Uso
result = agent.run("Busque o cliente CPF 123.456.789-00 e crie um ticket de suporte")
Sem LangChain (~90 linhas):
from openai import OpenAI
import json
client = OpenAI()
# Definir ferramentas
tools = [
{
"type": "function",
"function": {
"name": "buscar_cliente",
"description": "Busca informações de cliente por CPF",
"parameters": {
"type": "object",
"properties": {
"cpf": {"type": "string", "description": "CPF do cliente"}
},
"required": ["cpf"]
}
}
},
{
"type": "function",
"function": {
"name": "criar_ticket",
"description": "Cria ticket de suporte",
"parameters": {
"type": "object",
"properties": {
"titulo": {"type": "string"},
"descricao": {"type": "string"}
},
"required": ["titulo", "descricao"]
}
}
}
]
# Funções disponíveis
functions_map = {
"buscar_cliente": lambda cpf: {"nome": "João", "email": "joao@example.com"},
"criar_ticket": lambda titulo, descricao: f"Ticket #{1234} criado"
}
def run_agent(user_message: str) -> str:
messages = [{"role": "user", "content": user_message}]
while True:
# Chamar LLM
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools
)
message = response.choices[0].message
# Se não há tool calls, terminar
if not message.tool_calls:
return message.content
# Executar tool calls
messages.append(message)
for tool_call in message.tool_calls:
func_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
result = functions_map[func_name](**args)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
# Uso
result = run_agent("Busque o cliente CPF 123.456.789-00 e crie um ticket de suporte")
Análise:
- Controle: Versão direta dá controle total sobre o loop do agente
- Debugging: Muito mais fácil ver exatamente onde está o problema
- Performance: Mesma latência (ambos usam function calling nativo)
- Vantagem do LangChain: Parser automático de tool outputs (pequeno ganho)
Quando LangChain realmente se justifica
Depois de analisar dezenas de projetos, identifiquei 3 cenários onde LangChain agrega valor real:
1. Prototipagem rápida para validação de negócio
Contexto: Você tem uma hipótese de produto e precisa validar com usuários em 1-2 semanas.
Por que LangChain: Velocidade de desenvolvimento > performance/manutenibilidade.
Exemplo: MVP de chatbot para atendimento. Use LangChain para ir rápido. Se validar, considere refatorar para produção.
2. Sistemas multi-agente complexos com LangGraph
Contexto: Múltiplos agentes que precisam colaborar, passar estado entre si, com lógica de roteamento condicional.
Por que LangChain: LangGraph oferece abstrações para grafos de execução que são difíceis de implementar bem do zero.
Exemplo:
from langgraph.graph import StateGraph, END
# Definir estados e transições
workflow = StateGraph(AgentState)
workflow.add_node("researcher", research_agent)
workflow.add_node("writer", writing_agent)
workflow.add_node("reviewer", review_agent)
# Lógica de roteamento condicional
workflow.add_conditional_edges(
"reviewer",
lambda x: "writer" if x["quality_score"] menos de 0.8 else END
)
app = workflow.compile()
Implementar isso sem LangGraph exige arquitetura significativa.
3. Necessidade de trocar providers frequentemente
Contexto: Você está experimentando com múltiplos LLMs (OpenAI, Anthropic, Google, open-source) e quer trocar facilmente.
Por que LangChain: Abstração única para múltiplos providers.
Exemplo:
# Trocar de provider é trivial
llm = ChatOpenAI(model="gpt-4") # OpenAI
# llm = ChatAnthropic(model="claude-3-5-sonnet") # Anthropic
# llm = ChatGoogleGenerativeAI(model="gemini-pro") # Google
Na implementação direta, você precisaria adaptar código para cada SDK.
Quando migrar DE LangChain para implementação direta
Sinais de que você deveria migrar:
- Sistema já está validado e em produção (não é mais MVP)
- Performance é importante (latência, throughput)
- Você passa mais tempo debuggando abstrações do LangChain do que resolvendo problemas de negócio
- Seu caso de uso é relativamente simples (RAG básico, chat, extração)
- Time de engenharia é sênior (capaz de implementar direto)
- Versioning do LangChain está causando problemas (breaking changes)
Processo de migração:
Semana 1-2: Análise
- Identifique quais partes do LangChain você realmente usa
- Liste funcionalidades críticas que precisam ser mantidas
- Estime esforço de reimplementação (geralmente 2-4 semanas)
Semana 3-4: Reimplementação 4. Comece com testes: escreva testes end-to-end que definem comportamento esperado 5. Reimplemente usando SDKs oficiais 6. Mantenha ambas as versões rodando em paralelo (shadow mode)
Semana 5-6: Validação e rollout 7. Compare resultados entre as duas versões 8. Meça diferenças de latência e precisão 9. Faça rollout gradual (5% → 20% → 50% → 100%)
Alternativas ao LangChain
Se você decidiu que LangChain não é ideal para o seu caso:
Para RAG:
- LlamaIndex: Focado especificamente em RAG, menos genérico que LangChain
- Haystack: Framework mais opinativo para pipelines de NLP
- Implementação direta: OpenAI SDK + ChromaDB/Pinecone/Weaviate
Para agentes:
- CrewAI: Framework para sistemas multi-agente, mais simples que LangGraph
- AutoGen (Microsoft): Foco em agentes conversacionais que colaboram
- Implementação direta: OpenAI function calling + orquestração custom
Para orquestração:
- Prefect/Airflow: Se você precisa de workflows complexos e observabilidade
- Temporal: Se você precisa de durabilidade e retries sofisticados
Os 5 erros mais comuns com LangChain
1. Usar LangChain porque todos estão usando
LangChain é popular, mas não é sempre a escolha certa.
Correto: Avalie se resolve um problema específico seu. Se não, implemente direto.
2. Não entender as abstrações que está usando
Usar ConversationalRetrievalChain sem entender o que acontece por baixo dificulta debugging.
Correto: Leia o código fonte das chains que você usa. Se não entender, talvez seja muito abstrato para seu caso.
3. Confiar cegamente no “quick start”
Tutoriais de LangChain frequentemente mostram happy path sem tratar erros ou edge cases.
Correto: Implemente tratamento de erros robusto desde o início.
4. Não versionar dependências corretamente
LangChain tem histórico de breaking changes.
Correto: Use versões específicas no requirements.txt (ex: langchain==0.1.0, não langchain).
5. Tentar usar todas as features
LangChain tem centenas de componentes. É tentador usar todos.
Correto: Use apenas o que resolve seu problema. Menos é mais.
Checklist de decisão: Usar LangChain?
Use este checklist antes de adicionar LangChain ao projeto:
✅ Use LangChain SE:
- Você está prototipando MVP (velocidade > performance)
- Precisa de sistema multi-agente complexo (LangGraph)
- Vai trocar de provider de LLM frequentemente
- Time tem experiência prévia com LangChain
- Você usa pelo menos 3-4 componentes diferentes do framework
⚠️ Considere alternativas SE:
- Caso de uso é simples (RAG básico, chat, extração)
- Performance e latência são críticas
- Time é sênior e capaz de implementar direto
- Sistema já está em produção e estável
- Você usa apenas 1-2 componentes do LangChain
❌ Evite LangChain SE:
- Você não entende o que as abstrações fazem
- Está usando apenas porque “parece o jeito certo”
- Projeto é crítico para o negócio (use código que você controla)
- Time não tem experiência com LangChain
- Orçamento de latência é menos de 500ms
A recomendação prática
Depois de anos vendo projetos com e sem LangChain, minha recomendação:
Para MVPs e prototipagem: Use LangChain. Velocidade importa mais que perfeição.
Para produção em escala: Avalie criticamente. Na maioria dos casos, implementação direta com SDKs oficiais é mais simples, mais rápida e mais fácil de manter.
Para sistemas multi-agente: Use LangGraph. É genuinamente superior às alternativas.
Regra de ouro: Comece sem LangChain. Adicione apenas se encontrar um problema específico que ele resolve melhor.
Não use LangChain porque parece o “jeito certo” de fazer IA. Use quando ele resolve um problema concreto que você tem.
Conclusão
LangChain é uma ferramenta poderosa, mas não é sempre necessária. Os resultados que vejo:
Projetos que usam LangChain bem:
- Prototipam 2-3x mais rápido
- Conseguem testar múltiplos providers facilmente
- Sistemas multi-agente funcionam bem com LangGraph
Projetos que migraram para implementação direta:
- 30-50% de redução em latência
- 50-70% menos tempo debuggando
- Código 30-40% menor e mais claro
- Cobertura de testes 2-3x maior
A pergunta não é “LangChain é bom?” — é “LangChain é bom para o MEU caso de uso específico?”
Avalie honestamente. Protótipo com LangChain. Produza com o que fizer mais sentido para o seu contexto.
Está arquitetando um sistema de IA e quer uma segunda opinião sobre a stack técnica?