---
title: "LangGraph: Criando Agentes de IA com Python | python.dev.br"
url: "https://python.dev.br/blog/langgraph-agentes-ia-python/"
markdown_url: "https://python.dev.br/blog/langgraph-agentes-ia-python.MD"
description: "Aprenda a usar LangGraph para criar agentes de IA com grafos, memória e controle humano em Python. Tutorial prático com exemplos reais."
date: "2026-04-26"
author: "Equipe python.dev.br"
---

# LangGraph: Criando Agentes de IA com Python | python.dev.br

Aprenda a usar LangGraph para criar agentes de IA com grafos, memória e controle humano em Python. Tutorial prático com exemplos reais.


Se você acompanha o ecossistema Python em 2026, já deve ter notado que **agentes de IA** deixaram de ser curiosidade de laboratório e viraram ferramenta de produção. Frameworks como CrewAI e OpenAI Agents SDK trouxeram o conceito para mais perto dos desenvolvedores, mas quando o assunto é **controle fino, durabilidade e fluxos complexos**, o **LangGraph** se destaca como a principal escolha.

Neste artigo, vamos entender o que é o LangGraph, por que ele se diferencia de outras abordagens, e construir um agente funcional passo a passo em Python. Se você já trabalha com [LLMs e APIs de IA](/blog/python-e-llms-apis-inteligencia-artificial/) ou conhece o [OpenAI Agents SDK](/blog/openai-agents-sdk-python-multi-agentes/), vai perceber como o LangGraph complementa esse ecossistema.

## O que é o LangGraph?

O LangGraph é um framework open-source (licença MIT) criado pela equipe do LangChain para orquestrar **agentes de IA como grafos dirigidos**. Em vez de encadear chamadas de LLM de forma linear, você define **nós** (funções de processamento) e **arestas** (transições entre nós), criando fluxos que podem ter ciclos, ramificações condicionais e estado persistente.

A versão 1.1.6, lançada em abril de 2026, consolidou o LangGraph como padrão para aplicações que precisam de:

- **Execução durável** — o agente persiste através de falhas e retoma de onde parou
- **Human-in-the-loop** — pontos de aprovação humana antes de ações críticas
- **Memória** — estado de curto e longo prazo entre interações
- **Streaming** — respostas parciais em tempo real para o usuário

## Por que grafos em vez de chains?

Se você já usou LangChain, sabe que uma chain é uma sequência linear: prompt → LLM → parser → saída. Isso funciona para tarefas simples, mas agentes reais precisam de **decisões dinâmicas**.

Imagine um assistente que:

1. Recebe uma pergunta do usuário
2. Decide se precisa buscar dados na web ou no banco
3. Executa a busca escolhida
4. Analisa o resultado e decide se precisa de mais informação
5. Gera a resposta final

Esse fluxo tem **ramificações** (passo 2) e **ciclos** (passo 4 pode voltar ao passo 2). Um grafo modela isso naturalmente. Uma chain linear, não.

## Instalação e setup inicial

Primeiro, instale o LangGraph e as dependências. Se você usa o [uv](/blog/uv-gerenciador-pacotes-python/) como gerenciador de pacotes, o processo é direto:

```python
# Com uv (recomendado)
# uv add langgraph langchain-openai

# Com pip tradicional
# pip install langgraph langchain-openai
```

Você também precisa de uma chave de API de um provedor de LLM. Neste tutorial, usaremos a OpenAI, mas o LangGraph funciona com qualquer provedor compatível com LangChain.

```python
import os
os.environ["OPENAI_API_KEY"] = "sua-chave-aqui"
```

## Conceitos fundamentais

Antes de construir o agente, vamos entender os três pilares do LangGraph:

### 1. State (Estado)

O estado é um [dataclass](/blog/dataclasses-python-guia-completo/) ou `TypedDict` que carrega todas as informações do agente entre os nós:

```python
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages

class EstadoAgente(TypedDict):
    mensagens: Annotated[list, add_messages]
    tentativas: int
    resultado_final: str
```

O `add_messages` é um **reducer** — em vez de substituir a lista de mensagens, ele acumula novas mensagens ao estado existente.

