Construir um chatbot que responde a uma pergunta é fácil. Construir um agente que planeia, chama ferramentas, corrige os próprios erros e sabe quando pedir ajuda a um humano já é outra história. É aí que entra o LangGraph, a framework da LangChain para orquestração de agentes com estado, e o MCP (Model Context Protocol), o protocolo que a Anthropic lançou para padronizar a forma como os modelos acedem a ferramentas externas. Em agosto de 2026 esta combinação tornou-se o stack de referência para quem constrói agentes de produção, com atualizações recentes como node caching, deferred nodes e hooks de guardrails a tornar o processo bem mais direto do que há um ano.

Este tutorial mostra, passo a passo, como montar um agente funcional do zero: desde a instalação do LangGraph até à ligação a um servidor MCP, passando por guardrails, avaliações automáticas e aprovação humana antes de publicar em produção. No final tem um projeto completo e testável, mais uma lista de erros comuns e problemas típicos que vai encontrar pelo caminho.

O que é o LangGraph e porque está a dominar a orquestração de agentes

O LangGraph representa o fluxo de um agente como um grafo: nós que executam código ou chamam um modelo, e arestas que decidem para onde o processamento segue a seguir. Ao contrário de uma cadeia linear de prompts, um grafo permite ciclos, ramificações condicionais e pontos de checkpoint, o que é essencial quando o agente precisa de tentar de novo, pedir mais informação ou esperar por uma aprovação antes de continuar.

A própria LangChain posiciona o LangGraph como a peça central para orquestração stateful de agentes, com o LangSmith a tratar da depuração, avaliação e deploy. Segundo um ranking publicado pela Alice Labs em 2026, o LangGraph 1.x continua a ser a escolha por omissão para grafos complexos que exigem controlo explícito sobre o fluxo de execução, ao contrário de frameworks mais opinativas que escondem essa lógica.

As atualizações de agosto de 2026 trouxeram quatro mudanças que valem a pena conhecer antes de começar a codificar. Primeiro, node caching, que evita recomputar um nó quando os inputs não mudaram entre execuções. Segundo, deferred nodes, descritos pela Alice Labs como barreiras nativas de fan-in que esperam por todos os ramos a montante antes de avançar. Terceiro, hooks pré e pós-modelo, pensados para tarefas como corte de contexto, guardrails e redação de dados pessoais. Quarto, uma nova API de streaming centrada em blocos de conteúdo, que substitui o antigo stream token a token.

Na prática, isto traduz-se em três ganhos concretos para quem já usava o LangGraph antes de agosto. Fluxos com múltiplos ciclos de raciocínio ficam mais baratos, porque o node caching evita repetir chamadas ao modelo quando nada mudou nos dados de entrada. Grafos com vários ramos paralelos (por exemplo, três ferramentas a correr ao mesmo tempo) deixam de precisar de código próprio para esperar que todos terminem, graças aos deferred nodes. E a camada de segurança deixa de ser um conjunto de ifs espalhados pelo código, passando a viver em hooks bem definidos antes e depois de cada chamada ao modelo.

Porque combinar LangGraph com MCP (Model Context Protocol)

O MCP resolve um problema concreto: cada framework de agentes costumava ter a sua própria forma de definir ferramentas, o que obrigava a reescrever integrações sempre que se mudava de stack. O MCP padroniza essa camada. Um servidor MCP expõe ferramentas, recursos e prompts através de uma interface comum, e qualquer cliente compatível (LangGraph incluído) consegue descobri-las e usá-las sem código de integração personalizado.

Uma comparação publicada pela freeCodeCamp em 2026 usa como referência o LangGraph 1.1.0 junto do MCP 1.26.0 num sistema multi-agente real, o que dá uma ideia das versões usadas em produção neste momento. Segundo a mesma análise, o MCP funciona como camada de capacidades (as ferramentas em si), enquanto protocolos como o A2A (Agent-to-Agent) tratam da coordenação entre agentes de diferentes frameworks, uma distinção útil para não misturar responsabilidades no desenho do sistema.

