O LangChain chegou à versão 1.0 em outubro de 2025 e, quase um ano depois, o projeto já ultrapassa 145 mil estrelas no GitHub (dados de setembro de 2026). A framework deixou de ser um conjunto solto de abstrações para chains e passou a apostar tudo em agentes: a nova função create_agent() substitui o antigo createReactAgent do LangGraph e tornou-se o ponto de entrada oficial para quem quer construir um agente de IA capaz de usar ferramentas, manter memória e responder com base em documentos próprios.

Este tutorial mostra, passo a passo, como instalar o LangChain 1.0, criar um agente funcional com ferramentas personalizadas, ligar esse agente a uma base de conhecimento própria via RAG (Retrieval-Augmented Generation) e blindar o código contra as vulnerabilidades já conhecidas na framework. No final, vais ter um assistente de suporte técnico completo, a correr localmente, com observabilidade via LangSmith.

O guia serve tanto para quem nunca tocou no LangChain como para quem já tem projetos antigos em 0.x e precisa de perceber o que vai partir na migração. Não vamos assumir conhecimento prévio de agentes de IA, mas vamos assumir que já sabes programar em Python e que tens uma conta ativa junto de pelo menos um fornecedor de modelos (OpenAI, Anthropic ou DeepSeek). Cada passo inclui o código completo, o resultado esperado no terminal e, sempre que relevante, a razão de segurança por trás de uma escolha de configuração específica.

O que é o LangChain 1.0 e porque está em todo o lado

O LangChain nasceu em 2022 como uma biblioteca Python para encadear chamadas a modelos de linguagem. Cresceu depressa, ganhou dezenas de integrações e, por isso mesmo, acumulou uma quantidade enorme de abstrações concorrentes entre si. A versão 1.0, lançada em outubro de 2025, é uma tentativa deliberada de travar essa fragmentação: a equipa da LangChain chama-lhe uma base “LTS” (long-term support) pensada especificamente para produção, não para experimentação.

Segundo a documentação oficial, o LangChain 1.0 assenta em três pilares: uma API de agentes unificada através de create_agent(), uma limpeza de interfaces legadas que se acumularam ao longo de três anos de versões 0.x, e uma integração mais direta com o LangGraph para orquestração de estados. Isto significa, na prática, que já não é preciso escolher entre meia dúzia de classes de agente diferentes: há uma função, com um conjunto claro de parâmetros, e o resto é configuração.

Há também um motivo menos falado para a atenção que o LangChain está a receber agora: a framework acumulou, entre 2025 e 2026, cinco CVEs distintos, incluindo uma falha de path traversal com CVSS 7.5. Quem já tem projetos LangChain em produção precisa de saber exatamente que versões corrigem cada problema, e é por isso que este tutorial trata a segurança como parte do processo de instalação, não como um apêndice no fim.

Vale ainda notar uma tensão interessante no próprio ecossistema. O repositório langchain-ai/langchain continua entre os projetos de IA mais estrelados do GitHub, mas várias análises de 2026 apontam que parte das equipas de produção migrou dele para SDKs diretos dos fornecedores de modelos, por razões de desempenho e controlo. Isso não torna o LangChain irrelevante, muito pelo contrário: continua a ser a opção mais rápida para prototipar um agente com ferramentas, memória e RAG num único dia de trabalho, que é exatamente o que este tutorial propõe fazer.

Do 0.x ao 1.0: as mudanças que vão quebrar o teu código

Antes de instalar seja o que for, vale a pena perceber o que mudou. O LangChain segue agora uma política de versionamento semântico mais rígida: mudanças que quebram compatibilidade só acontecem em versões major (a passagem de 0.x para 1.0 é exatamente esse tipo de salto). Três alterações merecem destaque especial para quem vem de projetos antigos.

  • O parâmetro secrets_from_env deixou de ter valor True por omissão. Código que dependia do carregamento automático de segredos a partir de variáveis de ambiente passa a falhar silenciosamente até seres explícito sobre isso.
  • O carregamento de templates Jinja2 ficou bloqueado por omissão através de um novo init_validator, depois de se descobrir que templates maliciosos conseguiam aceder a atributos internos de objetos Python.
  • As classes de agente antigas (como as várias variantes de AgentExecutor) continuam a funcionar mas estão marcadas como legadas: a documentação recomenda migrar tudo para create_agent().

