Phase 16 - Lesson 22
Escalonamento em Produção — Filas, Checkpoints, Durabilidade
Escalar sistemas multiagentes para milhares de execuções simultâneas exige execução durável. O runtime do LangGraph grava um checkpoint após cada super-step chaveado por
thread_id(Postgres por padrão); falhas de workers liberam uma concessão (lease) e outro worker retoma a execução. Agentes podem dormir indefinidamente aguardando entrada humana. O MegaAgent (arXiv:2408.09955) executou uma fila de produtor-consumidor por agente com três estados (Idle / Processing / Response) e coordenação em duas camadas (chat intragrupo + chat administrativo intergrupo). Fiber/async supera thread-per-job para streaming de LLM: threads ficam ociosas 99% do tempo esperando por tokens, enquanto fibers cedem o controle cooperativamente no I/O. Contraponto: "Scaling Agentic Software" de Ashpreet Bedi defende FastAPI + Postgres + nada mais até que a carga prove o contrário — arquiteturas simples vão mais longe do que o esperado. Esta lição constrói um log de checkpoints durável, uma fila de trabalho por agente com transições de estado, uma demonstração de async vs thread, e consolida a regra pragmática de "começar simples".
Tipo: Aprenda + Construa
Linguagens: Python (stdlib, asyncio, sqlite3)
Pré-requisitos: Fase 16 · 09 (Redes de Enxame Paralelas), Fase 16 · 13 (Memória Compartilhada)
Tempo: ~75 minutos
Problema
Um protótipo de sistema multiagente funciona em um laptop com três agentes em um loop de eventos em memória. Você muda para a produção:
- Os agentes às vezes rodam por horas (pesquisas longas, esperas por interação humana).
- Processos de workers falham. Reiniciar perde o estado.
- A carga de pico é 10x a média; você precisa de escalabilidade horizontal.
- Os usuários pagam por execução de agente; você precisa de semântica de execução única (exactly-once) para cobrança.
O loop de eventos em memória não resolve nada disso. Você precisa de uma camada de execução durável por baixo. As opções canônicas de 2026 são:
- Um motor de fluxo de trabalho com checkpoints (Temporal, runtime do LangGraph).
- Uma fila de mensagens com um armazenamento de estado (Postgres + SQS/RabbitMQ).
- Frameworks baseados no modelo de atores (fila de produtor-consumidor por agente do MegaAgent).
- FastAPI + Postgres feito sob medida (argumento de Bedi).
Esta lição constrói uma miniatura de cada um.
Conceito
Execução durável, o padrão
Um motor de execução durável persiste o estado completo do programa após cada "passo" (super-step, na linguagem do LangGraph). Em caso de falha:
worker crashes mid-step
-> lease timeout
-> another worker picks up the thread_id
-> resumes from last checkpoint
-> no duplicate side effects
Requisitos para que isso funcione:
- Estado serializável. Todo o estado do agente precisa ser persistível. Closures de funções com conexões ativas de banco de dados não sobrevivem.
- Retomada determinante. Dado o mesmo estado e as mesmas entradas, o agente produz as mesmas ações (ou recorre a um oráculo determinístico externo para chamadas de LLM).
- Efeitos colaterais idempotentes. Chamadas externas (chamadas de ferramentas, pagamentos) devem ser idempotentes ou usar uma chave de desduplicação.
O LangGraph grava um checkpoint após cada super-step; o Temporal grava após cada atividade; o Restate usa diários baseados em fornecimento de eventos (event-sourced). Todos os três implementam o mesmo padrão.
Runtime do LangGraph
Cada agente possui um thread_id; o estado é um dicionário tipado; cada super-step grava uma linha na tabela de checkpoints. Na retomada, o runtime reproduz a partir do último checkpoint, não do zero. Os agentes podem interromper a execução com interrupt() aguardando entrada humana; o runtime persiste o estado e libera o worker. Quando a entrada chega, qualquer worker pode retomar.
Este é o design de produção de referência em abril de 2026.
Fila por agente do MegaAgent
O artigo arXiv:2408.09955 descreve um experimento de escala: milhares de agentes simultâneos em um único cluster. Arquitetura:
agent i:
state ∈ {Idle, Processing, Response}
in_queue <- messages addressed to agent i
out_queue -> replies + side effects
coordinators:
intra-group chat (agents in the same group)
inter-group admin chat (high-level routing)
A coordenação em duas camadas permite que as conversas intragrupo ocorram densamente, enquanto a intergrupo permanece esparsa — o padrão usado para manter o custo linear mesmo com milhares de agentes.
Async vs thread-per-job
As chamadas de LLM são limitadas por I/O (I/O-bound). Uma thread esperando pelo próximo token fica ociosa 99% do tempo. As threads custam cerca de 1MB de RAM cada; com 10.000 chamadas simultâneas, seriam 10GB apenas para pilhas de execução (stacks).
Fibers (Python asyncio, goroutines do Go, tokio do Rust) cedem controle cooperativamente no I/O. As mesmas 10.000 chamadas cabem confortavelmente no processo. Na escala de agentes de LLM, async não é uma otimização — é a arquitetura.
Exceção: O pós-processamento limitado por CPU (incorporação/embeddings, truques de tokenizadores) ainda requer threads ou processos. Separe sua camada de I/O de sua camada de CPU.
Contraponto de Bedi
"Scaling Agentic Software" (Ashpreet Bedi, 2026) argumenta que a maioria das equipes superdimensiona a engenharia antes de medir a carga. O padrão pragmático:
- FastAPI + Postgres.
- Cada execução de agente é uma linha; o estado é atualizado in-place com concorrência otimista.
- Tarefas em segundo plano via
pg_notifyou um worker Celery simples. - Política de tentativas (retry) no código da aplicação.
Para cargas abaixo de aproximadamente 100 execuções simultâneas de agentes em tarefas gerenciáveis, isso costuma ser tudo de que você precisa. Atualize quando medir falhas.
A regra: adote frameworks de execução durável apenas quando se deparar com um problema concreto que arquiteturas simples não conseguem resolver. A adoção prematura consome tempo em cerimônias que não se pagam.
Semântica de execução única (exactly-once)
Para execuções pagas de agentes, você precisa de uma "execução única efetiva" (entrega de pelo menos uma vez + consumidor idempotente). As técnicas de engenharia:
- Chave de desduplicação por execução. Inclua-a em cada chamada de efeito colateral.
- Padrão Outbox. Os efeitos colaterais gravam primeiro em uma tabela, depois um processo separado os executa. Ambas as etapas são idempotentes.
- Transações compensatórias. Quando um efeito colateral é bem-sucedido, mas a gravação do seu rastreamento falha, agenda-se uma compensação.
Esses são padrões de engenharia de banco de dados, não específicos de LLM. O único imposto da LLM é que as chamadas são lentas; tudo o mais é sistemas distribuídos padrão.
Implantação arco-íris (rainbow deployment)
O sistema de pesquisa multiagente da Anthropic usa "implantações arco-íris": múltiplas versões do runtime do agente rodam simultaneamente para que os agentes de longa execução não precisem ser encerrados a cada deploy de código. Teste novas versões em uma fração do tráfego (canary); desative as versões antigas conforme seus agentes finalizarem.
Isso é padrão para sistemas de longa execução com estado; a adaptação de 2026 reside no fato de que os agentes podem viver por horas, portanto os ciclos de implantação devem acomodar essa característica.
A lista de verificação de produção canônica
- Estado durável (checkpoints, snapshots ou log reproduzível com outbox).
- Efeitos colaterais idempotentes.
- Camada de I/O assíncrona para chamadas de LLM.
- Entrega de pelo menos uma vez (at-least-once) com desduplicação.
- Implantação arco-íris/canary para cargas de trabalho com estado.
- Observabilidade: rastreamento por agente, auditoria de super-step, contador de tentativas.
Build It
O arquivo code/main.py implementa:
CheckpointStore— log de checkpoints baseado em SQLite com chaves baseadas em ID de thread. Cada super-step anexa uma linha.run_with_checkpoint(agent, thread_id)— simula uma falha no meio da execução; um segundo worker retoma a partir do último checkpoint.AgentQueue— máquina de estados Idle / Processing / Response por agente com uma pequena fila de trabalho.demo_async_vs_threads()— executa 500 chamadas simultâneas de LLM simuladas via asyncio e via threads; relata o tempo de relógio e o pico de memória (aproximado).
Execute:
python3 code/main.py
Saída esperada: a retomada do checkpoint funciona com sucesso após a falha simulada; a versão assíncrona gerencia 500 chamadas simultâneas em menos de 1 segundo; a versão baseada em threads demora vários segundos e consome ordens de grandeza a mais de memória por unidade simultânea.
Use It
O arquivo outputs/skill-scaling-advisor.md fornece recomendações sobre a escolha da execução durável: FastAPI + Postgres, runtime do LangGraph, Temporal ou personalizado. Calibrado de acordo com a carga, necessidades de retenção de estado e frequência de deploy.
Ship It
Endurecimento canônico de produção:
- Comece simples (regra de Bedi). FastAPI + Postgres até medir falhas.
- Instrumente tudo antes de otimizar. Histograma de latência por execução, tempo por etapa (step), contagem de tentativas, categorização de falhas.
- Padrão Outbox para efeitos colaterais. Principalmente pagamentos e chamadas de API externas.
- Implantações arco-íris. Nunca encerre execuções de agentes em andamento durante os deploys.
- Adote motores de execução durável (Temporal / LangGraph / Restate) quando você se deparar com problemas específicos: esperas de horas por entrada humana, coordenação entre regiões, políticas complexas de tentativas/compensação.
- Async para a camada de I/O. Threads apenas para pós-processamento limitado por CPU.
Exercícios
- Execute
code/main.py. Confirme que a retomada de checkpoint funciona; meça a diferença de concorrência entre async e threads. - Implemente uma tabela outbox: cada chamada de ferramenta grava primeiro no outbox, depois uma tarefa/goroutine separada a executa. Verifique a idempotência executando a chamada de ferramenta duas vezes.
- Simule um deploy arco-íris: duas versões simultâneas do runtime; roteie metade dos novos thread_ids para cada; confirme que as threads em andamento na versão antiga não são interrompidas.
- Leia a documentação de runtime do LangGraph (link abaixo). Identifique quais recursos do runtime levariam mais tempo para replicar em uma versão sob medida usando FastAPI + Postgres. Esse é um motivo para adotá-lo ou você pode adiar?
- Leia a Seção 3 do MegaAgent (arXiv:2408.09955). A coordenação em duas camadas (chat intragrupo + chat administrativo intergrupo) é explícita. Esboce como você mapearia isso para uma fila de mensagens com duas famílias de filas.
Termos-Chave
| Termo | O que as pessoas dizem | O que realmente significa |
|---|---|---|
| Execução durável | "Persistir o estado do programa" | O motor grava o estado após cada super-step; a recuperação de falhas é determinística. |
| Super-step | "Fronteira transacional" | Unidade de trabalho entre checkpoints. Termo do LangGraph. |
| thread_id | "Identificador de execução do agente" | Chave que vincula checkpoints e lógica de retomada. |
| Idempotência | "Seguro para tentar novamente" | Repetir um efeito colateral produz o mesmo resultado que uma única tentativa. |
| Padrão Outbox | "Desacoplar efeitos colaterais" | Grava a intenção em uma tabela; um executor separado executa e marca como concluído. |
| Entrega de pelo menos uma vez | "Possíveis duplicatas" | Semântica de fila de mensagens; chave de desduplicação torna o consumo efetivamente uma única vez. |
| Implantação arco-íris | "Versões sobrepostas" | Múltiplas versões de runtime rodando simultaneamente durante cargas de trabalho de longa duração. |
| Fibra assíncrona | "Cessão de controle cooperativa" | Concorrência em modo de usuário; barata em comparação a threads para cargas limitadas por I/O. |
| Checkpoint | "Snapshot do estado" | Estado serializado na fronteira de um super-step; chave para retomada. |
Leitura Adicional
- LangChain — The runtime behind production deep agents — Design do runtime do LangGraph
- MegaAgent — Fila de produtor-consumidor por agente; coordenação em duas camadas com milhares de agentes simultâneos
- Matrix — Framework descentralizado com filas de mensagens como substrato de coordenação
- Temporal docs — O motor de workflow de referência para execução durável
- Anthropic — Multi-agent research system — Lições de produção incluindo implantação arco-íris