O MCP deixou de ser uma opção de nicho. De acordo com o ranking da Alice Labs, todas as dez frameworks de agentes avaliadas já suportam MCP de alguma forma, e sete delas (incluindo LangGraph 1.x, CrewAI 1.14.7, LlamaIndex Workflows 1.0, Pydantic AI 2.0 e o OpenAI Agents SDK) já o suportam nativamente, sem precisar de adaptadores externos. Se a interoperabilidade entre frameworks é um requisito do seu projeto, a mesma fonte aponta o Microsoft Agent Framework 1.0 e o Google ADK 2.0 como as apostas mais fortes por suportarem A2A e MCP em simultâneo.

Pré-requisitos: o que precisa antes de começar

Antes de abrir o terminal, confirme que tem estas peças no lugar. O tutorial assume conhecimentos básicos de Python (funções, dicionários, decoradores) e alguma familiaridade com o conceito de chamadas a APIs de modelos de linguagem. Não precisa de experiência prévia com LangChain, embora ajude.

FerramentaVersão mínima recomendadaPara que serve
Python3.11 ou superiorRuntime do projeto
langgraph1.xMotor de orquestração do agente (grafo, estado, checkpoints)
langchain-mcp-adaptersversão mais recente do PyPILiga clientes MCP ao LangGraph
Protocolo MCP1.26.0 ou compatívelPadrão de comunicação com servidores de ferramentas
Chave de API de um modeloconta ativa (Anthropic, OpenAI ou equivalente)Motor de raciocínio do agente
Editor com suporte a ambientes virtuaisVS Code ou equivalenteDesenvolvimento e depuração

Não precisa necessariamente de uma GPU nem de um servidor dedicado. O agente que vamos construir corre num portátil normal, já que a computação pesada acontece do lado da API do modelo, não localmente.

Um ponto que costuma gerar confusão a quem vem do LangChain clássico: o langchain-mcp-adapters não substitui o langchain, apenas acrescenta a camada de tradução entre o protocolo MCP e as ferramentas que o LangGraph já sabe consumir. Se o seu projeto já usa outras integrações do LangChain (bases de dados vetoriais, retrievers, parsers de documentos), continuam a funcionar normalmente lado a lado com as ferramentas MCP.

Passo 1: Preparar o ambiente e instalar o LangGraph

Comece por criar uma pasta dedicada ao projeto e um ambiente virtual isolado. Isto evita conflitos de versões com outros projetos Python que tenha na máquina.

mkdir agente-langgraph-mcp
cd agente-langgraph-mcp
python3 -m venv .venv
source .venv/bin/activate

pip install --upgrade pip
pip install langgraph langchain langchain-mcp-adapters langchain-anthropic python-dotenv

O pacote langchain-mcp-adapters é o que permite ao LangGraph consumir ferramentas expostas por um servidor MCP como se fossem ferramentas nativas do LangChain. Sem ele, teria de escrever manualmente o código de descoberta e invocação do protocolo.

Passo 2: Configurar as chaves de API

Crie um ficheiro .env na raiz do projeto para guardar as credenciais fora do código-fonte. Nunca comite este ficheiro para um repositório público.

# .env
ANTHROPIC_API_KEY=sk-ant-a-sua-chave-aqui
LANGSMITH_API_KEY=lsv2-opcional-para-observabilidade
LANGSMITH_TRACING=true

Adicione .env ao seu .gitignore antes do primeiro commit. Ativar o LANGSMITH_TRACING é opcional nesta fase, mas vamos usá-lo mais à frente para observabilidade, por isso convém deixar já configurado.

Passo 3: Definir o estado (State) do agente

No LangGraph, o estado é a estrutura de dados partilhada que viaja entre os nós do grafo. Cada nó recebe o estado atual, faz o seu trabalho e devolve as alterações que quer aplicar. Defina o estado com um TypedDict e use reducers para controlar como as atualizações se combinam, especialmente em campos como o histórico de mensagens.

from typing import Annotated, TypedDict
from langgraph.graph.message import add_messages

class EstadoAgente(TypedDict):
    messages: Annotated[list, add_messages]
    tarefa_concluida: bool
    tentativas: int

O reducer add_messages garante que novas mensagens são anexadas ao histórico em vez de o substituírem, o que é o comportamento que quase sempre se quer num agente conversacional. Esquecer este detalhe é uma das causas mais comuns de agentes que “perdem a memória” a meio de uma conversa.

Passo 4: Criar o primeiro nó do grafo

Um nó é uma função Python normal que recebe o estado e devolve um dicionário com as alterações. Vamos criar o nó principal, que chama o modelo e decide se precisa de usar uma ferramenta.

