Elton José logo
Elton José
Deep Agents

Deep Agents: O Padrão de Planejamento Hierárquico que Virou Template no LangGraph

Deep Agents: O Padrão de Planejamento Hierárquico que Virou Template no LangGraph
0 visualizações
19 minutos de leitura
#Deep Agents

Deep Agents: O Padrão de Planejamento Hierárquico que Virou Template no LangGraph

Foram quarenta minutos de execução numa tarefa de migração até o agente morrer no meio. Não morreu por bug, nem por limite de rate. Morreu porque o histórico de mensagens tinha engolido o próprio objetivo: quando ele chegou no arquivo número dezoito, já não lembrava direito da convenção que tinha decidido no arquivo três. O trace mostrava a decisão original lá, intacta, a uns cem mil tokens de distância — presente no contexto, mas invisível na prática.

Esse tipo de falha é chato porque não parece falha. O agente continua respondendo, continua chamando ferramenta, continua parecendo produtivo. Ele só para de ser coerente. E a resposta reflexa — "coloca um modelo com janela maior" — resolve o sintoma por umas três semanas, até a tarefa crescer de novo.

O padrão que surgiu como resposta séria a isso ganhou um nome meio infeliz mas que pegou: deep agent. Um agente que planeja em níveis, usa o sistema de arquivos como memória externa e delega pedaços do trabalho para subagentes que rodam em contexto próprio e devolvem só o resultado. É o desenho por trás do Claude Code e das ferramentas de deep research, e desde março de 2026 a LangChain o empacotou numa biblioteca própria, a deepagents, com template de deploy e CLI em volta.

Neste post quero destrinchar a anatomia desse padrão, entender por que ele funciona para tarefa longa, discutir o que significa ele ter virado template de framework, e ser honesto sobre onde ele cobra caro sem entregar — incluindo um caminho de adoção que não exige reescrever o agente que já está em produção.


O Que Um Deep Agent Tem Que Um Agente Comum Não Tem

Vale desfazer uma confusão de saída: deep agent não é um novo tipo de loop. O loop é o mesmo de sempre — modelo chama ferramenta, recebe resultado, decide de novo. A própria LangChain descreve a deepagents como "agent harness": a mesma mecânica de tool calling de qualquer framework, com um conjunto de capacidades embutidas por padrão. A diferença está no que vem montado em volta do loop.

São quatro peças. A primeira é o planejamento explícito: uma ferramenta que deixa o agente manter uma lista de tarefas com status (pending, in_progress, completed) persistida no estado, em vez de carregar o plano só na cabeça. Na deepagents isso é o TodoListMiddleware, que expõe a ferramenta write_todos. Guarde esse detalhe — ele volta mais adiante e é o ponto mais interessante do padrão inteiro.

A segunda é o filesystem virtual, um conjunto de ferramentas (ls, read_file, write_file, edit_file, glob, grep, delete, e execute quando há sandbox) sobre backends plugáveis: estado em memória, disco local, o store do LangGraph ou um roteamento composto entre eles. O agente não vê a diferença — ele vê arquivos.

A terceira são os subagentes. Uma ferramenta task permite ao agente principal criar filhos efêmeros para subtarefas isoladas. Cada invocação cria uma instância nova, com contexto próprio, que roda sozinha até terminar e devolve um único relatório final. São explicitamente stateless: não conversam de volta, não negociam. Entregam e morrem.

A quarta é o prompt de sistema detalhado — e aqui já mora a primeira ironia do padrão, que desenvolvo adiante. Junte as quatro e você tem algo assim:

from deepagents import create_deep_agent
from deepagents.middleware import FilesystemMiddleware
from langchain.agents.middleware import TodoListMiddleware

pesquisador = {
    "name": "pesquisador",
    "description": "Investiga um tópico específico e devolve um resumo com fontes.",
    "prompt": (
        "Você investiga UM tópico por vez. Escreva as descobertas em "
        "notas/{topico}.md e devolva no máximo 15 linhas de síntese. "
        "Não devolva transcrição de busca."
    ),
    "tools": ["read_file", "write_file", "grep"],
}

revisor = {
    "name": "revisor",
    "description": "Critica um rascunho e aponta lacunas factuais.",
    "prompt": "Leia o rascunho indicado e liste apenas o que está errado ou faltando.",
    "tools": ["read_file"],
}

