Objetivo da Aula
Definir context saturation e explicar por que ela degrada a qualidade de raciocínio de um agente
Reconhecer o momento em que o harness deve pausar a thread principal e instanciar um subagente temporário
Projetar o contrato de um subagente efêmero: contexto isolado, execução de micro-tarefa, retorno só do resultado refinado
Desenhar paralelismo horizontal (fan-out / fan-in) com múltiplos subagentes independentes
Avaliar o overhead de coordenação contra o ganho de isolamento e paralelismo
Por que isso importa
Todo agente opera dentro de uma janela de contexto finita. Isso não é um detalhe de implementação — é um recurso escasso que compete diretamente com a qualidade do raciocínio do agente. Quando a thread principal de um agente investigativo (capítulo 4.3) precisa varrer cinquenta páginas de documentação, ou fazer scraping de uma dúzia de URLs para coletar um dado, o resultado bruto dessas operações entope o contexto com informação majoritariamente irrelevante — e o que sobra de espaço para o raciocínio que realmente importa (sintetizar a causa raiz, decidir o próximo passo) encolhe.
Isso é context saturation: o ponto em que o contexto acumulado degrada, em vez de ajudar, a capacidade do agente de raciocinar sobre a tarefa original. A resposta arquitetural é isolar a micro-tarefa que gera ruído — o scraping, a varredura, a busca extensa — num subagente temporário, com seu próprio contexto isolado, que devolve à thread principal apenas o resultado já refinado. A thread principal nunca vê os cinquenta documentos brutos; vê o resumo de três parágrafos que o subagente extraiu deles.
Impacto direto no seu trabalho: essa é uma decisão que o harness toma repetidamente, não uma escolha de design única — a cada ação candidata, existe um critério para decidir “isto executa na thread principal ou merece ser isolado num subagente”. Entender esse critério evita dois erros simétricos: subagentizar tudo (overhead de coordenação sem necessidade) ou nunca isolar nada (contexto principal saturado até a qualidade cair).
Conceitos Fundamentais
Context saturation em números
Considere um agente com uma janela de contexto de 200.000 tokens, dos quais o harness reserva um orçamento de, digamos, 40.000 tokens para o raciocínio ativo da tarefa (histórico da conversa, instruções do sistema, estado da investigação). O restante é margem para ferramentas e dados recuperados.
Cenário sem isolamento:
Ação: "buscar informação em 8 páginas web sobre o tema X"
Resultado bruto de cada página: ~6.000 tokens (HTML limpo,
mas ainda com navegação, rodapé, trechos irrelevantes)
8 páginas × 6.000 tokens = 48.000 tokens direto no
contexto da thread principal
→ Só essa ação já estoura o orçamento de raciocínio
reservado (40.000 tokens), antes mesmo de o agente
ter processado o que encontrou.
Cenário com subagente isolado:
Ação: "buscar informação em 8 páginas web sobre o tema X"
→ delegada a 1 subagente com contexto próprio de 48.000
tokens (o mesmo custo de processamento existe, mas
ISOLADO)
Subagente retorna: resumo de ~800 tokens com os pontos
relevantes
→ Thread principal recebe 800 tokens, não 48.000.
Orçamento de raciocínio permanece intacto.O custo total de tokens processados não desaparece — o subagente ainda lê as oito páginas inteiras. O que muda é onde esse custo é pago: fora do contexto que precisa permanecer limpo para o raciocínio da thread principal continuar coerente.
Contrato de um subagente efêmero
Um subagente, nesta topologia, não é um agente de propósito geral — é uma instância criada para uma micro-tarefa específica, com início e fim bem definidos, sem estado que sobrevive além da tarefa.
estrutura SubagenteEfemero:
tarefa: string # escopo estreito, ex: "resumir
conteúdo relevante destas 8 URLs
sobre o tema X"
contexto: isolado # não herda o histórico da thread
principal, só o necessário
para executar a tarefa
ferramentas: [scraping, leitura_de_pagina] # só o que
a micro-tarefa exige
saida_esperada: resumo_estruturado (contrato fixo)
ciclo_de_vida: efêmero # descartado ao final,
nenhum estado persiste
fluxo:
1. thread_principal.pausar()
2. subagente = instanciar(SubagenteEfemero, tarefa)
3. resultado = subagente.executar()
4. thread_principal.retomar(contexto_adicional=resultado)
5. subagente.descartar() # contexto isolado morre aquiO ponto central desse contrato é o passo 4: a thread principal recebe apenas o resultado, um objeto estruturado e enxuto — nunca o contexto interno de execução do subagente. Do ponto de vista da thread principal, o subagente é uma caixa-preta que consome uma tarefa e devolve um resultado, exatamente como uma chamada de função.
Fan-out / fan-in: paralelismo horizontal
Quando a micro-tarefa se divide naturalmente em unidades independentes — oito URLs para investigar, cinco arquivos para analisar — o harness pode instanciar múltiplos subagentes em paralelo, cada um cuidando de uma fatia, e consolidar os resultados quando todos terminam.
A thread principal dispara os quatro subagentes em paralelo, cada um recebendo uma fatia independente do trabalho:
- Thread principal dispara → Subagente 1 (URL A, B) → resumo 1
- Thread principal dispara → Subagente 2 (URL C, D) → resumo 2
- Thread principal dispara → Subagente 3 (URL E, F) → resumo 3
- Thread principal dispara → Subagente 4 (URL G, H) → resumo 4
Quando os quatro terminam, ocorre o fan-in: a thread principal agrega os 4 resumos e continua com [resumo 1, resumo 2, resumo 3, resumo 4] no contexto — não com as 8 páginas brutas.
Paralelismo aqui não é apenas ganho de velocidade (embora seja isso também — os quatro subagentes rodam concorrentemente, não em sequência). É, principalmente, uma forma de manter cada subagente com um escopo de contexto pequeno e coerente: um subagente que processa duas URLs relacionadas ao invés de oito raciocina melhor sobre elas do que um agente único processando oito de uma vez.
Fundamento: Janela de Contexto como Recurso Escasso
É tentador tratar uma janela de contexto grande (100 mil, 200 mil tokens) como “praticamente ilimitada” e não se preocupar com o que entra nela. Isso ignora um efeito bem documentado: qualidade de raciocínio não é uniforme ao longo do contexto — informação no meio de um contexto muito extenso tende a ser subutilizada em comparação com informação no início ou perto do fim (o efeito às vezes chamado de “lost in the middle”). Um contexto tecnicamente cabível não é, na prática, um contexto igualmente utilizável. Isolar ruído em subagentes não é só economia de tokens — é uma forma de manter o sinal relevante em posição de destaque no contexto que o modelo realmente usa para decidir o próximo passo.
O que o subagente devolve: contrato de saída, não transcrição
A qualidade do isolamento depende inteiramente do que o subagente coloca no campo resultado. Um subagente que devolve sua transcrição inteira de raciocínio (todas as páginas que leu, todo o processo de decisão) apenas move o problema de saturação um nível acima — a thread principal agora satura com a transcrição do subagente em vez de com os dados brutos originais.
Contrato de saída ruim (transcrição completa):
resultado = {
raciocinio_completo: "Primeiro consultei a página A, que
dizia X. Depois fui à página B, que mencionava Y mas
não confirmava X. Então busquei na página C..." (2.400
tokens de narrativa do processo)
}
→ thread principal ainda precisa processar quase o mesmo
volume de texto, só que reformulado em prosa
Contrato de saída correto (resultado estruturado):
resultado = {
pontos_relevantes: ["X confirmado pela página A, não
contestado pelas demais", "Y mencionado mas não
verificado"],
fontes: ["url_A", "url_B"],
confianca: "alta para X, baixa para Y"
}
→ ~150 tokens, direto ao ponto, sem narrativa do processoDefinir o contrato de saída antes de instanciar o subagente — como um schema fixo de campos esperados, não como “resuma o que você encontrar” em texto livre — é o que garante que o isolamento realmente produza economia de contexto, e não apenas mova o volume de um lugar para outro.
Aprofundamento Técnico
O custo real da coordenação
Cada subagente instanciado tem overhead: latência de inicialização, custo de tokens do seu próprio system prompt e instruções, e o custo de agregar resultados na thread principal. Paralelizar oito URLs em oito subagentes de uma URL cada tem overhead de coordenação proporcionalmente maior do que quatro subagentes de duas URLs cada — o ganho de isolamento por subagente não escala linearmente até o infinito.
| Configuração | Overhead de coordenação | Risco de saturação interna |
|---|---|---|
| 1 subagente cuidando de 8 URLs | baixo (1 instanciação) | alto — o próprio subagente pode saturar seu contexto |
| 8 subagentes cuidando de 1 URL cada | alto (8 instanciações, 8 agregações no fan-in) | mínimo, mas o overhead consome o ganho |
| 4 subagentes cuidando de 2 URLs cada | moderado — equilíbrio típico | baixo, contexto de cada subagente ainda coerente |
Não existe um número mágico universal — o ponto de equilíbrio depende do tamanho médio de cada unidade de trabalho e do custo de coordenação do harness específico. O princípio de arquitetura é: granularidade de subagente deve ser dimensionada para que cada um processe uma fatia coerente o bastante para não saturar internamente, mas grande o bastante para que o overhead de instanciação não domine o ganho.
Falha parcial em paralelismo
Quando um subagente entre vários falha (timeout, erro de ferramenta, resultado malformado), o harness precisa de uma política explícita — não pode simplesmente travar o fan-in esperando por um resultado que nunca chega.
política de falha parcial:
se subagente_i falha:
se falhas_totais / total_subagentes <= LIMIAR_TOLERAVEL:
continuar com os resultados disponíveis,
marcar resultado_i como "indisponível"
(thread principal decide se isso compromete
a conclusão ou não)
senão:
abortar a operação inteira,
reportar falha sistêmica
(muitos subagentes falhando sugere problema
na tarefa em si, não acaso pontual)A decisão de continuar com resultado parcial ou abortar depende do tipo de tarefa: uma síntese de tendências gerais em oito fontes pode tolerar perder uma fonte; uma verificação de compliance que precisa checar oito requisitos obrigatórios não pode reportar sucesso com um requisito “indisponível”.
Instanciação dinâmica: decidir o número de subagentes em tempo de execução
Em muitos casos, o número de unidades de trabalho não é conhecido de antemão — só se sabe quantos subagentes fazem sentido depois que a thread principal já começou a examinar a tarefa. Isso significa que a instanciação de subagentes não é uma configuração fixa da topologia, é uma decisão tomada em tempo de execução, com base no volume real de trabalho descoberto.
tarefa: "investigar todas as menções ao produto X nas
últimas 48h em fontes públicas"
passo 1 (thread principal): descobrir quantas fontes existem
→ busca inicial retorna 23 URLs distintas
passo 2 (decisão dinâmica de paralelismo):
se numero_de_unidades <= LIMITE_SUBAGENTE_UNICO (ex: 3):
processar inline, sem overhead de subagente
senão se numero_de_unidades <= LIMITE_PARALELO_MAX (ex: 30):
agrupar em lotes de ~3 unidades por subagente
→ 23 URLs / 3 por subagente ≈ 8 subagentes paralelos
senão:
# volume grande demais para paralelismo direto —
# sinal de que a tarefa precisa ser redesenhada
# (paginação, filtragem prévia, ou um loop
# investigativo em vez de fan-out bruto)
reportar_necessidade_de_replanejamento()O limite superior importa tanto quanto o inferior: paralelismo sem teto vira uma forma de context saturation deslocada — em vez de uma thread principal saturada, você tem um fan-in tentando consolidar resultados de dezenas de subagentes simultâneos, o que desloca o problema em vez de resolvê-lo.
Critério prático: isto merece um subagente?
Decisão de Arquitetura: Quando Isolar em Subagente
Três perguntas guiam essa decisão a cada ação candidata. Primeiro: o resultado bruto desta ação é muito maior que o resultado útil dela? (scraping de página inteira para extrair um parágrafo relevante — sim; uma chamada de API que já retorna JSON compacto — não, não precisa de isolamento). Segundo: esta ação é independente o bastante para rodar sem depender do raciocínio corrente da thread principal? Se a ação seguinte depende de uma decisão que só a thread principal pode tomar com base no histórico completo da investigação, isolá-la num subagente sem esse histórico produz um resultado pior, não melhor. Terceiro: o overhead de instanciar e coordenar um subagente é menor que o custo de saturação que a ação causaria se rodasse inline? Para uma única chamada pequena, a resposta quase sempre é não — o overhead de coordenação supera o ganho. Só quando as três respostas apontam na mesma direção (ruído alto, independência alta, overhead menor que o dano) o isolamento em subagente compensa.
A topologia de subagentes efêmeros resolve o problema de contexto saturado por micro-tarefas de vida curta. Mas existe uma classe diferente de sistema multi-agente: aquele em que você não quer instanciar e descartar um agente a cada tarefa pequena, e sim manter um conjunto fixo de especialistas de longa duração, cada um responsável por uma fatia persistente do domínio. Essa é a topologia do próximo e último capítulo desta parte.