from langchain_anthropic import ChatAnthropic
from langgraph.graph import StateGraph, START, END

modelo = ChatAnthropic(model="claude-opus-5", temperature=0)

def no_raciocinio(estado: EstadoAgente):
    resposta = modelo.invoke(estado["messages"])
    return {"messages": [resposta]}

grafo = StateGraph(EstadoAgente)
grafo.add_node("raciocinio", no_raciocinio)
grafo.add_edge(START, "raciocinio")

Repare que ainda não ligámos “raciocinio” a END. Sem essa aresta, o grafo não sabe quando parar, o que nos leva diretamente ao próximo passo: as arestas condicionais.

Passo 5: Adicionar arestas condicionais

As arestas condicionais são o que dá ao agente capacidade de decisão. Em vez de seguir sempre o mesmo caminho, uma função avalia o estado e escolhe o próximo nó. É aqui que se decide, por exemplo, se o agente deve chamar uma ferramenta, pedir aprovação humana ou terminar.

def decidir_proximo_passo(estado: EstadoAgente):
    ultima_mensagem = estado["messages"][-1]
    if getattr(ultima_mensagem, "tool_calls", None):
        return "ferramentas"
    return END

grafo.add_conditional_edges(
    "raciocinio",
    decidir_proximo_passo,
    {"ferramentas": "ferramentas", END: END},
)

Este padrão, verificar se a resposta do modelo contém uma chamada a ferramenta, é praticamente universal em agentes LangGraph. O nó “ferramentas” ainda não existe, e é precisamente aí que o MCP entra em cena.

Passo 6: Ligar um servidor MCP às ferramentas do agente

Em vez de escrever cada ferramenta à mão, vamos ligar-nos a um servidor MCP que já as expõe. O cliente MultiServerMCPClient trata da descoberta automática: basta indicar o endereço do servidor e o transporte usado.

from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import ToolNode

cliente_mcp = MultiServerMCPClient({
    "pesquisa_web": {
        "command": "npx",
        "args": ["-y", "@meu-servidor/mcp-pesquisa"],
        "transport": "stdio",
    }
})

ferramentas = await cliente_mcp.get_tools()
modelo_com_ferramentas = modelo.bind_tools(ferramentas)

grafo.add_node("ferramentas", ToolNode(ferramentas))
grafo.add_edge("ferramentas", "raciocinio")

O ToolNode do LangGraph já sabe como interpretar chamadas de ferramenta vindas do modelo e devolver o resultado ao estado, por isso não é preciso escrever esse encaixe manualmente. Note que get_tools() é assíncrono, o que significa que o resto do fluxo de arranque do agente também vai precisar de ser executado dentro de uma função async.

O transporte escolhido no dicionário de configuração (stdio no exemplo acima) determina como o cliente fala com o servidor MCP, e a escolha certa muda consoante o cenário de deploy.

Transporte MCPComo funcionaQuando usar
stdioO cliente arranca o servidor como subprocesso local e comunica por entrada e saída padrãoFerramentas locais, scripts, desenvolvimento e testes
SSE (Server-Sent Events)O servidor corre remotamente e envia eventos num canal persistenteServidores partilhados por vários agentes, com latência tolerável
Streamable HTTPPedidos e respostas HTTP normais, com suporte a streaming quando necessárioProdução atrás de um balanceador de carga ou gateway de API

Para o desenvolvimento local que este tutorial segue, stdio é a opção mais simples. Ao mover o agente para produção no passo 13, o mais comum é trocar para streamable HTTP, o que evita ter de gerir subprocessos dentro do próprio servidor da aplicação.

Passo 7: Guardrails, PII e segurança do agente

Dar a um agente acesso a ferramentas reais sem guardrails é um risco desnecessário. Um artigo da Plexibit sobre agentes em produção descreve o stack recomendado como LangGraph para orquestração, MCP para ferramentas, Langfuse para observabilidade e guardrails explícitos em cada fronteira do sistema. Os hooks pré e pós-modelo introduzidos em agosto de 2026 tornam isto muito mais simples de implementar do que antes.

import re

def redigir_pii(estado: EstadoAgente):
    padrao_email = re.compile(r"[\w.+-]+@[\w-]+\.[a-zA-Z]{2,}")
    for msg in estado["messages"]:
        if hasattr(msg, "content") and isinstance(msg.content, str):
            msg.content = padrao_email.sub("[email removido]", msg.content)
    return estado