agent = create_deep_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[buscar_web, consultar_banco],
    system_prompt=(
        "Fluxo obrigatório: planejar, delegar, criticar, finalizar.\n"
        "Escreva o plano em plano.md antes de delegar qualquer coisa.\n"
        "A redação final é sua — não delegue escrita."
    ),
    subagents=[pesquisador, revisor],
    middleware=[TodoListMiddleware()],
    interrupt_on={"write_file": True},
)

Esse esqueleto é quase exatamente o que a LangChain publicou no repositório deep-agent-template: grafo deployável, prompt de workflow na sequência planejar–delegar–criticar–finalizar, dois subagentes predefinidos (researcher e critic) e interrupções de human-in-the-loop em execute e write_file. Não é pseudocódigo de blog — é o que vem na caixa.


O Filesystem Não É Ferramenta, É Memória De Trabalho

A peça que mais gera mal-entendido é o filesystem. Muita gente olha e pensa "ok, o agente pode escrever arquivo, legal". Mas o papel dele no padrão não é output — é memória de trabalho.

O raciocínio vem direto do trabalho da Anthropic sobre engenharia de contexto: contexto é recurso finito com retorno marginal decrescente, e modelos sofrem de context rot — conforme a janela cresce, a capacidade de recuperar informação de dentro dela cai. Não é um penhasco, é um gradiente. Aquele agente da minha abertura não "esqueceu" a decisão do arquivo três; ele simplesmente parou de conseguir prestar atenção nela em meio a cem mil tokens de ruído.

A saída é externalizar. Em vez de carregar tudo para dentro da janela e torcer, o agente mantém identificadores leves — caminhos, nomes, queries — e puxa o conteúdo sob demanda. A Anthropic chama isso de estratégia just in time e diz que é como o Claude Code opera sobre bases grandes: escreve queries direcionadas, guarda resultados, analisa volume de dados sem nunca carregar o objeto inteiro no contexto. É a mesma lógica pela qual nenhum de nós decora o repositório: a gente usa grep.

Tem um efeito lateral fácil de subestimar: estrutura de diretório e nome de arquivo carregam sinal. Um test_utils.py dentro de tests/ significa algo diferente de um arquivo de mesmo nome em src/core_logic/. Hierarquia, convenção de nomenclatura e timestamp são metadados que o agente lê de graça e usa para decidir o que vale a pena abrir. Quando você desenha o layout de arquivos do agente, está desenhando a estrutura de indexação dele.

Isso conversa diretamente com o que já discuti sobre arquitetura de memória de agentes em produção: a diferença entre memória de curto prazo, memória de trabalho e memória de longo prazo não é acadêmica, é operacional. O deep agent usa o filesystem para as três coisas ao mesmo tempo, e é por isso que a escolha de backend importa. StateBackend, o padrão, guarda no estado do grafo e some quando a thread acaba. StoreBackend persiste entre threads. FilesystemBackend toca disco de verdade. Escolher errado aqui é a diferença entre um agente que lembra de ontem e um que reinicia do zero toda manhã sem avisar ninguém.

Há uma consequência de projeto que decorre disso e raramente é dita em voz alta: nesse desenho, o plano do agente é só mais um arquivo. Quando o plano.md vive no filesystem em vez de numa mensagem enterrada no histórico, ele pode ser relido a qualquer momento, reescrito quando a realidade muda e inspecionado por um humano no meio da execução sem que ninguém abra um trace. O agente da minha abertura não precisava de janela maior. Precisava de um lugar estável para a convenção que decidiu no arquivo três e de instrução para reler esse lugar antes de tocar no arquivo dezoito — uma correção quase constrangedora de simples perto do tamanho do problema.

O preço disso é que a externalização transfere trabalho para a política de recuperação, e essa parte quase nunca recebe o mesmo cuidado. Um arquivo que o agente escreve e nunca mais abre é pior do que contexto: é custo de escrita sem nenhum benefício de leitura, e não aparece no trace porque nada falha. Vale instrumentar leitura, não só escrita — quantos dos arquivos produzidos numa execução o agente volta a abrir depois. Se a resposta ficar perto de zero, o filesystem virou aterro, não memória de trabalho.


Externalizar memória resolve metade do problema. A outra metade é o que fazer quando uma subtarefa, sozinha, já é grande demais para caber.

O Subagente Devolve Resumo, Não Histórico

Esse é o coração do padrão e a razão pela qual ele funciona em tarefa de horizonte longo. A formulação da Anthropic é a mais clara que já vi: cada subagente pode explorar extensivamente, gastando dezenas de milhares de tokens ou mais, e devolve apenas um resumo condensado do trabalho — tipicamente entre mil e dois mil tokens.