Se o teu projeto ainda corre em LangChain 0.3.x, a boa notícia é que grande parte da correção de segurança também chegou a essa linha (0.3.80 e 0.3.81, por exemplo). Não precisas de saltar para o 1.0 amanhã, mas precisas de atualizar já as dependências de segurança, seja qual for a linha que usas.

Pré-requisitos: contas, versões e ferramentas

Antes de avançar, confirma que tens isto pronto na tua máquina. O LangChain 1.0 exige Python 3.10 ou superior, conforme a política de versões publicada pela equipa do projeto. Nada abaixo disso vai instalar.

RequisitoVersão mínimaNota
Python3.10Exigido pelo LangChain 1.0; recomenda-se 3.11 ou 3.12
langchain1.4.0Versão mais recente à data de escrita (3 de setembro de 2026)
langchain-core1.6.3Corrige as três CVEs de 2025-2026 descritas abaixo
langchain-openai1.6.1Só é preciso se usares modelos OpenAI
langchain-community0.3.27 ou superiorCorrige falhas em EverNoteLoader e FAISS
chromadblatest versionBase de dados vetorial usada neste tutorial
Conta OpenAI, Anthropic ou DeepSeekPrecisas de uma chave de API de pelo menos um fornecedor
Conta LangSmith (opcional)Plano gratuito chega para seguir este tutorial

Não precisas de GPU nem de máquina potente: este tutorial usa APIs de modelos alojados, não modelos locais. Reserva cerca de 60 minutos para completar todos os passos com calma, incluindo os testes. Se preferires usar um modelo local por questões de custo ou privacidade, o LangChain também se integra com o Ollama através do pacote langchain-ollama, mas os exemplos de código abaixo assumem um fornecedor por API para simplificar.

Passo 1: Preparar o ambiente Python isolado

Cria uma pasta dedicada ao projeto e um ambiente virtual. Isto evita conflitos de versões entre este projeto e outros que já tenhas na máquina, algo particularmente importante com o LangChain porque o ecossistema tem dezenas de subpacotes que precisam de andar sincronizados.

mkdir assistente-langchain
cd assistente-langchain
python3 -m venv .venv
source .venv/bin/activate

# Confirma a versão do Python antes de continuar
python3 --version
# Deve devolver 3.10.x ou superior

Em Windows, o comando de ativação é .venv\Scripts\activate em vez de source .venv/bin/activate. Se estiveres a usar Poetry ou uv em vez de venv, o raciocínio é o mesmo: isola as dependências deste projeto do resto do sistema.

Passo 2: Instalar o LangChain 1.0 e os pacotes de integração

Cria um ficheiro requirements.txt com versões fixadas. Fixar versões é especialmente relevante aqui: como vimos, várias versões antigas do langchain-core têm falhas de segurança conhecidas, por isso convém escrever o ficheiro de forma a nunca instalar por engano uma versão vulnerável. Podes confirmar sempre o número da versão mais recente disponível na página do langchain-core no PyPI antes de fixares o número no teu ficheiro.

langchain>=1.4.0
langchain-core>=1.6.3
langchain-openai>=1.6.1
langchain-community>=0.3.27
langgraph
chromadb
python-dotenv
langsmith
pip install -r requirements.txt

# Confirma a versão instalada do langchain-core
pip show langchain-core | grep Version

Se estiveres a usar Anthropic em vez de OpenAI, adiciona langchain-anthropic>=1.7.2 ao ficheiro. O LangChain segue o mesmo padrão para praticamente todos os fornecedores: um pacote genérico (langchain), um núcleo partilhado (langchain-core) e um pacote de integração por fornecedor.

Passo 3: Configurar as chaves de API em segurança

Nunca escrevas chaves de API diretamente no código. Cria um ficheiro .env na raiz do projeto e adiciona-o de imediato ao .gitignore, antes de escreveres qualquer segredo lá dentro.

# .gitignore
.env
.venv/
__pycache__/
chroma_db/
# .env
OPENAI_API_KEY=sk-a-tua-chave-aqui
LANGSMITH_API_KEY=lsv2-a-tua-chave-aqui
LANGSMITH_TRACING=true
LANGSMITH_PROJECT=assistente-suporte

Lembra-te da mudança de comportamento referida acima: a partir das versões corrigidas do langchain-core, o carregamento automático de segredos a partir do ambiente (secrets_from_env) já não acontece por omissão. Isto é intencional e reduz o risco de um segredo ser exposto sem querer durante a serialização de um objeto. Carrega o ficheiro .env de forma explícita no início do teu script.