grafo.add_node("guardrail_pii", redigir_pii)
grafo.add_edge(START, "guardrail_pii")
grafo.add_edge("guardrail_pii", "raciocinio")

Este exemplo cobre só emails, mas o mesmo padrão serve para validar o schema de entrada, detetar tentativas de injeção de prompt antes de chegarem ao modelo, ou bloquear ferramentas com efeitos secundários (como enviar um email ou fazer uma compra) até haver confirmação humana. Trate os guardrails como parte do desenho do grafo, não como um extra a adicionar no fim.

Passo 8: Ativar node caching e deferred nodes

Duas das novidades de agosto de 2026 no LangGraph resolvem problemas de custo e de sincronização que antes exigiam código próprio. O node caching evita voltar a computar um nó quando o input não mudou entre execuções, o que reduz chamadas repetidas ao modelo em fluxos com múltiplas iterações. Os deferred nodes funcionam como uma barreira de fan-in nativa: esperam que todos os ramos anteriores terminem antes de avançar, sem precisar de lógica manual de sincronização.

from langgraph.cache.memory import InMemoryCache
from langgraph.types import CachePolicy

grafo.add_node(
    "raciocinio",
    no_raciocinio,
    cache_policy=CachePolicy(ttl=120),
)

app = grafo.compile(cache=InMemoryCache())

Note o cache=InMemoryCache() na chamada compile(). É fácil escrever a política de cache no nó e esquecer de a ativar globalmente no grafo, e nesse caso o cache simplesmente não faz nada, sem erro visível. Para produção, considere um backend de cache persistente em vez do InMemoryCache, que se perde a cada reinício do processo.

Passo 9: Testar o agente localmente

Com o grafo compilado, é hora de correr o primeiro teste. Use um limite de recursão explícito desde o início: é a rede de segurança que impede um agente com um ciclo mal desenhado de consumir o seu orçamento de API em minutos.

import asyncio

async def testar_agente():
    resultado = await app.ainvoke(
        {"messages": [("user", "Qual foi a última atualização do LangGraph?")],
         "tarefa_concluida": False, "tentativas": 0},
        config={"recursion_limit": 15},
    )
    print(resultado["messages"][-1].content)

asyncio.run(testar_agente())

Exemplo de saída típica no terminal:

$ python testar_agente.py
A atualização mais recente do LangGraph (agosto de 2026) inclui node caching,
deferred nodes para sincronização de ramos, hooks pré e pós-modelo para
guardrails, e uma nova API de streaming baseada em blocos de conteúdo.

Se a chamada devolver um erro em vez de texto, veja a secção de resolução de problemas mais abaixo antes de continuar para o passo seguinte.

Passo 10: Adicionar avaliações automáticas (evals)

Um agente que funciona hoje pode deixar de funcionar depois de mudar um prompt ou atualizar uma dependência. Por isso, tratar as avaliações como testes automatizados, e não como algo manual, é uma prática cada vez mais comum. A Future AGI descreve instrumentação automática de LangGraph com avaliação por rubricas, como conclusão da tarefa e fidelidade da resposta ao contexto fornecido.

from langsmith import Client
from langsmith.evaluation import evaluate

def avaliar_conclusao(execucao, exemplo):
    resposta = execucao.outputs["messages"][-1].content
    esperado = exemplo.outputs["resposta_esperada"]
    return {"score": 1 if esperado.lower() in resposta.lower() else 0}

evaluate(
    lambda entradas: app.invoke(entradas),
    data="conjunto-de-testes-agente",
    evaluators=[avaliar_conclusao],
)

A prática recomendada por vários relatos de produção é manter um conjunto de avaliação por cada pull request que altere o comportamento do agente, exatamente como se faz com testes unitários num backend tradicional. Isto apanha regressões antes de chegarem a produção, em vez de as descobrir através de utilizadores frustrados.

Passo 11: Aprovação humana antes de ações sensíveis

Para ações com consequências reais (enviar dinheiro, apagar dados, publicar conteúdo), o LangGraph permite interromper a execução do grafo e esperar por uma decisão humana antes de continuar. Isto usa os checkpoints nativos da framework, que gravam o estado exato onde o agente parou.

from langgraph.types import interrupt