Pare um segundo nesse número, porque ele é a chave. A relação entre o que o subagente gasta e o que devolve para o pai é de uma ordem de grandeza ou mais. O agente principal nunca vê as trinta buscas, os quinze arquivos abertos, as sete hipóteses descartadas — ele vê a conclusão. O custo em tokens de explorar continua existindo, e você paga por ele; o custo em atenção do agente principal, não. É por isso que o "single handoff" dos subagentes na deepagents não é limitação, é design: se o filho pudesse mandar cinco mensagens de volta, o pai voltaria a acumular histórico e você teria reinventado o problema com passos extras.

O que quebra esse mecanismo é instrução vaga. A Anthropic documentou isso com precisão ao construir o sistema multiagente de pesquisa: começaram deixando o agente líder dar instruções curtas do tipo "pesquise a escassez de semicondutores", e os subagentes ou interpretavam mal a tarefa ou faziam exatamente as mesmas buscas uns dos outros. Num caso, um subagente foi investigar a crise de chips automotivos de 2021 enquanto dois outros duplicavam trabalho sobre cadeias atuais. Cada subagente precisa de objetivo, formato de saída, orientação sobre ferramentas e fontes, e fronteira clara de escopo. Sem isso você não paralelizou nada — só multiplicou a conta.

Tem uma assimetria aqui que o Harrison Chase resumiu bem e que eu levaria para qualquer decisão de arquitetura: sistemas multiagente que principalmente leem são muito mais fáceis do que os que escrevem. Leitura paraleliza; escrita carrega decisão implícita, e decisões conflitantes produzem resultado ruim. Não é coincidência que no Claude Research a parte multiagente cuide da pesquisa, enquanto a síntese final do relatório fica deliberadamente com um único agente numa chamada só. Se o seu deep agent está delegando redação para três subagentes em paralelo e depois tentando costurar, o problema não é o prompt.

Isso complementa a discussão que já fiz sobre composição de agentes especializados versus generalista: a especialização do subagente aqui não é sobre ele ser "melhor" no domínio dele. É sobre ele ter uma janela limpa, um escopo estreito e um contrato de saída pequeno. O ganho é de isolamento de contexto, não de expertise.


O Que Significa Isso Ter Virado Template De Framework

Padrão que vira template de framework atravessou uma fronteira: alguém já pagou o custo de descobrir os defaults, e a discussão migra de "como eu construo isso" para "quando eu uso isso".

O trajeto foi rápido. O LangGraph chegou ao 1.0 em outubro de 2025. Em março de 2026 a LangChain lançou a deepagents como biblioteca standalone sobre o runtime do LangGraph, herdando execução durável, streaming e human-in-the-loop de graça. Em paralelo veio o deepagents-cli, com subcomandos init, dev e deploy, e um layout de projeto que diz muito sobre o que a indústria já considera estável: agent.json para configuração e permissões, AGENTS.md como prompt de sistema, tools.json, skills/<nome>/SKILL.md e subagents/<nome>/.

Repare no que essa estrutura de diretório revela. Subagente virou artefato versionado no repositório, com pasta própria, do mesmo jeito que skill virou. Prompt de sistema virou arquivo AGENTS.md, seguindo uma convenção hoje compartilhada entre ferramentas de fornecedores diferentes. Permissão de filesystem virou regra declarativa — operations, paths em glob e mode de allow ou deny, avaliada em ordem com first-match-wins. Isso é vocabulário de infraestrutura, não de experimento.

O runtime embaixo amadureceu junto, e nem sempre pelos motivos glamourosos — os controles de produção que o LangGraph ganhou em 2026 são menos sobre o agente ser esperto e mais sobre ele falhar de um jeito que dê para operar às três da manhã. Deixo o detalhe dessa camada para a comparação entre LangGraph e CrewAI para agentes em produção que publico na terça, onde ela é o assunto principal.

Vale a ressalva de escopo, porque marketing de framework confunde fácil: deepagents é biblioteca separada, não recurso do LangGraph. LangGraph é o runtime de grafo; o create_agent da LangChain é um harness mínimo em cima; Deep Agents é um harness opinativo em cima do create_agent. As camadas compõem — qualquer CompiledStateGraph pode virar subagente de um deep agent —, mas são coisas distintas, e confundi-las leva a decisão errada de dependência: você acaba prendendo a sua aplicação à opinião do harness quando só queria a durabilidade do runtime, ou reimplementando na mão o que já vinha na caixa uma camada acima.


