A maioria das pessoas que tentam construir um agente multi-etapas acaba com uma linha reta. Passo um, passo dois, passo três - cada um esperando educadamente o anterior terminar antes de começar.
9/10 percebem que metade desses passos nunca precisou esperar.
Eles não roteiam. Eles não ramificam. Eles não paralelizam. Eles apenas enfileiram - uma cabeça, um contexto, uma coisa de cada vez, até que a janela enche e o agente esquece o que estava fazendo.
Siga meu Substack para receber novidades frescas de IA:
Este é o roteiro de 14 etapas que transforma essa fila individual em um grafo: um que se ramifica por uma frota, verifica suas próprias descobertas e converge para um resultado que um único agente jamais conseguiria manter.

Aqui está a mudança que ninguém explica. Um prompt é uma frase. Um loop é um ciclo. Um harness é o chão onde o agente se apoia.
Mas o formato do trabalho em si - o que executa antes do quê, o que pode executar ao mesmo tempo, o que tem que esperar por todo o resto - esse formato é um grafo. Os nós fazem o pensamento. As arestas carregam os resultados.
O Claude Code disponibilizou as ferramentas para construir esses grafos diretamente: workflows dinâmicos.
O Claude escreve um script de orquestração em JavaScript puro, então cria uma frota coordenada de subagentes para executá-lo - e a própria coordenação custa zero tokens do modelo, porque é código, não uma conversa.
01. Nós são tarefas. Arestas são o que flui.
Um grafo tem exatamente duas coisas, e entendê-las direito resolve a maior parte da confusão. Um nó é uma unidade de trabalho - um agente, uma tarefa delimitada, uma entrada e uma saída.
Uma aresta é uma dependência: ela diz a saída deste nó alimenta a entrada daquele nó. Nada mais.

O erro é tratar "e então" como uma aresta. "Resumir o arquivo e então me dizer o clima" não tem aresta entre os dois - o clima não consome o resumo.
Isso são dois nós desconectados que um script linear acorrenta desnecessariamente. A aresta só existe quando os dados realmente fluem através dela.
Aprenda a perguntar, para cada "e então" no seu agente: o próximo passo lê a saída do passo anterior? Se não, não há aresta, e a espera é desperdiçada.
1Desenhe como caixas e setas. Uma caixa é uma chamada agent().2Uma seta é uma variável passada do retorno de uma chamada para o3prompt de outra. Se você não consegue desenhar a seta - se nenhuma4variável cruza - as duas caixas são independentes, e independência5é a coisa que você explorará pelo resto deste curso.
02. Seu script linear é um grafo degenerado
Quando você escreve um agente como "faça A, então B, então C, então D", você desenhou um grafo - uma única cadeia sem ramificações. Cada nó tem exatamente uma aresta de entrada e uma de saída.
Ele funciona corretamente. Mas também funciona lentamente e de forma frágil, porque uma cadeia não tem redundância: se C trava, D nunca acontece, e o trabalho de A fica preso rio acima sem para onde ir.

A primeira habilidade real da engenharia de grafos é redesenhar a cadeia. Pegue seu agente linear e, para cada seta, faça a pergunta do Passo 1.
A maioria das cadeias tem duas ou três setas que não carregam dados - elas são apenas a ordem em que você digitou as coisas.
Corte essas setas e a cadeia se desfaz em algo mais amplo: alguns nós independentes que poderiam todos ser executados de uma vez, alimentando um único nó que precisa de todos eles.
03. Dê a cada nó um contrato
Um nó sobre o qual você não pode raciocinar é um nó que você não pode paralelizar. A solução é um contrato: entrada delimitada, saída delimitada, exatamente uma tarefa.
A entrada é o que o nó lê - passado explicitamente, nunca assumido a partir de uma janela compartilhada. A saída é uma forma definida, idealmente validada, para que o próximo nó possa consumi-la sem adivinhar.