def no_confirmacao(estado: EstadoAgente):
    decisao = interrupt({
        "pergunta": "Aprovar esta ação com efeitos reais?",
        "acao_proposta": estado["messages"][-1].content,
    })
    if decisao != "aprovado":
        return {"tarefa_concluida": True}
    return {}

Quando o grafo atinge interrupt(), a execução pausa e devolve o controlo à sua aplicação, que pode mostrar a ação proposta a um humano numa interface própria. Só depois de receber a resposta é que o grafo retoma exatamente onde parou, graças ao checkpointer configurado na compilação.

Passo 12: Preparar o agente para produção

Antes de expor o agente a utilizadores reais, confirme quatro coisas: um checkpointer persistente (não o de memória usado nos testes), limites de recursão e de custo por conversa, logging estruturado ligado ao LangSmith ou equivalente, e um plano para o que acontece quando uma ferramenta MCP fica indisponível a meio de uma execução.

from langgraph.checkpoint.postgres import PostgresSaver

with PostgresSaver.from_conn_string(DATABASE_URL) as checkpointer:
    checkpointer.setup()
    app = grafo.compile(checkpointer=checkpointer, cache=InMemoryCache())

Trocar o checkpointer de memória por um baseado em base de dados é o que permite a uma conversa sobreviver a um reinício do servidor, algo que qualquer agente de produção precisa de garantir mais cedo ou mais tarde.

Passo 13: Publicar e monitorizar o agente

Com o checkpointer persistente configurado, o agente pode ser exposto através de um servidor FastAPI ou de um serviço próprio de deploy. A recomendação mais consistente encontrada em relatos de produção é separar claramente o ciclo de vida da sessão MCP (abrir a conexão uma vez por processo, não por pedido) do ciclo de vida de cada conversa individual do agente.

from fastapi import FastAPI
from contextlib import asynccontextmanager

@asynccontextmanager
async def ciclo_de_vida(api: FastAPI):
    api.state.cliente_mcp = MultiServerMCPClient({...})
    yield
    await api.state.cliente_mcp.close()

api = FastAPI(lifespan=ciclo_de_vida)

@api.post("/conversar")
async def conversar(mensagem: str, id_conversa: str):
    resultado = await app.ainvoke(
        {"messages": [("user", mensagem)]},
        config={"configurable": {"thread_id": id_conversa}, "recursion_limit": 15},
    )
    return {"resposta": resultado["messages"][-1].content}

O thread_id em configurable é o que liga cada pedido ao checkpoint correto, permitindo que conversas diferentes corram em paralelo sem misturar estado entre utilizadores.

Casos de uso reais para agentes LangGraph com MCP

O padrão descrito neste tutorial não é teórico: relatos de implementações em produção mostram-no aplicado a setores como banca, saúde e manufatura, segundo a Plexibit, com o mesmo stack de base (LangGraph para orquestração, MCP para ferramentas, guardrails em cada fronteira) adaptado ao domínio de cada empresa. Três padrões de uso aparecem com regularidade nesses relatos.

O primeiro é o assistente interno que responde a perguntas cruzando várias fontes de dados, por exemplo um sistema de tickets, uma base de conhecimento e um CRM, todos expostos como servidores MCP separados. O agente decide, caso a caso, que fontes consultar, em vez de ter esse fluxo escrito à mão. O segundo é o agente de automação de tarefas administrativas, que lê um pedido em linguagem natural, valida-o contra guardrails de negócio e só executa a ação (criar um registo, agendar algo, atualizar um estado) depois de confirmar que os dados fazem sentido. O terceiro é o agente de suporte técnico com escalonamento, que tenta resolver o pedido sozinho e usa o nó de aprovação humana descrito no passo 11 sempre que a confiança na própria resposta é baixa ou a ação implica um risco maior.

Nos três casos, o desenho do grafo é semelhante ao que construímos neste tutorial: um nó de raciocínio, um nó de ferramentas ligado via MCP, guardrails nas fronteiras de entrada e saída, e checkpoints persistentes para que o histórico sobreviva a reinícios do sistema. O que muda entre setores é sobretudo que ferramentas cada servidor MCP expõe e que regras de negócio entram nos guardrails, não a arquitetura de base do agente.

LangGraph vs outras frameworks de agentes em 2026