Até aqui contei a parte que funciona. A parte mais interessante, e que quase ninguém está contando, é onde o próprio fornecedor do padrão descobriu que ele não se paga.

Onde O Padrão Cobra Caro E Não Entrega

Em 29 de julho de 2026 a LangChain publicou a v0.7 da deepagents com uma decisão que merece mais atenção do que recebeu: o TodoListMiddleware deixou de ser padrão. A ferramenta write_todos — o planner explícito, a peça que dá nome a "planejamento hierárquico" — virou opt-in. O motivo declarado: as avaliações internas mostraram que o prompt de planejamento e a ferramenta de todos não melhoravam a performance de forma significativa. Nas três categorias de benchmark e nos modelos testados, os resultados foram levemente melhores e mais baratos com os todos desligados.

Isso não invalida o padrão, mas recalibra a expectativa. A v0.7 removeu o prompt de sistema base embutido, cortou 43% das descrições das ferramentas nativas e tornou os todos opcionais. Resultado: 65% menos tokens de entrada base por turno, de cerca de 6 mil para cerca de 2 mil, com reward estável. No gpt-5.6-luna foram 34% menos tokens e 15% menos custo com reward 4% acima. A própria LangChain registra que os intervalos de confiança do reward cruzam zero em todos os modelos — o ganho de qualidade não é estatisticamente claro; o de custo é. Gosto quando o fornecedor publica isso em vez de arredondar para cima.

Vale insistir no que exatamente foi medido, porque é fácil ler isso como "planejamento não serve", e não é o que o dado diz. O que os evals não sustentaram foi a ferramenta de todos ligada por padrão, para todo tipo de tarefa, com um prompt genérico de planejamento por cima. Planejar continua acontecendo de qualquer jeito: o modelo faz isso no próprio raciocínio, e o plano.md do filesystem cobre o caso em que o plano precisa sobreviver à janela. O que virou opt-in foi a versão cerimonial — uma lista de tarefas com estado, mantida por chamadas explícitas que reaparecem no contexto de todo turno seguinte. A distância entre "planejar" e "declarar o plano numa estrutura persistida e reencaminhá-la a cada passo" é sutil no texto e enorme na conta de tokens.

A leitura que faço: parte das rodinhas de apoio do padrão era compensação para modelos que já não precisam dela. A Anthropic reportou algo convergente ao cortar mais de 80% do system prompt do Claude Code para modelos da geração Opus 5 e Fable 5 sem queda mensurável nos evals de código. Prompt que sobrou de uma geração anterior vira imposto silencioso em toda chamada.

Então quando o planner ainda vale? A própria LangChain lista três casos: tarefas longas e de muitos passos, onde o agente se beneficia de um plano explícito para não perder o fio; modelos menos capazes, que precisam de mais rodinhas de apoio para não pular etapa; e casos com interface de usuário, onde o plano visível vale tanto quanto a execução. Fora isso, você está pagando tokens de planejamento para o modelo dizer em voz alta o que já ia fazer.

Os outros dois custos são menos mensuráveis e mais dolorosos. O primeiro é o debug: agente já é não determinístico entre execuções com o mesmo prompt, e com subagentes a pergunta "por que ele não achou a informação óbvia" ganha uma camada — foi busca ruim do filho, instrução ruim do pai, resumo que descartou o essencial ou falha de ferramenta lá no fundo? Sem tracing completo você não responde isso, e "sem tracing completo" é o estado default da maioria dos times que conheço. O segundo é econômico: sistemas multiagente funcionam em boa parte porque conseguem gastar tokens suficientes, e só fazem sentido quando o valor da tarefa justifica o gasto. Para tarefa curta, deep agent é overhead puro.

Quem leu o post sobre os cinco padrões de orquestração multiagente que dominam a produção reconhece a família: o deep agent é uma encarnação específica do hierárquico, com decisões já tomadas sobre memória e contrato de handoff. O que ele acrescenta é opinião; o que cobra é o mesmo overhead de coordenação em cada nível.


Como Adotar Isso De Forma Incremental

A pior forma de adotar esse padrão é a que mais vejo: alguém lê sobre deep agents numa sexta e na segunda propõe reescrever o agente que já funciona. Não faça isso. As quatro peças são independentes e entram uma de cada vez.

Comece pelo filesystem. É a peça com melhor relação valor/risco e não muda a topologia de nada. Você adiciona ferramentas de leitura e escrita, instrui o agente a descarregar resultado grande em arquivo em vez de carregar no contexto, e passa a referenciar por caminho. O sinal aparece rápido: a conta de tokens de entrada cai e o agente para de perder o fio no meio de tarefa média. Com StateBackend isso vive só dentro da thread; trocar para StoreBackend depois é uma linha.