Em um workflow, esse contrato é aplicado com um schema. Quando você passa para o Claude uma chamada agent() com um schema JSON, o subagente Claude que é criado é forçado a retornar dados estruturados validados - a validação acontece na camada de chamada de ferramenta, então o Claude tenta novamente em caso de incompatibilidade, em vez de lhe entregar texto livre que você precisa analisar e torcer para funcionar.
Esta é a diferença entre um nó que o Claude pode conectar em um grafo e um nó que só funciona quando um humano lê sua saída.
1// Um nó com contrato real: entrada delimitada, saída validada, uma tarefa.2const ITEM = {3 type: 'object', additionalProperties: false,4 properties: {5 title: { type: 'string' },6 url: { type: 'string' },7 impact: { type: 'string', enum: ['high', 'medium', 'low'] },8 },9 required: ['title', 'url', 'impact'],10};1112const result = await agent(source.prompt, {13 label: `research:${source.key}`,14 schema: ITEM, // força saída estruturada validada15 agentType: 'general-purpose',16});17// result agora é uma forma que o próximo nó pode confiar — não texto livre.
04. Trate a aresta como um contrato de dados
Uma aresta não é apenas "B vem depois de A". É uma promessa sobre o que cruza: A produz esta forma, e B é construído para consumir esta forma. Quando você nomeia a aresta pelo seu dado - não pela sua ordem - duas coisas ficam mais fáceis.

Você pode ver instantaneamente se a aresta é real (os dados realmente se movem?), e você pode trocar o nó em qualquer extremidade sem quebrar o grafo, desde que a forma se mantenha.
Na prática, a aresta vive em JavaScript puro. A etapa de redução entre a expansão e a síntese - achatar, deduplicar, filtrar - é apenas código operando nas formas que seus nós retornaram.
Nenhum agente necessário. Uma das vitórias silenciosas do pensamento em grafos: uma quantidade enorme do que as pessoas queimam tokens de modelo é, na verdade, uma aresta, e arestas são gratuitas.
1A tentação é criar um agente para "combinar os resultados." Resista.2Se combinar significa achatar-e-deduplicar, isso é results.flatMap(...)3e um Set — determinístico, instantâneo, zero tokens. Guarde agentes para4julgamento, não para encanamento. Um grafo onde cada aresta é um agente é um5grafo pagando aluguel na própria fiação.
05. Expanda com parallel()
Este é o movimento que paga tudo. Quando você tem N nós independentes - N fontes para verificar, N arquivos para revisar, N rotas para auditar - você não os encadeia.
Você diz ao Claude para expandi-los e executá-los de uma vez. Em um workflow, isso é parallel(): o Claude pega um array de thunks e cria um subagente por thunk, todos executando simultaneamente, e então devolve o array de resultados.

Dois detalhes o tornam robusto. Primeiro, parallel() é uma barreira - ela espera todos os thunks antes de retornar, então o próximo estágio vê o conjunto completo. Segundo, um thunk que lança um erro resolve para null em vez de rejeitar todo o lote, então um agente instável não pode afundar a execução.
Sempre .filter(Boolean) nos resultados. A concorrência é limitada em torno da sua contagem de núcleos e o excesso é enfileirado, então você pode passar cem thunks e todos terminarão - apenas alguns de cada vez.
1phase('Research');23// Nove fontes, nove agentes, todos de uma vez.4const raw = await parallel(5 SOURCES.map((s) => () =>6 agent(s.prompt, {7 label: `research:${s.key}`,8 phase: 'Research',9 schema: ITEM_SCHEMA, // cada nó retorna JSON validado10 agentType: 'general-purpose',11 }),12 ),13);1415const collected = raw.filter(Boolean); // remove os nulls de agentes com falha
A expansão vive no código que o Claude escreveu, não em uma conversa do modelo. O próprio contexto do Claude nunca contém nove fontes ao mesmo tempo - cada subagente carrega as suas, e apenas a resposta final retorna.
É isso que permite ao Claude escalar um workflow para dezenas ou centenas de subagentes sem afogar a sessão. A camada de orquestração custa zero tokens porque não é outra rodada de pensamento do Claude.
06. Reúna em uma barreira
Uma expansão só é útil se algo a reunir. A reunião é o nó onde as arestas convergem - onde um agente (ou um pedaço de código) vê todos os resultados upstream de uma vez e faz algo que requer o conjunto completo: deduplicar entre fontes, classificar por impacto, sair cedo se o total retornou vazio. Este é o único lugar onde uma barreira ganha seu custo de tempo de relógio.