from dotenv import load_dotenv
load_dotenv()

import os
assert os.getenv("OPENAI_API_KEY"), "Falta a OPENAI_API_KEY no .env"

Passo 4: A primeira chamada a um modelo de chat

Com o ambiente pronto, o próximo passo é confirmar que consegues falar com o modelo antes de complicares com agentes e ferramentas. O LangChain 1.0 unificou a forma de inicializar modelos através de init_chat_model(), que aceita o nome do modelo e escolhe automaticamente o pacote de integração certo.

from dotenv import load_dotenv
load_dotenv()

from langchain.chat_models import init_chat_model

modelo = init_chat_model("gpt-4o-mini", model_provider="openai")

resposta = modelo.invoke("Explica o que é RAG em duas frases, em português de Portugal.")
print(resposta.content)

Ao correr o script, deves ver algo semelhante a isto no terminal:

$ python3 primeiro_teste.py
RAG significa Retrieval-Augmented Generation: em vez de o modelo responder só
com o que aprendeu no treino, o sistema procura primeiro documentos relevantes
numa base própria e junta-os à pergunta antes de gerar a resposta.

Se este passo funcionar, tens confirmação de que a chave de API está correta e que o pacote de integração está bem instalado. Só depois disto faz sentido avançar para agentes. É tentador saltar direto para create_agent(), mas isolar primeiro a chamada mais simples poupa tempo de diagnóstico mais tarde: se algo falhar num agente com cinco ferramentas, memória e RAG, é bem mais difícil perceber se o problema está na chave de API, no modelo escolhido ou na lógica do agente em si.

Passo 5: Prompts, templates e o risco de injeção

O LangChain usa templates para separar instruções fixas de conteúdo variável (a pergunta do utilizador, por exemplo). É precisamente aqui que surgiu uma das vulnerabilidades mais recentes da framework: uma falha de injeção de template que, em versões entre a 1.0.0 e a 1.0.6, permitia aceder a atributos internos de objetos Python através da sintaxe do próprio template.

from langchain_core.prompts import ChatPromptTemplate

template = ChatPromptTemplate.from_messages([
    ("system", "És um assistente de suporte técnico. Responde sempre em português de Portugal."),
    ("human", "{pergunta}")
])

mensagens = template.invoke({"pergunta": "Como reinicio o router?"})
print(mensagens)

Duas regras práticas evitam problemas: nunca construas templates a partir de texto fornecido diretamente pelo utilizador final (usa sempre variáveis de input, como {pergunta} acima, em vez de concatenar strings), e mantém o langchain-core atualizado para a versão 1.6.3 ou superior, que já bloqueia por omissão a inicialização insegura de templates Jinja2.

Passo 6: Criar o primeiro agente com create_agent()

Chegamos à peça central do LangChain 1.0. A função create_agent() substitui o antigo createReactAgent do LangGraph e constrói, por baixo, um grafo de estados compilado: o modelo é chamado com a lista de mensagens, e se a resposta contiver pedidos de chamada de ferramentas (tool_calls), o grafo executa essas ferramentas e volta a chamar o modelo, em ciclo, até já não haver mais ferramentas a chamar.

from dotenv import load_dotenv
load_dotenv()

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model

modelo = init_chat_model("gpt-4o-mini", model_provider="openai")

agente = create_agent(
    model=modelo,
    tools=[],
    system_prompt="És um assistente de suporte técnico, direto e educado."
)

resultado = agente.invoke({"messages": [("human", "Boa tarde, o meu router não liga.")]})
print(resultado["messages"][-1].content)

Repara que o agente ainda não tem ferramentas (tools=[]). Neste estado, comporta-se como um chatbot normal: recebe mensagens, responde, sem capacidade de agir sobre o mundo exterior. O próximo passo resolve isso.

Passo 7: Adicionar ferramentas personalizadas ao agente

Uma ferramenta (tool) é, na prática, uma função Python normal com uma descrição que o modelo consegue ler e decidir se e quando a deve chamar. O LangChain usa o decorador @tool para transformar qualquer função nisto.

from langchain_core.tools import tool

@tool
def consultar_estado_servico(regiao: str) -> str:
    """Consulta o estado atual do serviço numa região (norte, centro, sul)."""
    estados = {
        "norte": "sem incidentes registados",
        "centro": "lentidão pontual reportada às 14h",
        "sul": "sem incidentes registados",
    }
    return estados.get(regiao.lower(), "região desconhecida")

