LangGraph
Uma tarefa que precisa consultar dados, aguardar uma pessoa e continuar depois de um reinício se beneficia de uma representação explícita das etapas. LangGraph modela o trabalho como um grafo de nós, arestas e estado. O exemplo desta aula será uma proposta de compra: consultar preço, decidir se exige revisão e, após a decisão, registrar a compra simulada. O interesse não está em desenhar caixas; está em tornar visíveis os caminhos possíveis e suas condições.
O grafo não precisa usar modelo em todos os nós. Consulta, validação e autorização podem ser determinísticas, enquanto a preparação de uma proposta pode usar um modelo quando houver interpretação necessária. Vamos estudar branching, persistência, retries, interrupções humanas e execução durável. O exemplo local expõe a semântica de retomada sem importar LangGraph. A integração do laboratório deverá usar a documentação e a versão instalada para confirmar como os mecanismos se comportam no runtime real.
JavaScriptLangGraphAgentesAo terminar esta aula
- Um grafo torna dependências e caminhos explícitos.
- Retomada pode reexecutar código de nós e requer efeitos seguros.
- Checkpoint durável e idempotência externa resolvem problemas diferentes.
Antes de continuar: Laboratório: Google ADK
Nós calculam mudanças; arestas escolhem o caminho
FundamentosUm nó recebe o estado necessário e produz uma atualização. Uma aresta define qual etapa vem depois, e uma aresta condicional escolhe o destino com base no estado. No caso da compra, consultar produz preco; decidir verifica o limiar definido pela aplicação; revisar espera uma decisão; executar registra o resultado. Essa divisão evita esconder todo o fluxo em uma única função que conversa com o modelo. Também facilita testar uma condição específica sem depender de uma resposta textual diferente a cada execução.
Defina o estado por campos com significado operacional: pedido, preço, revisão da proposta, decisão, chave do efeito e resultado. A regra de combinação das atualizações é importante quando vários nós escrevem. Substituir uma lista inteira não equivale a acrescentar eventos; somar valores não equivale a escolher o mais recente. Os mecanismos de atualização e reducers do grafo precisam corresponder à regra de negócio. Caso contrário, um caminho paralelo pode perder evidências ou somar duas vezes um valor em uma repetição. Estado explícito não é automaticamente estado correto.
Branching deve preservar as condições de segurança
SegurançaO preço determina se a proposta exige revisão, mas o limiar é uma decisão da política, não uma propriedade universal de agentes. Uma proposta abaixo do limiar ainda precisa ser válida e autorizada. A aresta que conduz diretamente à execução não deve pular controles de identidade ou propriedade. Para avaliar branching, teste valores nos dois lados do limite e exatamente no limite. Um operador maior em vez de maior ou igual muda a política naquele ponto e pode criar um caminho não revisado.
Interrupções humanas suspendem a execução para receber um valor externo. A retomada depende de um checkpoint e da identidade da execução. O código do nó que interrompe pode ser reexecutado ao continuar, por isso um efeito colocado antes da interrupção pode acontecer novamente. A documentação de interrupts enfatiza cuidados com a ordem e com efeitos. Coloque operações irreversíveis depois da validação da decisão ou use mecanismos idempotentes. Uma pausa não significa que a função inteira ficará congelada na memória indefinidamente.
Checkpoint permite continuar, mas o efeito precisa de identidade
FundamentosA persistência do grafo salva estados recuperáveis, ligados a uma execução ou thread conforme a configuração. Isso permite continuar um trabalho sem começar do objetivo original. A durabilidade depende do checkpointer utilizado e de como os serviços externos são integrados. Um armazenamento em memória é insuficiente para reinício de processo. Mesmo com banco, um checkpoint anterior ao pagamento pode ser retomado depois de o pagamento ter ocorrido. A chave estável do efeito é a ligação necessária para consultar o resultado anterior e evitar uma duplicação cega.
No simulador, preparar calcula a proposta e marca aguardando; retomar valida a decisão e usa o mapa de efeitos para reconhecer repetição. O resultado da segunda retomada deve apontar para o mesmo registro. Isso mostra uma defesa local, mas não implementa transação distribuída. Se dois workers retomarem ao mesmo tempo, o mapa não oferece garantia entre processos. Na versão real, combine checkpoint durável com unicidade ou idempotência do executor externo e registre resultados desconhecidos para reconciliação.
const ledger=new Map();
function preparar(id) { return {id,revisao:1,preco:300,status:'aguardando'}; }
function retomar(p,decisao) {
if (decisao.revisao!==p.revisao) throw new Error('revisao incorreta');
if (!decisao.aprovado) return {...p,status:'recusado'};
const chave=p.id+':'+p.revisao;
if (!ledger.has(chave)) ledger.set(chave,{recibo:chave,status:'compra_simulada'});
return {...p,status:'concluido',resultado:ledger.get(chave)};
}
const p=preparar('C7'); console.log(p);
console.log(retomar(p,{revisao:1,aprovado:true}));
console.log(retomar(p,{revisao:1,aprovado:true}));
console.log(retomar(preparar('C8'),{revisao:1,aprovado:false}));
console.log('efeitos',ledger.size);Retries corrigem indisponibilidade, não qualquer problema
FundamentosRetry é adequado a falhas transitórias quando a operação pode ser repetida com segurança. Argumento inválido, acesso negado ou proposta recusada não melhoram por insistência. Classifique erros e defina tentativas, intervalo e orçamento total. Um timeout de leitura pode justificar uma nova consulta; um timeout depois de emitir compra exige consultar o efeito antes de repetir. A documentação de tolerância a falhas descreve mecanismos do runtime, mas a aplicação ainda precisa declarar que exceções são recuperáveis e qual semântica cada operação possui.
Avalie o grafo pelo caminho e pelo estado final. Casos necessários incluem aprovação, rejeição, revisão antiga, retomada repetida e queda entre efeito e checkpoint. Registre quais nós foram reexecutados e quantos efeitos ocorreram. Um fluxo que terminou com sucesso após duas compras não está correto. A abordagem funcional do LangGraph oferece outra forma de expressar trabalho durável; a escolha entre essa forma e a API de grafo depende da legibilidade do fluxo e das operações, não de uma superioridade automática de uma sintaxe.
Exercício aplicado
Uma compra C7 espera revisão e poderá ser retomada duas vezes. Crie um grafo com decisão condicional, pausa humana e execução idempotente simulada, além de um caso de falha transitória.
- Execute o simulador com aprovação, recusa e revisão antiga.
- Implemente os quatro nós no LangGraph com versão e checkpointer registrados.
- Retome a mesma execução e conte os efeitos.
- Injete timeout depois do recibo e mostre a reconciliação pela chave.
Abrir resolução comentada
A primeira etapa retorna uma proposta aguardando revisão. A retomada aprovada gera uma chave C7:1 e grava um único efeito. Quando a mesma proposta é retomada novamente, o resultado existente é recuperado. Ao rejeitar, o fluxo termina recusado antes de qualquer efeito. A revisão da decisão também precisa coincidir com a proposta, para impedir aprovação de um estado antigo.
A implementação LangGraph deve provar recuperação com um checkpointer durável e identificar os nós repetidos na retomada. O mapa local conserva somente a garantia dentro do processo. O teste de queda no executor real é o que revela a janela entre efeito e checkpoint; desenhar uma aresta não elimina essa janela.
const ledger=new Map();
function preparar(id) { return {id,revisao:1,preco:300,status:'aguardando'}; }
function retomar(p,decisao) {
if (decisao.revisao!==p.revisao) throw new Error('revisao incorreta');
if (!decisao.aprovado) return {...p,status:'recusado'};
const chave=p.id+':'+p.revisao;
if (!ledger.has(chave)) ledger.set(chave,{recibo:chave,status:'compra_simulada'});
return {...p,status:'concluido',resultado:ledger.get(chave)};
}
const p=preparar('C7'); console.log(p);
console.log(retomar(p,{revisao:1,aprovado:true}));
console.log(retomar(p,{revisao:1,aprovado:true}));
console.log(retomar(preparar('C8'),{revisao:1,aprovado:false}));
console.log('efeitos',ledger.size);Como conferir seu resultado
- Recusa não emite compra.
- Retomada repetida devolve o mesmo recibo.
- A evidência distingue persistência do grafo e do registro de efeitos.
Aplique em um problema novo
Primeiro resolva sem consultar a resposta. Explique suas decisões e guarde a evidência. A conclusão de leitura é independente desta autoavaliação.
Confira seus pré-requisitos
- Modelar nós/arestas/estado.
- Separar checkpoint e efeito idempotente.
Compras>=500 exigem revisão. Compare 499/500/501; recibo existe mas checkpoint ficou anterior. Explique retomada.
Conferir raciocínio e critérios de domínio
499 segue caminho autorizado automático;500/501 exigem revisão, conforme política inclusiva.
Checkpoint recupera posição, não prova ausência de recibo.
Executor consulta intenção estável e evita segunda compra.
Evidências para autoavaliação ou revisão por pares
- Branching: 499 segue caminho autorizado automático;500/501 exigem revisão, conforme política inclusiva.
- Durabilidade: Checkpoint recupera posição, não prova ausência de recibo.
- Reconciliação: Executor consulta intenção estável e evita segunda compra.
Um erro frequente
Checkpoint substitui idempotência.
Checkpoint recupera posição; intenção idempotente identifica o efeito.
Teste sua compreensão
Responda com suas palavras antes de abrir o comentário. Saber explicar uma decisão é parte do domínio.
1. Por que efeitos antes de interrupt são perigosos?
O nó pode ser reexecutado na retomada.
A pausa não garante congelamento permanente da função em memória.
2. Acesso negado deve receber retry?
Normalmente não, pois é uma condição permanente para aquela identidade.
Tentativas adicionais não concedem a permissão ausente.
3. Checkpointer substitui chave de idempotência?
Não. Um guarda posição de execução; a outra identifica o efeito.
A queda pode separar o efeito remoto do checkpoint local.
Seu progresso fica salvo neste navegador. Concluir a leitura não substitui demonstrar o domínio nos exercícios.
Referências e aprofundamento
Documentação oficial e trabalhos originais. As referências registram o escopo e as limitações para você conferir o que sustentam.
- Graph API overview
LangChain • consulta: 2026-10-06
APIsStateGraph, nós, arestas, condicionais e reducers para combinar atualizações.
Limites: Reducers resolvem combinação de dados; conflitos semânticos de agentes precisam de regra editorial/negocial explícita.
- Thinking in LangGraph
LangChain • consulta: 2026-10-06
LangGraphAgentesDecompor passos, representar estado, roteamento, recuperação e escolhas entre loops e grafos.
Limites: Tutorial de desenho; ajustar o exemplo ao caso de uso e à versão instalada.
- Persistence
LangChain • consulta: 2026-10-06
FundamentosCheckpointer de estado por thread versus store de memória entre threads.
Limites: InMemorySaver é demonstrativo; usar backend durável para sobreviver a reinícios.
- Checkpointers
LangChain • consulta: 2026-10-06
FundamentosCheckpoints, threads, retomada e tolerância a falhas.
Limites: Checkpoint de estado não torna ações externas exatamente uma vez; planejar idempotência.
- Fault tolerance
LangChain • consulta: 2026-10-06
FundamentosRetries de nós, backoff, timeouts e tratamento de erros.
Limites: Time-out e retry não desfazem efeitos já executados; APIs avançadas exigem versão mínima.
- Interrupts
LangChain • consulta: 2026-10-06
FundamentosPausa human-in-the-loop e retomada com estado persistido.
Limites: Código anterior a interrupt pode reexecutar; efeitos devem ser idempotentes e decisão humana vinculada à ação.
- Use the functional API
LangChain • consulta: 2026-10-06
APIsTasks, cache de resultados, retomada e operações externas isoladas.
Limites: Retomada exige sequência estável de tasks/interrupções; usar idempotência para efeitos.