A regra que mantém os grafos rápidos: use uma barreira apenas quando um estágio genuinamente precisar de todos os resultados anteriores juntos. Deduplicar entre todas as fontes? Barreira - correto.
1// A aresta: JS puro, sem agente, zero tokens.2const flat = collected.flatMap((c) => c.items);3log(`Coletados ${flat.length} itens`);45phase('Curate');6// O nó barreira: precisa do CONJUNTO INTEIRO para deduplicar + classificar.7const curated = await agent(8 `Deduplicar e classificar estes por impacto:\n${JSON.stringify(flat)}`,9 { phase: 'Curate', schema: CURATED_SCHEMA },10);
Apenas achatar uma lista? Isso é uma aresta, faça inline. O teste de cheiro é brutal e simples: se você escreveu parallel → transform → parallel, e essa transformação do meio não tem dependência entre itens, você deveria ter usado um pipeline e pulado a barreira completamente.
07. O diamante: dividir → trabalhar → mesclar
Junte a expansão e a reunião e você obtém a topologia de trabalho pesado de todo grafo de agente sério: o diamante.
Um nó divide o trabalho, muitos nós fazem o trabalho em paralelo, um nó mescla. É a forma por trás de uma varredura de mercado, uma auditoria de dependências, uma revisão de código, um relatório de pesquisa - troque as fontes e os prompts e o mesmo esqueleto se adapta.

A forma canônica tem um nome que vale a pena memorizar: expandir → reduzir → sintetizar. Expanda para obter amplitude, reduza com código puro para comprimir, sintetize com um agente final para escrever a resposta.
Depois que você vê o diamante, para de perguntar "como faço meu agente dar mais passos" e começa a perguntar "onde está a divisão, onde está a mesclagem" - que é a pergunta que realmente escala.
08. Roteie a aresta em tempo de execução com um condicional
Nem todo grafo é fixo. Às vezes, a aresta a ser seguida depende do que um nó encontrou. Um nó roteador inspeciona um resultado e decide qual caminho downstream dispara - classifique o ticket, então ramifique para o manipulador correto; verifique o tamanho do diff, então faça uma revisão rápida ou inicie uma auditoria completa.
Em um workflow, isso é apenas um if ou switch JavaScript na saída validada de um nó, porque o fluxo de controle vive no código.

É aqui que o determinismo se torna uma característica, não uma limitação. A decisão do roteador pode ser alimentada pelo Claude (um subagente classifica), mas o roteamento é código que o Claude escreveu - então ele executa da mesma forma toda vez para a mesma classificação.
Você obtém o julgamento do Claude no nó e a confiabilidade do script na aresta. Sem surpresas emergentes de "Claude decidiu pular a auditoria" - porque a omissão teria que ser escrita no grafo, e não está.
1// Nó roteador: um agente classifica, o código escolhe a aresta.2const { severity } = await agent(3 `Classifique o risco deste diff:\n${diff}`,4 { schema: { type: 'object',5 properties: { severity: { enum: ['low', 'high'] } },6 required: ['severity'] } },7);89let review;10if (severity === 'high') {11 // caminho pesado: auditoria paralela completa12 review = await parallel(FILES.map((f) => () => agent(`Auditar ${f}`)));13} else {14 // caminho leve: uma passagem rápida15 review = await agent(`Revisão rápida de ${diff}`);16}
09. Coloque um verificador na aresta
A verdadeira vantagem de um grafo não são mais agentes - é a estrutura que você pode colocar em volta deles para produzir confiança.
Um nó verificador fica na aresta antes que um resultado seja permitido downstream, e seu único trabalho é tentar matar a descoberta. Se ela sobreviver, passa. Se não, nunca chega à resposta.

Três padrões valem a pena ter em mãos.
- Verificação adversarial: para cada descoberta, crie N céticos independentes instruídos a refutá-la; mantenha-a apenas se a maioria sobreviver.
- Verificação com perspectiva diversa: dê a cada verificador uma lente distinta - correção, segurança, isso-se-reproduz - porque a diversidade pega modos de falha que N verificações idênticas nunca pegarão.
- Painel de juízes: gere N tentativas de diferentes ângulos, pontue-as com juízes paralelos, sintetize a partir do vencedor enquanto enxerta o melhor dos segundos colocados.
Este é exatamente o padrão que permitiu a uma equipe real portar o runtime Bun com revisão de código adversarial integrada ao loop.
10. Isole os nós para que uma falha não envenene o grafo
Em uma cadeia, uma falha em cascata - C morre, D nunca executa, tudo para. Em um grafo, a falha deve ser contida ao seu nó.
Isso já é parcialmente verdade: um thunk que lança um erro dentro de parallel() resolve para null, então oito bons agentes ainda retornam enquanto um ruim cai fora. Seu .filter(Boolean) é a contenção.
Projete cada reunião para tolerar entradas ausentes em vez de assumir um conjunto completo.