@tool
def abrir_ticket(descricao: str, prioridade: str = "normal") -> str:
    """Abre um ticket de suporte com uma descrição e uma prioridade (baixa, normal, alta)."""
    numero = 48213
    return f"Ticket #{numero} aberto com prioridade '{prioridade}': {descricao}"

agente = create_agent(
    model=modelo,
    tools=[consultar_estado_servico, abrir_ticket],
    system_prompt="És um assistente de suporte técnico. Usa as ferramentas disponíveis sempre que precisares de dados concretos."
)

resultado = agente.invoke({
    "messages": [("human", "O meu router não liga e estou no Porto. Podes ver se há problemas na zona e abrir um ticket?")]
})
print(resultado["messages"][-1].content)

Ao correr este script, o agente identifica a região correspondente ao Porto, chama consultar_estado_servico, lê o resultado, decide que também deve abrir um ticket, chama abrir_ticket e só depois formula a resposta final ao utilizador. Todo este raciocínio acontece dentro do ciclo do grafo, sem que precises de o programar manualmente.

Um detalhe que costuma confundir quem vem de outras frameworks de agentes: não és tu que decides a ordem das chamadas às ferramentas. É o próprio modelo, com base na descrição (docstring) de cada função, que escolhe quando e em que sequência as usar. Por isso, escrever docstrings claras e específicas nas tuas tools não é um detalhe estético, é o que determina se o agente as vai usar corretamente ou não.

Passo 8: Memória e conversas persistentes

Sem memória, cada chamada ao agente é uma conversa nova. Para manteres o histórico entre mensagens (essencial num assistente real), usa um checkpointer e identifica cada conversa com um thread_id.

from langgraph.checkpoint.memory import InMemorySaver

memoria = InMemorySaver()

agente = create_agent(
    model=modelo,
    tools=[consultar_estado_servico, abrir_ticket],
    system_prompt="És um assistente de suporte técnico.",
    checkpointer=memoria
)

config = {"configurable": {"thread_id": "cliente-4471"}}

agente.invoke({"messages": [("human", "O meu router não liga.")]}, config)
resultado = agente.invoke({"messages": [("human", "Já agora, estou em Lisboa.")]}, config)
print(resultado["messages"][-1].content)

Como o thread_id é o mesmo nas duas chamadas, o agente lembra-se do contexto anterior (o problema do router) quando recebe a segunda mensagem. Em produção, troca o InMemorySaver por um checkpointer persistente, como o baseado em SQLite ou Postgres, para o histórico sobreviver a um reinício do servidor.

Nota de segurança: se usares o checkpointer SQLite do LangGraph, confirma que tens a versão langgraph-checkpoint-sqlite 3.0.1 ou superior instalada. Versões anteriores tinham uma vulnerabilidade de injeção SQL que permitia execução remota de código.

Passo 9: Construir a base RAG com Chroma

Um agente com ferramentas fixas só sabe o que tu programaste. Para responder com base em documentação própria (manuais, políticas internas, FAQs longas), precisas de RAG: transformar os documentos em vetores, guardá-los numa base de dados vetorial e ir lá buscar os trechos mais relevantes a cada pergunta.

from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma

loader = TextLoader("manual_suporte.txt", encoding="utf-8")
documentos = loader.load()

splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50)
fragmentos = splitter.split_documents(documentos)

embeddings = OpenAIEmbeddings(model="text-embedding-3-small")

base_vetorial = Chroma.from_documents(
    documents=fragmentos,
    embedding=embeddings,
    persist_directory="./chroma_db"
)

recuperador = base_vetorial.as_retriever(search_kwargs={"k": 3})

Cria um ficheiro manual_suporte.txt simples com algumas secções (configuração de router, políticas de garantia, horários de atendimento) para testares. O persist_directory grava a base vetorial em disco, para não teres de recalcular os vetores sempre que reinicias o script.

Os valores de chunk_size e chunk_overlap não são arbitrários. Um chunk_size de 500 caracteres costuma equilibrar bem dois objetivos opostos: fragmentos pequenos de mais perdem contexto (uma frase cortada a meio raramente responde sozinha a uma pergunta), fragmentos grandes de mais diluem a relevância de cada trecho recuperado. O chunk_overlap de 50 caracteres evita que uma informação importante fique cortada exatamente na fronteira entre dois fragmentos. Para manuais técnicos mais longos, vale a pena experimentar valores entre 300 e 800 caracteres e comparar a qualidade das respostas.