O LangGraph não é a única opção, e escolher bem depende do que o projeto precisa. Se o requisito principal for controlo explícito sobre grafos complexos com ciclos, o LangGraph continua a ser a referência. Se a prioridade for interoperabilidade entre agentes de fornecedores diferentes através do protocolo A2A, vale a pena avaliar alternativas com esse suporte nativo mais maduro.

FrameworkVersão de referência (2026)Suporte MCPMelhor para
LangGraph1.x (1.1.0 em exemplos recentes)NativoGrafos com estado complexo e controlo explícito de fluxo
CrewAI1.14.7NativoEquipas de agentes com papéis pré-definidos
LlamaIndex Workflows1.0NativoAgentes centrados em recuperação de dados e RAG
Pydantic AI2.0NativoValidação forte de tipos e outputs estruturados
OpenAI Agents SDKversão mais recente do fornecedorNativoIntegração direta com o ecossistema OpenAI
Microsoft Agent Framework1.0Nativo (com A2A)Interoperabilidade entre agentes multi-fornecedor
Google ADK2.0Nativo (com A2A)Ecossistemas Google Cloud e A2A

Vale sublinhar que estas frameworks não são mutuamente exclusivas na prática. É comum ver LangGraph a orquestrar o fluxo principal enquanto delega sub-tarefas a agentes construídos noutra framework, comunicando entre si via A2A e partilhando ferramentas via MCP.

Projeto completo: o agente funcional do início ao fim

Juntando todos os passos anteriores, este é o esqueleto completo do agente, pronto para copiar e adaptar. Guarde-o como agente.py na raiz do projeto criado no passo 1.

import asyncio, re
from typing import Annotated, TypedDict
from dotenv import load_dotenv
from langchain_anthropic import ChatAnthropic
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langgraph.prebuilt import ToolNode
from langgraph.cache.memory import InMemoryCache
from langgraph.types import CachePolicy

load_dotenv()

class EstadoAgente(TypedDict):
    messages: Annotated[list, add_messages]

async def construir_agente():
    modelo = ChatAnthropic(model="claude-opus-5", temperature=0)
    cliente_mcp = MultiServerMCPClient({
        "pesquisa_web": {"command": "npx", "args": ["-y", "@meu-servidor/mcp-pesquisa"], "transport": "stdio"}
    })
    ferramentas = await cliente_mcp.get_tools()
    modelo_com_ferramentas = modelo.bind_tools(ferramentas)

    def no_raciocinio(estado):
        return {"messages": [modelo_com_ferramentas.invoke(estado["messages"])]}

    def decidir(estado):
        ultima = estado["messages"][-1]
        return "ferramentas" if getattr(ultima, "tool_calls", None) else END

    grafo = StateGraph(EstadoAgente)
    grafo.add_node("raciocinio", no_raciocinio, cache_policy=CachePolicy(ttl=120))
    grafo.add_node("ferramentas", ToolNode(ferramentas))
    grafo.add_edge(START, "raciocinio")
    grafo.add_conditional_edges("raciocinio", decidir, {"ferramentas": "ferramentas", END: END})
    grafo.add_edge("ferramentas", "raciocinio")

    return grafo.compile(cache=InMemoryCache())

async def main():
    app = await construir_agente()
    resultado = await app.ainvoke(
        {"messages": [("user", "Resume as novidades do LangGraph de agosto de 2026")]},
        config={"recursion_limit": 15},
    )
    print(resultado["messages"][-1].content)

if __name__ == "__main__":
    asyncio.run(main())

Este esqueleto cobre raciocínio, chamada de ferramentas via MCP e cache de nós. Para chegar a produção, acrescente os blocos dos passos 7, 11 e 12 (guardrails, aprovação humana e checkpointer persistente) conforme a sensibilidade das ações que o seu agente vai executar.

A maior parte dos problemas que se encontram ao construir um primeiro agente com LangGraph não são bugs no framework, são decisões de desenho tomadas cedo demais e sem pensar no que acontece quando algo corre mal. A lista seguinte junta os erros que mais aparecem em relatos de quem já passou por este processo, para que não precise de os descobrir da forma difícil.

