Terceiro artigo da série de 6 partes sobre os cenários do CCA-F — código-fonte completo de cada cenário: aicert-labs.
O cenário, como está no exam guide
Um agente coordenador delega para subagentes especializados — busca, análise de documentos, síntese, geração de relatório — para produzir relatórios citados e abrangentes.
| Domínio | Peso | Onde aparece neste cenário |
|---|---|---|
| Agentic Architecture & Orchestration | 27% | O coordenador planeja subtópicos, roda um subagente por subtópico e depois sintetiza |
| Tool Design & MCP Integration | 18% | Um servidor MCP com duas tools, não uma — a separação é proposital |
| Context Management & Reliability | 15% | O que o coordenador pode — e não pode — ver depois que um subagente termina |
Delegar é a parte fácil
É tentador achar que o problema difícil em "coordenador delega para subagentes" é a própria delegação — decidir dividir o trabalho. Não é. O problema difícil, e o que as questões de cenário do CCA-F são feitas pra testar, é o que atravessa a fronteira entre um subagente e o coordenador.
A versão ingênua faz o coordenador manter uma única conversa longa e chamar toda tool ele mesmo, subtópico após subtópico. Seu contexto cresce com tudo: cada busca, cada documento lido que acabou sendo irrelevante, pra cada subtópico, tudo na mesma conversa. No terceiro subtópico, o contexto do coordenador já é majoritariamente ruído de busca — e, como tudo compete pela mesma janela de contexto, esse ruído é exatamente o que empurra pra fora os achados relevantes do primeiro subtópico.
O researchSubtopic() do aicert-labs resolve isso dando a cada subtópico sua própria conversa descartável. Ele retorna exatamente uma coisa pro coordenador: { subtopic, findings: [{ claim, documentId, source }] }. Não a transcrição. Não quais documentos foram rejeitados. Um punhado de fatos estruturados. O contexto do coordenador cresce com o número de subtópicos, não com quanto cada um precisou pesquisar.
Duas tools, não uma
O servidor MCP expõe search_documents (barata, retorna resultados compactos) e get_document (busca o texto completo de um documento) como tools separadas, em vez de uma única tool que busca e retorna texto completo numa chamada só. Essa separação obriga o subagente a decidir o que vale a pena ler por completo — nem tudo entra no contexto por padrão só porque bateu com uma palavra-chave. A própria descrição do get_document avisa o subagente que trechos (snippets) não são seguros pra citar, o mesmo padrão do process_refund do Cenário 1: colocar a regra no contrato da tool, não numa observação no system prompt fácil de esquecer três tool calls depois.
Rode você mesmo
git clone https://github.com/AICERT-STUDY/aicert-labs
cd aicert-labs/cca-f/scenario-3-multi-agent-research
npm install
cp .env.example .env # adicione sua ANTHROPIC_API_KEY
npm run research -- "Does a 4-day work week actually work?"
O corpus mock (seis fontes sobre pesquisa de semana de 4 dias) inclui de propósito documentos que discordam entre si — um estudo de manufatura não encontra ganho de produtividade onde estudos de trabalho de conhecimento encontram — então a síntese precisa realmente reconciliar fontes, não só concatená-las.
Teste seus conhecimentos
1. Por que researchSubtopic() retorna só { subtopic, findings } em vez do histórico completo de mensagens do subagente?
Resposta: pra que o contexto do coordenador cresça com o número de subtópicos, não com quanto cada subagente precisou buscar e ler.
Se o coordenador mantivesse a transcrição completa de cada subagente, seu contexto encheria de ruído de busca proporcional ao esforço, não ao que é realmente relevante pro relatório final — e esse ruído empurra pra fora os achados que importam.
2. Qual a razão arquitetural pra separar search_documents e get_document em duas tools em vez de uma só que retorna o texto completo direto?
Resposta: obriga o subagente a decidir o que vale a pena ler por completo, em vez de todo resultado de busca entrar no contexto por padrão com o texto completo.
Uma única tool de buscar-e-retornar-tudo otimiza pra menos chamadas de tool ao custo de crescimento de contexto não revisado. Separar o ponto de decisão numa chamada própria é uma troca deliberada: uma ida-e-volta extra em troca do subagente só trazer o que ele de fato julga relevante.
3. O subagente de pesquisa tem uma tool record_finding em vez de simplesmente responder com uma lista de achados no texto final. Por quê?
Resposta: uma tool dedicada dá ao coordenador um resultado estruturado e parseável, em vez de depender do modelo formatar texto livre corretamente e de forma consistente.
É o mesmo princípio por trás dos resultados tipados de tool em outros pontos desta série: uma chamada de tool é algo que o código chamador pode confiar estruturalmente; um parágrafo de prosa exige que quem chama interprete corretamente toda vez, sem garantia de consistência entre execuções.
4. Se dois documentos dão respostas conflitantes pro mesmo subtópico, em que etapa desta arquitetura isso é reconciliado?
Resposta: na síntese — os subagentes de pesquisa individuais não trocam informação entre si; só a etapa de síntese do coordenador vê os achados de todos os subtópicos ao mesmo tempo.
Cada subagente de pesquisa trabalha em um subtópico isoladamente e não tem visibilidade do que outros subagentes encontraram. Reconciliar contradições exige um ponto de vista que veja tudo de uma vez, o que, por design, só a etapa de síntese tem.
5. O coordenador roda os subagentes de pesquisa sequencialmente, num loop for, em vez de em paralelo. O que precisaria ser verdade pra trocar isso por Promise.all ser seguro?
Resposta: os subagentes precisariam ser independentes entre si, sem estado mutável compartilhado e sem um subtópico depender dos achados de outro — o que já é o caso aqui.
Como cada chamada de researchSubtopic() só lê do corpus MCP compartilhado e escreve no seu próprio array local de findings, nada na arquitetura de fato exige execução sequencial — é uma escolha de legibilidade do log no console, não uma questão de corretude.
Simulado gratuito do CCA-F, cobrindo os 5 domínios: aicert.study/certifications/ccaf.