Passo 10: Ligar o RAG ao agente e testar

Com o recuperador pronto, transforma-o numa ferramenta como qualquer outra. É esta a parte que costuma surpreender quem vem de versões antigas do LangChain: já não existe uma classe especial “RetrievalQA”, o recuperador é apenas mais uma tool que o agente decide usar ou não.

from langchain_core.tools import tool

@tool
def consultar_manual(pergunta: str) -> str:
    """Procura no manual de suporte trechos relevantes para responder à pergunta."""
    documentos_relevantes = recuperador.invoke(pergunta)
    return "\n\n".join(doc.page_content for doc in documentos_relevantes)

agente = create_agent(
    model=modelo,
    tools=[consultar_estado_servico, abrir_ticket, consultar_manual],
    system_prompt=(
        "És um assistente de suporte técnico. Usa consultar_manual sempre que "
        "a pergunta parecer estar coberta pela documentação interna."
    ),
    checkpointer=memoria
)

config = {"configurable": {"thread_id": "cliente-9902"}}
resultado = agente.invoke(
    {"messages": [("human", "Qual é o prazo de garantia do router e como faço para o ativar?")]},
    config
)
print(resultado["messages"][-1].content)

Se tudo estiver bem ligado, a resposta final deve citar factos que só existem no teu ficheiro manual_suporte.txt, não conhecimento genérico do modelo. Essa é a prova de que o RAG está mesmo a influenciar a resposta, e não apenas a correr em paralelo sem efeito.

Passo 11: Observabilidade com LangSmith

Depurar um agente “às cegas” é frustrante: quando a resposta sai errada, precisas de ver exatamente que ferramentas foram chamadas, com que argumentos, e em que ordem. É para isso que serve o LangSmith, a plataforma oficial de observabilidade e avaliação para LangChain e LangGraph.

Já configuraste as variáveis de ambiente no Passo 3 (LANGSMITH_TRACING=true e LANGSMITH_API_KEY). A partir daí, qualquer agente criado com create_agent() passa a enviar traces automaticamente, sem precisares de alterar o código do agente em si.

export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY="lsv2-a-tua-chave"
export LANGSMITH_PROJECT="assistente-suporte"

python3 assistente.py

Depois de correres o script com estas variáveis ativas, abre o painel do LangSmith e vais ver uma árvore com cada passo do agente: a chamada inicial ao modelo, cada tool chamada, os argumentos exatos e o tempo que cada etapa demorou. Isto poupa horas quando um agente começa a comportar-se de forma inesperada em produção.

Passo 12: Testar, avaliar e corrigir as CVEs conhecidas

Antes de dares o projeto por terminado, vale a pena fazer duas verificações: confirmar que as dependências estão livres de vulnerabilidades conhecidas, e escrever pelo menos um teste automático que valide o comportamento do agente.

pip install pip-audit
pip-audit

# Devolve uma lista de pacotes instalados com CVEs conhecidas, se existirem
def test_agente_abre_ticket():
    resultado = agente.invoke({
        "messages": [("human", "O router não liga, abre um ticket urgente.")]
    })
    texto_final = resultado["messages"][-1].content.lower()
    assert "ticket" in texto_final

A tabela seguinte resume as vulnerabilidades conhecidas do ecossistema LangChain em 2025 e 2026. Vale a pena guardá-la e verificar as tuas versões instaladas com pip show antes de colocar qualquer agente em produção.

CVEComponenteVersões afetadasCorrigido emGravidade
CVE-2025-68664langchain-core1.0.0 a 1.2.4; abaixo de 0.3.811.2.5 / 0.3.81Injeção de serialização
CVE-2025-65106langchain (prompt templates)1.0.0 a 1.0.6; abaixo de 0.3.801.0.7 / 0.3.80Injeção de template
CVE-2026-34070langchain-core (loading.py)Abaixo de 1.2.221.2.22CVSS 7.5, path traversal
CVE-2025-67644langgraph-checkpoint-sqliteAbaixo de 3.0.13.0.1Injeção SQL / RCE
CVE-2025-6984langchain-community (EverNoteLoader)Abaixo de 0.3.270.3.27XXE
CVE-2024-5998langchain-community (FAISS)Abaixo de 0.3.270.3.27Deserialização pickle