Erros comuns a evitar

  • Esquecer o recursion_limit: sem ele, um ciclo mal desenhado entre “raciocinio” e “ferramentas” pode correr indefinidamente e esgotar o orçamento de API antes de alguém dar por isso.
  • Não usar reducers no estado: campos de lista sem um reducer como add_messages acabam por ser substituídos em vez de acumulados, e o agente “esquece” o histórico.
  • Ativar cache_policy no nó mas esquecer cache= na compilação: o cache fica definido mas nunca é usado, sem qualquer erro visível a avisar.
  • Abrir uma sessão MCP por pedido HTTP: o custo de handshake do MCP é feito para ser pago uma vez por processo, não a cada mensagem de um utilizador.
  • Ignorar exceções dentro dos nós: um nó que rebenta silenciosamente pode deixar o checkpoint num estado inconsistente, difícil de depurar mais tarde.
  • Dar acesso a ferramentas com efeitos secundários sem guardrail: uma ferramenta que envia emails ou faz pagamentos precisa de validação antes de ser chamada, não depois.
  • Usar o checkpointer de memória em produção: funciona bem em testes locais, mas qualquer reinício do processo apaga todas as conversas em curso.

Resolução de problemas: situações frequentes

GraphRecursionError ao correr o agente. O grafo atingiu o recursion_limit configurado. Normalmente indica um ciclo entre nós que nunca satisfaz a condição de paragem. Reveja a função decidir_proximo_passo e confirme que existe um caminho real até END.

Erro de autenticação da API do modelo. Confirme que o .env está a ser carregado com load_dotenv() antes de instanciar o ChatAnthropic, e que a variável tem o nome exato esperado pelo SDK (ANTHROPIC_API_KEY).

Ligação recusada ao servidor MCP. Se o transporte for stdio, confirme que o comando indicado (por exemplo npx) está instalado e acessível no PATH do processo que corre o agente, não só no seu terminal interativo.

As ferramentas MCP não aparecem na lista. get_tools() é assíncrono. Se for chamado fora de um contexto async ou antes do servidor terminar o handshake inicial, a lista devolvida vem vazia sem erro explícito.

O nó não recebe o estado atualizado do nó anterior. Verifique se a chave devolvida pelo nó corresponde exatamente ao nome do campo no TypedDict do estado. Um erro de nome silencioso faz o LangGraph ignorar a atualização.

Streaming não devolve nada, ou devolve tokens a mais. Confirme se está a usar a API de streaming baseada em blocos de conteúdo introduzida em agosto de 2026, e não a API de stream token a token, que foi marcada como legacy.

O cache não invalida depois de alterar o código do nó. O InMemoryCache guarda resultados por processo. Reinicie o processo depois de alterar a lógica de um nó com cache_policy ativo, ou use uma chave de cache que inclua uma versão do código.

interrupt() nunca retoma a execução. A retoma de um interrupt exige que o mesmo thread_id seja usado na chamada seguinte a ainvoke(), com o valor da decisão passado através do parâmetro Command. Confirme que a aplicação que trata a aprovação humana guarda e reenvia esse identificador.

Custos de API mais altos do que o esperado. Sem node caching, cada iteração de um ciclo raciocinio-ferramentas repete a chamada completa ao modelo mesmo quando o input não mudou. Ative cache_policy nos nós que fazem chamadas repetidas com os mesmos argumentos.

Dicas avançadas para produção

Depois do agente funcionar de ponta a ponta, há um conjunto de práticas que separam um protótipo de um sistema fiável. Ligue o LangSmith ou uma ferramenta equivalente como o Langfuse desde o primeiro dia, não só quando algo correr mal, porque reconstruir o histórico de execuções depois de um incidente é muito mais difícil do que já o ter registado.

Trate os conjuntos de avaliação como testes de regressão: corra-os em cada pull request que altere um prompt, um nó ou uma dependência de ferramenta. Para agentes que envolvem múltiplos fornecedores de modelos, considere isolar a camada de coordenação (A2A) da camada de ferramentas (MCP), em vez de misturar as duas responsabilidades no mesmo nó. E se o agente vai crescer para múltiplos sub-agentes especializados, avalie o padrão Deep Agents da própria LangChain, pensado especificamente para workflows longos que combinam planeamento, execução e revisão.

Por fim, aplique limites de taxa e circuit breakers às ferramentas externas chamadas via MCP. Um servidor de terceiros em baixo não deve travar o agente inteiro, deve degradar graciosamente para uma resposta alternativa ou pedir confirmação humana sobre como proceder.