### 2. Nodes (Nós)

Cada nó é uma função Python que recebe o estado atual e retorna as atualizações:

```python
from langchain_openai import ChatOpenAI

modelo = ChatOpenAI(model="gpt-4o-mini", temperature=0)

def chatbot(estado: EstadoAgente) -> dict:
    resposta = modelo.invoke(estado["mensagens"])
    return {"mensagens": [resposta]}
```

### 3. Edges (Arestas)

As arestas definem o fluxo entre nós. Podem ser fixas ou **condicionais**:

```python
def decidir_proximo(estado: EstadoAgente) -> str:
    ultima = estado["mensagens"][-1]
    if ultima.tool_calls:
        return "ferramentas"
    return "fim"
```

## Construindo um agente completo

Vamos criar um agente que pesquisa informações e responde perguntas usando ferramentas. Este exemplo mostra o padrão **ReAct** (Reasoning + Acting) implementado como grafo:

```python
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode
from langchain_core.tools import tool

# Definindo uma ferramenta simples
@tool
def buscar_clima(cidade: str) -> str:
    """Busca a previsão do tempo para uma cidade."""
    # Em produção, aqui teria uma chamada real a uma API
    climas = {
        "São Paulo": "Parcialmente nublado, 22°C",
        "Rio de Janeiro": "Ensolarado, 31°C",
        "Curitiba": "Chuva leve, 16°C",
    }
    return climas.get(cidade, f"Dados não disponíveis para {cidade}")

@tool
def buscar_populacao(cidade: str) -> str:
    """Busca a população estimada de uma cidade brasileira."""
    populacoes = {
        "São Paulo": "12,4 milhões",
        "Rio de Janeiro": "6,8 milhões",
        "Curitiba": "1,9 milhão",
    }
    return populacoes.get(cidade, f"Dados não disponíveis para {cidade}")

# Configurando o modelo com as ferramentas
ferramentas = [buscar_clima, buscar_populacao]
modelo_com_tools = modelo.bind_tools(ferramentas)

# Nó do chatbot
def chatbot(estado: EstadoAgente) -> dict:
    resposta = modelo_com_tools.invoke(estado["mensagens"])
    return {"mensagens": [resposta]}

# Função de roteamento condicional
def roteador(estado: EstadoAgente) -> str:
    ultima_mensagem = estado["mensagens"][-1]
    if hasattr(ultima_mensagem, "tool_calls") and ultima_mensagem.tool_calls:
        return "ferramentas"
    return END

# Montando o grafo
grafo = StateGraph(EstadoAgente)
grafo.add_node("chatbot", chatbot)
grafo.add_node("ferramentas", ToolNode(ferramentas))

grafo.add_edge(START, "chatbot")
grafo.add_conditional_edges("chatbot", roteador)
grafo.add_edge("ferramentas", "chatbot")

agente = grafo.compile()
```

Para executar o agente:

```python
from langchain_core.messages import HumanMessage

resultado = agente.invoke({
    "mensagens": [HumanMessage(content="Qual o clima em São Paulo e a população de Curitiba?")],
    "tentativas": 0,
    "resultado_final": "",
})

for msg in resultado["mensagens"]:
    print(f"{msg.type}: {msg.content}")
```

O agente automaticamente decide que precisa chamar **duas ferramentas**, executa ambas, e depois gera uma resposta consolidada. Esse ciclo de raciocínio → ação → observação é o coração do padrão ReAct.

## Adicionando memória persistente

Uma das maiores vantagens do LangGraph é a memória entre conversas. Com um **checkpointer**, o estado do agente sobrevive entre sessões:

```python
from langgraph.checkpoint.memory import MemorySaver

memoria = MemorySaver()
agente_com_memoria = grafo.compile(checkpointer=memoria)

# Primeira interação
config = {"configurable": {"thread_id": "conversa-1"}}
resultado1 = agente_com_memoria.invoke(
    {"mensagens": [HumanMessage(content="Meu nome é Diego")], "tentativas": 0, "resultado_final": ""},
    config=config,
)

# Segunda interação — o agente lembra do nome
resultado2 = agente_com_memoria.invoke(
    {"mensagens": [HumanMessage(content="Qual é meu nome?")], "tentativas": 0, "resultado_final": ""},
    config=config,
)
# O agente responde: "Seu nome é Diego"
```