Como o langchain-core 1.6.3, usado neste tutorial, já é bastante posterior à versão 1.2.22, o exemplo que construíste está protegido contra todas estas falhas. O risco real está em projetos antigos que nunca foram atualizados desde 2025. Podes consultar o registo completo do CVE-2026-34070 na base de dados OSV para veres a descrição técnica exata da falha de path traversal e confirmares se algum outro componente do teu stack depende da mesma função de carregamento de ficheiros.

Projeto completo: assistente de suporte técnico pronto a usar

Junta tudo o que construíste nos passos anteriores num único ficheiro assistente.py. Este é o projeto completo, pronto a correr, combinando ferramentas personalizadas, memória persistente e RAG sobre documentação própria.

from dotenv import load_dotenv
load_dotenv()

from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain_core.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma

# --- Base RAG ---
loader = TextLoader("manual_suporte.txt", encoding="utf-8")
fragmentos = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50).split_documents(loader.load())
base_vetorial = Chroma.from_documents(
    documents=fragmentos,
    embedding=OpenAIEmbeddings(model="text-embedding-3-small"),
    persist_directory="./chroma_db"
)
recuperador = base_vetorial.as_retriever(search_kwargs={"k": 3})

# --- Ferramentas ---
@tool
def consultar_estado_servico(regiao: str) -> str:
    """Consulta o estado atual do serviço numa região (norte, centro, sul)."""
    estados = {"norte": "sem incidentes", "centro": "lentidão pontual", "sul": "sem incidentes"}
    return estados.get(regiao.lower(), "região desconhecida")

@tool
def abrir_ticket(descricao: str, prioridade: str = "normal") -> str:
    """Abre um ticket de suporte com uma descrição e uma prioridade (baixa, normal, alta)."""
    return f"Ticket #48213 aberto com prioridade '{prioridade}': {descricao}"

@tool
def consultar_manual(pergunta: str) -> str:
    """Procura no manual de suporte trechos relevantes para responder à pergunta."""
    return "\n\n".join(doc.page_content for doc in recuperador.invoke(pergunta))

# --- Agente ---
modelo = init_chat_model("gpt-4o-mini", model_provider="openai")
memoria = InMemorySaver()

agente = create_agent(
    model=modelo,
    tools=[consultar_estado_servico, abrir_ticket, consultar_manual],
    system_prompt=(
        "És um assistente de suporte técnico em português de Portugal. "
        "Usa consultar_manual para questões de política e garantia, "
        "consultar_estado_servico para questões de rede, e abre tickets "
        "sempre que o cliente reportar uma avaria."
    ),
    checkpointer=memoria
)

if __name__ == "__main__":
    config = {"configurable": {"thread_id": "sessao-cli"}}
    print("Assistente de suporte pronto. Escreve 'sair' para terminar.")
    while True:
        pergunta = input("\nTu: ")
        if pergunta.strip().lower() == "sair":
            break
        resultado = agente.invoke({"messages": [("human", pergunta)]}, config)
        print("Assistente:", resultado["messages"][-1].content)

Corre com python3 assistente.py e testa perguntas como “o router não liga, estou em Faro” ou “qual é o prazo de garantia?”. Deves ver o agente a alternar entre as três ferramentas consoante o assunto, sempre mantendo o contexto da conversa graças ao checkpointer.

Erros comuns ao trabalhar com LangChain 1.0

Estes são os cinco erros que mais aparecem em projetos recentes com LangChain 1.0, segundo os próprios avisos de segurança e a documentação de migração da equipa do projeto.

  • Ficar em versões antigas do langchain-core. Muitos projetos continuam presos entre a 1.0.0 e a 1.2.4, exatamente a janela vulnerável ao CVE-2025-68664. Corre pip show langchain-core regularmente.
  • Depender do carregamento automático de segredos. Com secrets_from_env agora a False por omissão, código antigo que assumia esse comportamento passa a devolver erros de autenticação difíceis de diagnosticar à primeira vista.
  • Construir templates a partir de texto do utilizador. Concatenar a pergunta do utilizador diretamente na string do template, em vez de a passar como variável, reabre a porta para injeção mesmo em versões corrigidas.
  • Misturar classes de agente antigas com create_agent(). Tentar reaproveitar código com AgentExecutor ou createReactAgent dentro de um fluxo pensado para create_agent() costuma gerar erros de tipo confusos.
  • Esquecer o thread_id. Sem um thread_id consistente, o checkpointer não tem forma de saber que duas chamadas pertencem à mesma conversa, e a “memória” do agente simplesmente não funciona.