A falha mais sutil são nós interferindo uns nos outros. Quando agentes escrevem arquivos em paralelo, eles podem colidir.
A solução é o isolamento: "worktree" - cada agente executa em seu próprio git worktree, faz seu trabalho em uma sandbox e mescla de forma limpa.
Recorra a ele apenas quando os nós realmente escreverem em paralelo. É o cinto de segurança para a topologia que precisa dele, não um imposto padrão em toda execução.
11. Adicione um ciclo - mas faça-o convergir
Às vezes você não sabe o tamanho do trabalho até estar nele: descoberta de tamanho desconhecido, uma varredura de bugs onde encontrar um bug revela mais três. Isso precisa de um ciclo - uma aresta controlada de volta a um nó anterior.
O perigo é óbvio: um ciclo que não converge é um loop infinito que cria agentes até que seu orçamento acabe.

O padrão que converge é loop-até-secar: continue criando localizadores até que K rodadas consecutivas não revelem nada de novo, então pare. O único detalhe que faz ou quebra - e o erro que quase todo mundo comete na primeira vez - é contra o que você deduplica.
Deduplique contra tudo visto, não apenas contra resultados confirmados. Caso contrário, descobertas rejeitadas reaparecem a cada rodada, o loop nunca seca, e você construiu uma máquina que paga para redescobrir os mesmos becos sem saída para sempre.
1const seen = new Set(); const confirmed = []; let dry = 0;23while (dry < 2) { // para após 2 rodadas vazias4 const found = (await parallel(5 FINDERS.map((f) => () => agent(f.prompt, { schema: BUGS }))6 )).filter(Boolean).flatMap((r) => r.bugs);78 const fresh = found.filter((b) => !seen.has(key(b)));9 if (!fresh.length) { dry++; continue; } // nada novo → em direção a secar10 dry = 0;11 fresh.forEach((b) => seen.add(key(b))); // deduplica vs VISTO, não confirmado1213 // verificação com lentes diversas para cada nova descoberta antes de contar14 const judged = await parallel(fresh.map((b) => () =>15 parallel(['correctness', 'security', 'repro'].map((lens) => () =>16 agent(`Julgue "${b.desc}" via ${lens} — real?`, { schema: VERDICT })))17 .then((v) => ({ b, real: v.filter(Boolean).filter((x) => x.real).length >= 2 }))));1819 confirmed.push(...judged.filter((v) => v.real).map((v) => v.b));20}
12. Hierarquize os modelos entre os nós
Nem todo nó precisa do seu melhor modelo. Um grafo torna isso óbvio de uma forma que um único agente nunca faz: alguns nós são delimitados e repetitivos (extrair este campo, classificar este ticket), e alguns carregam o julgamento real (sintetizar o relatório, julgar a descoberta).
Execute os nós chatos em um modelo mais barato e gaste seus tokens caros onde o julgamento realmente vive.

Em um workflow, cada subagente que o Claude cria herda o modelo da sua sessão, a menos que o script o substitua - então, por padrão, uma execução grande fatura inteiramente no nível da sua sessão. A opção model em uma única chamada agent() diz ao Claude para rotear apenas aquele nó para outro lugar.
Verifique /model antes de uma execução grande, então peça ao Claude para rotear os nós repetitivos da expansão para um modelo mais barato e manter o nó de mesclagem no nível superior. Esta é a alavanca que transforma um grafo faminto por tokens de caro em econômico sem tocar em sua forma.
13. Topologia é seu custo e latência
A forma do grafo não é cosmética - é a maior alavanca no tempo de relógio. A escolha que pega todo mundo: parallel() versus pipeline(). Uma barreira parallel() faz tudo esperar pelo nó mais lento antes do próximo estágio começar.
Um pipeline() transmite cada item por todos os estágios de forma independente, sem barreira - o item A pode estar no estágio 3 enquanto o item B ainda está no estágio 1. Itens rápidos terminam cedo em vez de ficarem ociosos atrás de itens lentos.

Use pipeline() por padrão. Recorra a uma barreira apenas quando um estágio precisar genuinamente de todos os resultados anteriores de uma vez - uma deduplicação entre conjuntos, uma saída antecipada no total, um prompt que compara com "as outras descobertas." "É código mais limpo" e "os estágios parecem separados" não são razões; a latência da barreira é real, mensurável, tempo desperdiçado. Separado não é o mesmo que sincronizado.
14. Deixe o Claude desenhar o grafo - auto-roteamento
O movimento final é parar de desenhar o grafo manualmente para trabalhos que você não pode planejar com antecedência.
Com workflows dinâmicos, você descreve o objetivo e o Claude escreve o script de orquestração - decompondo a tarefa, escolhendo a expansão, criando uma frota coordenada de subagentes e sintetizando o resultado. Você obtém um grafo adaptado para esta execução, em vez de um fixo que você esperava que se encaixasse.

Existem três maneiras de entrar. Diga a palavra "workflow" no seu prompt e o Claude escreve um para a tarefa. Execute um salvo ou empacotado - /deep-research é um grafo real rodando em produção: escopo → pesquisa paralela → buscar → verificar adversarialmente → sintetizar, o esqueleto exato deste curso.
Ou ative o ultracode e o Claude planeja um workflow para cada tarefa substancial na sessão. Quando uma execução for boa, pressione s para salvar seu script em .claude/workflows/ - versionado, reexecutável pelo nome, um grafo que qualquer um que clonar o repositório pode lançar.
1› Execute um workflow para auditar cada rota em src/routes/ em busca de2autenticação ausente. Crie um agente por arquivo de rota, então verifique cada3descoberta antes de relatar. ● Claude escreveu um script de orquestração ·4lançando em segundo plano… /workflows — auth-audit · executando ✓ Escopo 1/152.1k tok · 4s ✓ Expansão 18/18 um agente por arquivo de rota ◯ Verificar611/18 céticos de 3 votos por descoberta… ○ Sintetizar 0/1 aguardando7verificação a sessão permanece responsiva — continue trabalhando enquanto a8frota executa
Seis grafos para construir com o Claude esta semana

- Varredura de segurança em cada rota. O Claude cria um subagente por arquivo de rota, cada um caçando verificações de autenticação ausentes, então uma passagem de verificador confirma cada descoberta antes que ela chegue ao relatório. Amplitude que nenhum contexto único poderia conter.
- Relatório citado com /deep-research. Um grafo que já vem no Claude Code. O Claude decompõe sua pergunta em ângulos distintos, executa pesquisas paralelas, deduplica fontes, então verifica adversarialmente cada afirmação com céticos de três votos antes de escrever.
- Porte um módulo, arquivo por arquivo. O teto do Bun, escalado para seu repositório. O Claude distribui a tradução entre os arquivos, executa a suíte de testes como uma barreira em cada um, e loopa as falhas de volta - revisão adversarial pegando o que uma única passagem enviaria quebrado.
- Revisão adversarial de um diff. O Claude roteia com base no tamanho do diff: uma pequena alteração recebe uma passagem rápida, uma grande aciona uma auditoria paralela completa com revisores em lentes distintas - correção, segurança, desempenho - então um painel de juízes sintetiza.
- Varredura de ecossistema em um cronograma. Salve uma vez, execute para sempre. O Claude verifica muitas fontes em paralelo - releases, blogs, discussões - classifica por impacto em uma barreira, e escreve o resumo. Versionado em .claude/workflows/, lançável pelo nome.
- Descoberta de tamanho desconhecido. Você não sabe quantos bugs existem. O Claude executa localizadores em paralelo, deduplica cada nova descoberta contra tudo visto, verifica os sobreviventes, e continua em loop até que duas rodadas não revelem nada de novo - então para.
Conclusão:
Um criador de prompts faz uma pergunta. Um arquiteto desenha um grafo.
O agente linear nunca foi o teto - era apenas a primeira forma, aquela que todos usam porque corresponde a como digitamos. Uma linha, uma cabeça, uma coisa de cada vez.
Depois que você consegue ver os nós e as arestas, você para de pedir ao agente para fazer mais e começa a pedir ao grafo para fazer mais amplo: expanda onde o trabalho é independente, controle as arestas onde a confiança importa, hierarquize os modelos onde o julgamento não está.
A maioria das pessoas continuará enfileirando passos em uma linha. Aqueles que aprenderem a desenhar o grafo executarão uma frota - e nunca notarão o teto sob o qual o resto está preso.