Depois ajuste a compactação. A deepagents dispara sumarização quando a conversa passa de 85% da janela, com um prompt genérico. Esse limiar é alto se o objetivo é ficar longe da zona de degradação, e não só evitar o estouro. Desde a v0.7 dá para substituir a instância do middleware por uma com o seu limiar e o seu prompt. O conselho da Anthropic para calibrar esse prompt é bom: primeiro maximize recall sobre um trace complexo, depois corte o supérfluo para ganhar precisão.

O terceiro passo é o primeiro subagente — um só, e de leitura. Escolha a subtarefa que mais polui o contexto principal: normalmente busca, exploração de código ou coleta de dados. Escreva o contrato com rigor desproporcional ao tamanho da tarefa: objetivo, formato exato da saída, limite de tamanho, ferramentas permitidas, o que explicitamente não é escopo. Meça tokens do agente principal e taxa de conclusão antes e depois. Se o subagente não reduziu o contexto do pai de forma perceptível, ele não está fazendo o trabalho dele.

O planner vem por último, e como hipótese a testar. Ligue TodoListMiddleware() numa linha, rode nos seus casos reais e compare. Se as suas tarefas são longas o suficiente, ou se o modelo que você usa é mais fraco, ou se existe uma interface mostrando progresso para um humano, ele provavelmente se paga. Fora esses casos, o dado público do fornecedor diz que provavelmente não. Essa é uma inversão saudável em relação a como o padrão foi vendido no começo do ano.

Duas coisas atravessam todos os passos. Tracing desde o dia um, não depois do primeiro incidente: sem ver a trajetória de cada subagente separadamente você não consegue atribuir culpa e acaba ajustando o prompt errado. E interrupts nas operações destrutivas: o template oficial vem com human-in-the-loop em execute e write_file porque a deepagents opera num modelo declarado de "confie no LLM", em que o agente pode fazer tudo o que as ferramentas permitirem. A fronteira mora na ferramenta e no sandbox, não na esperança de que o modelo se autopolicie.


Conclusão

O deep agent é o primeiro padrão de agente longo que vejo chegar com trajetória completa: nasceu como observação sobre por que o Claude Code funciona, virou biblioteca, virou template deployável e depois voltou atrás em uma das próprias peças quando os dados mandaram. Esse último movimento é o que mais me deixa confiante nele. Framework que só acumula recurso está vendendo; framework que corta o que não passou no próprio eval está fazendo engenharia.

Se eu tivesse que resumir o valor central numa frase: o ganho não vem de o agente pensar mais, vem de ele carregar menos. É menos parecido com deixar o agente mais esperto e mais parecido com arrumar a bancada antes de começar o serviço — o filesystem tira peso do contexto, o subagente tira ruído, a sumarização tira histórico morto, e o que sobra na frente do modelo é a peça em que ele está trabalhando agora, com o resto ao alcance da mão mas fora do caminho. O planner explícito, que dá nome ao padrão, acabou sendo a peça com evidência mais fraca, e é justamente a que todo mundo implementa primeiro porque é a mais fácil de demonstrar numa apresentação.

O que ainda não sei responder é quanto disso vai continuar sendo problema nosso. Boa parte dessa arquitetura pode acabar descendo para dentro do modelo e do runtime, do mesmo jeito que ninguém mais escreve retentativa de chamada HTTP na mão — não porque o problema tenha sumido, mas porque a camada de baixo passou a resolvê-lo sem pedir licença. A parte que aposto que fica do nosso lado é a decisão sobre o que entra na janela: enquanto a atenção do modelo for recurso finito com retorno decrescente, escolher o que tirar de lá vai valer mais do que aumentar o tamanho dela. O resto eu trataria como hipótese, não como arquitetura definitiva.

Fontes:

Newsletter

Receba os artigos mais relevantes da semana, sem quebrar seu ritmo de leitura

Um resumo semanal com os melhores posts sobre IA, engenharia de software e tecnologia, enviado no melhor momento para continuar a conversa depois da leitura.

Foto de Elton José

Escrito por

eltonjose

Engenheiro de software e estrategista de produtos digitais, focado em IA pragmática e em transformar experiências de trabalho remoto em aprendizados aplicáveis. Compartilho frameworks e decisões reais que uso em consultorias e projetos.

  • Principais temasDeep Agents, LangGraph
  • Formato do conteúdoGuia prático + insights de carreira