Nenhum destes erros é difícil de corrigir isoladamente. O problema é que costumam aparecer combinados: um projeto que ainda usa AgentExecutor, numa versão antiga do langchain-core, sem testes automáticos, é um projeto onde qualquer um destes cinco pontos pode falhar sem aviso. Reserva 20 minutos, antes de avançares para produção, só para percorrer esta lista com o teu próprio código.

Resolução de problemas: os erros mais frequentes e as soluções

SintomaCausa provávelSolução
ModuleNotFoundError: langchain_chromaPacote de integração não instaladoCorre pip install langchain-chroma
AuthenticationError ao chamar o modeloChave de API não carregada ou secrets_from_env desativadoConfirma que chamaste load_dotenv() antes de importar o modelo
Agente entra em ciclo e não terminaFerramenta não devolve um valor que satisfaça a condição de paragemGarante que cada tool devolve sempre uma string, mesmo em caso de erro
Memória “esquece” a conversa anteriorthread_id diferente entre chamadasUsa sempre o mesmo thread_id por sessão de utilizador
RAG devolve respostas genéricas, sem citar o manualRecuperador não está a ser chamado pelo agenteReforça no system_prompt quando usar consultar_manual
chromadb falha ao persistir no discoPasta persist_directory sem permissões de escritaConfirma permissões da pasta ou usa um caminho absoluto
Traces não aparecem no LangSmithVariáveis de ambiente não exportadas na sessão do terminalExporta LANGSMITH_TRACING e LANGSMITH_API_KEY antes de correr o script
pip-audit reporta CVE em langchain-communityVersão abaixo de 0.3.27Atualiza com pip install -U langchain-community>=0.3.27
Erro de tipo ao passar mensagens ao agenteFormato de mensagens antigo (dicionários) em vez de tuplosUsa o formato (“human”, “texto”) aceite pelo create_agent

Dicas avançadas para produção

Depois de teres o agente a funcionar localmente, há um conjunto de ajustes que fazem diferença real quando o projeto sai do teu portátil para um servidor com utilizadores verdadeiros.

  • Troca o InMemorySaver por um checkpointer persistente (SQLite ou Postgres) antes de ires para produção, ou perdes todo o histórico a cada reinício.
  • Define limites de tempo (timeouts) nas ferramentas que fazem chamadas externas, para o agente não ficar bloqueado à espera de uma API lenta.
  • Usa o LangSmith não só para depuração mas também para avaliação: cria um conjunto de perguntas de teste e corre-o sempre que mudares o system_prompt, para detetar regressões.
  • Faz rate limiting às ferramentas que abrem tickets ou enviam emails, para um utilizador malicioso não conseguir abusar do agente para gerar spam.
  • Corre pip-audit como parte do pipeline de integração contínua, não só manualmente. As correções de segurança do LangChain têm saído com frequência trimestral desde 2025.
  • Regista o número de tokens consumidos por conversa, especialmente em agentes com RAG: cada chamada ao recuperador pode devolver vários fragmentos de texto que entram todos no contexto enviado ao modelo, o que encarece rapidamente conversas longas.
  • Documenta, junto de cada tool, o que acontece se a chamada externa falhar (API em baixo, timeout). Um agente que trata bem os erros das próprias ferramentas evita respostas confusas ao utilizador final.

Nenhuma destas medidas exige reescrever o projeto do zero. São, na sua maioria, configurações e verificações que se acrescentam ao código que já construíste ao longo deste tutorial, sem alterar a lógica central do agente.

LangChain 1.0 vs LangGraph vs CrewAI: qual escolher

Uma dúvida comum de quem chega agora ao ecossistema é se deve usar LangChain, LangGraph ou uma alternativa como o CrewAI. Não são exatamente concorrentes: o LangGraph é a camada de orquestração que o próprio create_agent() usa por baixo, e o LangChain fornece os componentes (modelos, ferramentas, prompts) que correm dentro dessa orquestração. O CrewAI segue uma filosofia diferente, orientada a papéis de equipa (um agente “investigador”, outro “escritor”, por exemplo) em vez de um único grafo de ferramentas.