Outra prática que compensa cedo é versionar o próprio grafo, não só o código à volta dele. Quando um nó muda de comportamento, ou uma aresta condicional passa a decidir de forma diferente, isso é uma alteração de contrato tão relevante como mudar o schema de uma base de dados. Guardar essas versões junto com os conjuntos de avaliação do passo 10 permite comparar o desempenho do agente antes e depois de cada mudança, em vez de confiar apenas na perceção de que “parece estar melhor”. Equipas que já correm agentes LangGraph em produção há mais tempo tendem a tratar o grafo como qualquer outro artefacto de infraestrutura: com revisão de código, testes automáticos e um histórico de alterações consultável.

Vale ainda considerar o custo de latência introduzido por cada camada adicional. Um guardrail de PII, uma chamada MCP e um passo de aprovação humana somam-se ao tempo total de resposta. Para agentes que precisam de responder em tempo real, meça o tempo gasto em cada nó do grafo (o LangSmith mostra isto automaticamente) e decida deliberadamente onde vale a pena trocar segurança por velocidade, em vez de deixar essa decisão acontecer por acidente.

Perguntas frequentes

O que é exatamente o LangGraph?
É uma framework Python (e JavaScript) da LangChain para construir agentes de IA como grafos com estado, em vez de cadeias lineares de prompts. Permite ciclos, ramificações condicionais e checkpoints, o que o torna adequado para agentes que precisam de planear, corrigir-se e esperar por aprovação humana.

O que é o MCP e em que difere de uma API normal?
O Model Context Protocol é um padrão aberto, criado pela Anthropic, para expor ferramentas, recursos e prompts a modelos de forma uniforme. A diferença face a uma API tradicional é a descoberta automática: um cliente MCP consegue listar e usar as ferramentas de um servidor sem código de integração escrito à mão para cada uma.

Preciso de saber Python avançado para seguir este tutorial?
Não. Conhecimentos básicos de funções, dicionários e programação assíncrona (async/await) chegam para acompanhar todos os passos. A parte mais nova para a maioria dos programadores é o conceito de grafo com estado, não a sintaxe em si.

O LangGraph é gratuito?
A biblioteca em si é open source e gratuita para instalar e correr. Os custos vêm das chamadas à API do modelo de linguagem escolhido e, opcionalmente, de serviços de observabilidade como o LangSmith, que tem um nível gratuito limitado e planos pagos para volumes maiores.

O LangGraph funciona só com modelos da Anthropic?
Não. Este tutorial usa o ChatAnthropic como exemplo, mas o LangGraph é agnóstico ao fornecedor de modelo. Basta trocar a instanciação do modelo por um wrapper equivalente de outro fornecedor suportado pelo LangChain.

Qual a diferença entre LangGraph e LangChain?
O LangChain é a biblioteca mais ampla, com integrações, prompts e utilitários. O LangGraph é a camada de orquestração construída sobre esse ecossistema, focada especificamente em fluxos com estado, ciclos e checkpoints, algo que o LangChain sozinho não modela bem.

É seguro dar a um agente acesso a ferramentas via MCP?
Só se houver guardrails explícitos antes de qualquer ferramenta com efeitos secundários reais. Práticas como validação de schema, deteção de injeção de prompt, redação de dados pessoais e aprovação humana para ações sensíveis são consideradas padrão em relatos de agentes de produção, não extras opcionais.

Quanto tempo demora a ter o primeiro agente funcional?
Seguindo este tutorial do zero, contar com cerca de 60 minutos até ao agente de teste do passo 9 funcionar. Adicionar guardrails, avaliações e preparação para produção (passos 7, 10, 11 e 12) costuma levar mais uma ou duas sessões de trabalho, dependendo da complexidade das ferramentas envolvidas.

Posso usar LangGraph em JavaScript ou só em Python?
O LangGraph tem uma versão para JavaScript e TypeScript mantida pela mesma equipa, com a mesma API conceptual de nós, arestas e estado. Este tutorial usa Python porque é a linguagem mais comum neste tipo de projeto, mas os conceitos de grafo, checkpoint e MCP transferem-se diretamente para a versão JavaScript.

O que acontece se um servidor MCP externo ficar em baixo a meio de uma conversa?
Sem tratamento explícito, o nó de ferramentas devolve um erro que sobe até ao utilizador. A prática recomendada, referida na secção de dicas avançadas, é aplicar um circuit breaker à volta da chamada MCP, de forma a que o agente responda com uma alternativa (por exemplo, informar que a ferramenta está indisponível) em vez de falhar de forma abrupta.