Para produção, o LangGraph oferece checkpointers para PostgreSQL e SQLite, garantindo durabilidade real dos dados.

## Human-in-the-loop: aprovação humana

Em cenários críticos, você quer que um humano aprove antes do agente executar uma ação. O LangGraph suporta isso nativamente com **interrupt**:

```python
from langgraph.types import interrupt

@tool
def executar_pagamento(valor: float, destino: str) -> str:
    """Executa um pagamento financeiro."""
    aprovacao = interrupt({
        "acao": "pagamento",
        "valor": valor,
        "destino": destino,
        "pergunta": f"Aprovar pagamento de R${valor:.2f} para {destino}?"
    })
    if aprovacao == "sim":
        return f"Pagamento de R${valor:.2f} para {destino} realizado."
    return "Pagamento cancelado pelo usuário."
```

Quando o agente chega nesse ponto, a execução **pausa** e espera a aprovação humana. Isso é essencial para aplicações financeiras e outras situações críticas.

## Streaming de respostas

Para interfaces de chat, você quer mostrar a resposta conforme ela é gerada:

```python
async for evento in agente_com_memoria.astream_events(
    {"mensagens": [HumanMessage(content="Explique Python em 3 parágrafos")], "tentativas": 0, "resultado_final": ""},
    config=config,
    version="v2",
):
    if evento["event"] == "on_chat_model_stream":
        token = evento["data"]["chunk"].content
        if token:
            print(token, end="", flush=True)
```

## Quando usar LangGraph vs alternativas

| Cenário | LangGraph | OpenAI Agents SDK | CrewAI |
|---------|-----------|-------------------|--------|
| Fluxos complexos com ciclos | Excelente | Limitado | Bom |
| Human-in-the-loop | Nativo | Manual | Básico |
| Memória persistente | Nativo | Manual | Básico |
| Facilidade de começar | Moderada | Alta | Alta |
| Controle de estado | Total | Parcial | Parcial |
| Vendor lock-in | Nenhum (MIT) | OpenAI | Nenhum |

Se você precisa de **controle total** sobre o fluxo de execução e durabilidade em produção, o LangGraph é a escolha certa. Para protótipos rápidos ou agentes simples, o [OpenAI Agents SDK](/blog/openai-agents-sdk-python-multi-agentes/) pode ser mais direto.

## Boas práticas para produção

1. **Defina estados tipados** — use [type hints](/glossario/type-hints/) para evitar erros em tempo de execução
2. **Limite ciclos** — configure `recursion_limit` para evitar loops infinitos
3. **Use checkpointers** — nunca rode agentes em produção sem persistência de estado
4. **Monitore com tracing** — o LangSmith integra nativamente para observabilidade
5. **Teste cada nó isoladamente** — como são funções puras, cada nó pode ser testado com [pytest](/blog/testes-unitarios-python/)

## Conclusão

O LangGraph amadureceu em 2026 como o framework padrão para agentes de IA em Python que precisam ir além de chamadas lineares a LLMs. A abstração de grafos oferece flexibilidade para modelar qualquer fluxo, enquanto recursos como memória, streaming e human-in-the-loop resolvem problemas reais de produção.

Se você está começando com Python e IA, vale começar pelo nosso guia de [Python e LLMs](/blog/python-e-llms-apis-inteligencia-artificial/) antes de mergulhar no LangGraph. Já para quem quer explorar performance e tipagem, confira como o [ty type checker](/blog/ty-type-checker-python-rust/) pode ajudar em projetos grandes.

Para quem também trabalha com outras linguagens, vale conferir como Go lida com concorrência em <a href="https://golang.com.br" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">golang.com.br</a> — a comparação entre agentes Python e goroutines Go é fascinante. Quem usa Rust para performance pode explorar <a href="https://rustlang.com.br" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">rustlang.com.br</a> e entender como o Rust complementa pipelines de IA.