CaracterísticaLangChain 1.0LangGraphCrewAI
Foco principalComponentes + agente unificado (create_agent)Orquestração de estados e ciclosEquipas de agentes com papéis definidos
Curva de aprendizagemModeradaMais técnica (grafos explícitos)Baixa para casos simples
Usa-se sozinho ou combinadoCombinado com LangGraph por baixoPode ser usado sozinho ou sob o LangChainSozinho, com integrações próprias
Observabilidade nativaLangSmith (automática com create_agent)LangSmithIntegrações de terceiros
Melhor paraUm agente com várias ferramentas e memóriaFluxos complexos com múltiplos estados e condiçõesVários agentes especializados a colaborar

Para o caso de uso deste tutorial (um único assistente com ferramentas e RAG), o LangChain 1.0 sozinho já chega, porque create_agent() trata da orquestração internamente. Se precisares de vários agentes especializados a colaborar entre si, ou de fluxos com ramificações condicionais complexas, vale a pena explorar diretamente o LangGraph ou o CrewAI.

Na prática, muitas equipas acabam por usar as três ferramentas em conjunto ao longo do tempo: começam com LangChain para prototipar depressa, migram partes específicas para LangGraph quando o fluxo cresce em complexidade, e só recorrem ao CrewAI quando o problema deixa de ser “um agente com várias ferramentas” e passa a ser “vários agentes com responsabilidades distintas a negociar entre si”. Não há uma escolha universalmente certa, há uma escolha certa para a fase em que o teu projeto está.

Perguntas frequentes

O LangChain 1.0 é gratuito?

Sim, o LangChain é uma biblioteca open source e a sua instalação não tem custo. O que pode ter custo são as chamadas às APIs dos modelos (OpenAI, Anthropic, DeepSeek) e o uso do LangSmith além do plano gratuito.

Preciso de migrar já o meu projeto 0.x para o 1.0?

Não é obrigatório de imediato, mas as correções de segurança mais recentes (como a do CVE-2026-34070) também chegaram à linha 0.3.x. O mais urgente é atualizar as dependências para as versões corrigidas, mesmo que ainda não migres para create_agent().

Posso usar o LangChain 1.0 sem o LangGraph?

Sim, para chains simples (uma chamada ao modelo, um prompt fixo) não precisas de instalar o LangGraph. Mas create_agent() depende dele por baixo, por isso, assim que criares um agente com ferramentas, o LangGraph entra automaticamente como dependência.

Qual é a diferença entre create_agent() e o antigo AgentExecutor?

O AgentExecutor é a abordagem legada, mantida por compatibilidade mas já não recomendada. O create_agent() constrói um grafo de estados compilado, com uma API mais simples e maior capacidade de personalização através de middleware e hooks.

É seguro usar LangChain em produção depois destas CVEs?

Sim, desde que mantenhas as dependências atualizadas para as versões corrigidas (langchain-core 1.6.3 ou superior, langchain-community 0.3.27 ou superior). As falhas descobertas em 2025 e 2026 já têm patch disponível há vários meses.

O LangSmith é obrigatório para usar o LangChain?

Não. O LangSmith é opcional e serve para observabilidade e avaliação. O agente funciona perfeitamente sem ele, mas depurar problemas complexos fica bastante mais difícil sem visibilidade sobre cada passo do agente.

Que base de dados vetorial devo usar em vez do Chroma?

O Chroma é uma boa escolha para começar por ser local e simples de configurar. Para projetos maiores, o FAISS e o Pinecone são integrações comuns do ecossistema LangChain, mas exigem mais configuração de infraestrutura.

Consigo usar este tutorial com modelos DeepSeek em vez de OpenAI?

Sim. Basta trocar o pacote de integração e o argumento model_provider em init_chat_model() pelo fornecedor correspondente. A lógica dos agentes, ferramentas e RAG mantém-se exatamente igual.

O que acontece se eu não atualizar as dependências vulneráveis?

O agente continua a funcionar normalmente no dia a dia, mas fica exposto às falhas descritas na tabela de CVEs deste tutorial. Um atacante com acesso a inputs não controlados (por exemplo, texto de utilizadores finais que chega a um template ou a um carregador de ficheiros) poderia explorar essas falhas para aceder a dados internos ou executar código não autorizado.

Consigo usar Ollama com o LangChain para correr modelos localmente?

Sim, através do pacote langchain-ollama. A vantagem é não depender de uma API externa nem pagar por token consumido; a desvantagem é precisares de hardware capaz de correr o modelo com latência aceitável, e a qualidade das respostas costuma ficar abaixo dos modelos maiores disponíveis por API.