Documentation Index
Fetch the complete documentation index at: https://docs.mka1.com/llms.txt
Use this file to discover all available pages before exploring further.
Use este padrão quando um modelo fazendo toda a pesquisa em uma única resposta começar a atingir os limites de contexto.
Em vez de permitir que uma resposta consuma diretamente cada resultado de web_search, use uma resposta pai para delegar tarefas de pesquisa focadas para respostas filhas.
Cada filho realiza suas próprias buscas e retorna um memorando compacto.
O pai consome apenas esses memorandos, o que permite que o fluxo de trabalho geral pesquise de forma muito mais agressiva sem sobrecarregar o contexto do pai.
Esta é uma versão especializada do padrão geral de subagente.
Aqui, o pai é um orquestrador de pesquisa e os filhos são trabalhadores de pesquisa.
Fluxo de pesquisa profunda
-> resposta pai planeja a pesquisa
-> pai chama spawn_subagent várias vezes
-> seu app executa respostas filhas com web_search
-> filhos retornam memorandos de pesquisa compactos
-> seu app envia todos os memorandos filhos de volta como function_call_output
-> pai retoma, decide se faz outra rodada, então responde
Por que usar subagentes para pesquisa profunda
Em um loop clássico de pesquisa profunda com agente único, uma resposta continua chamando web_search.
Isso funciona até que a resposta tenha visto muitos resultados de busca e comece a ficar sem orçamento de contexto útil.
Os subagentes resolvem isso dividindo o trabalho:
- O pai mantém o plano global e a síntese final.
- Cada filho lida com uma tarefa de pesquisa focada e pode fazer várias buscas por conta própria.
- O pai vê apenas o memorando do filho, não cada resultado bruto da busca.
- O pai pode delegar uma segunda ou terceira rodada se a primeira for fraca ou conflitante.
O pai não deve pesquisar diretamente.
Sua função é decompor o pedido, lançar múltiplos subagentes em paralelo e decidir se outra rodada é necessária.
Os filhos devem pesquisar diretamente.
Sua função é fazer o trabalho focado, superar resultados iniciais fracos e retornar evidências compactas para o pai.
Uma boa divisão se parece com isto:
- Pai: planejamento, decomposição de tarefas, resolução de conflitos, resposta final.
- Filho: refinamento de consultas, busca repetida, avaliação de fontes, redação do memorando.
Defina a ferramenta de delegação
Mantenha o esquema da ferramenta pequeno.
Passe apenas a tarefa do filho, instruções opcionais e uma possível substituição de modelo.
const spawnSubagentTool = {
type: "function" as const,
name: "spawn_subagent",
description: "Delegue uma tarefa de pesquisa focada para uma resposta filha e retorne um memorando compacto.",
strict: true,
parameters: {
type: "object",
properties: {
task: { type: "string" },
instructions: { type: "string" },
model: { type: "string" },
},
required: ["task"],
additionalProperties: false,
},
};
type SpawnSubagentArgs = {
task: string;
instructions?: string;
model?: string;
};
Dê ao pai um prompt de orquestração
O prompt do pai deve forçar a decomposição e a abrangência.
Para pesquisa profunda, diga ao pai para usar vários subagentes por padrão e lançar outra rodada quando a primeira for fraca.
const DEEP_RESEARCH_PARENT_INSTRUCTIONS = `
Você é um orquestrador de pesquisa profunda.
Você não pesquisa diretamente.
Use a ferramenta spawn_subagent para delegar tarefas de pesquisa focadas para respostas filhas.
Regras de delegação:
- Para buscas factuais diretas, lance pelo menos 3 subagentes antes de responder.
- Para a maioria das tarefas de pesquisa, lance pelo menos 4 subagentes antes de responder.
- Para pesquisas amplas, ambíguas ou de alto risco, lance de 5 a 8 subagentes em rodadas.
- Lance múltiplos subagentes no mesmo turno sempre que o trabalho deles puder prosseguir de forma independente.
- Se a primeira rodada for incompleta, repetitiva, fraca ou conflitante, lance outra rodada em vez de adivinhar.
Exemplos de delegação:
- Um subagente para o caminho de resposta mais direto.
- Um subagente focado em fontes primárias ou oficiais.
- Um subagente focado em corroboração ou contradições.
- Subagentes adicionais para linha do tempo, geografia, perspectiva de stakeholders, detalhes técnicos ou desenvolvimentos recentes.
Após o retorno de todos os resultados das ferramentas, sintetize as evidências em uma resposta para o usuário.
`;
Dê ao filho um prompt de pesquisa mais rigoroso
O prompt do filho deve restaurar a intensidade de busca que a pesquisa profunda de agente único costuma ter naturalmente.
Sem isso, um filho pode parar após uma busca fraca e retornar um memorando dizendo o que faria a seguir.
const DEEP_RESEARCH_CHILD_INSTRUCTIONS = `
Você é um subagente especialista em pesquisa profunda.
Você tem a ferramenta web_search e deve usá-la de forma agressiva.
Foque apenas na tarefa delegada.
Disciplina de busca:
- Para tarefas não triviais, faça pelo menos 3 buscas web distintas antes de retornar.
- Se a primeira busca for fraca, vazia, genérica ou composta principalmente por diretórios, continue buscando.
- Não retorne "próximos passos". Execute essas buscas você mesmo antes de retornar.
- Prefira fontes primárias, oficiais e de autoridade.
- Trate diretórios e sites de perfil como pistas para corroborar, não como prova única quando uma fonte mais forte deveria existir.
Retorne um memorando compacto para outro modelo:
1. Principais descobertas
2. Evidências e fontes
3. Questões em aberto ou ressalvas
`;
Cada filho é apenas outra requisição de Responses.
Forneça a tarefa delegada como input e a ferramenta web_search.
import { SDK } from "@meetkai/mka1";
const sdk = new SDK({
bearerAuth: process.env.MKA1_API_KEY!,
});
async function runResearchChild(args: SpawnSubagentArgs) {
const child = await sdk.llm.responses.create({
model: args.model ?? "meetkai:functionary-pt",
instructions: args.instructions ?? DEEP_RESEARCH_CHILD_INSTRUCTIONS,
input: args.task,
tools: [
{
type: "web_search",
userLocation: { country: "pakistan" },
searchContextSize: "medium",
},
],
tool_choice: "meetkai:functionary-pt",
parallel_tool_calls: true,
max_tool_calls: 60,
store: true,
});
return {
response_id: child.id,
output_text: child.outputText,
};
}
Continue filhos fracos em vez de aceitá-los
Para pesquisa profunda, não aceite um resultado de filho só porque ele retornou texto.
Se o filho pesquisou apenas uma vez, produziu um memorando curto ou disse coisas como “próximos passos” ou “preciso pesquisar mais”, continue esse mesmo filho com previous_response_id.
const MIN_CHILD_SEARCHES = 3;
const MAX_CHILD_PASSES = 3;
const WEAK_MEMO_PATTERNS = [
/next steps/i,
/let me try/i,
/need to search/i,
/should check/i,
/didn't find/i,
/no direct results/i,
];
function isWeakMemo(outputText: string) {
const trimmed = outputText.trim();
if (!trimmed) return true;
if (trimmed.length < 250) return true;
return WEAK_MEMO_PATTERNS.some((pattern) => pattern.test(trimmed));
}
function buildChildContinuationPrompt(args: {
task: string;
searchCount: number;
previousOutput: string;
}) {
return [
`Continue a tarefa de pesquisa delegada: ${args.task}`,
`Você completou apenas ${args.searchCount} buscas web até agora.`,
`Faça pelo menos ${MIN_CHILD_SEARCHES} buscas web distintas antes de retornar, a menos que já tenha uma resposta direta de evidência autoritativa.`,
`Não retorne "próximos passos" nem diga que mais buscas são necessárias. Execute as buscas adicionais você mesmo.`,
`Priorize fontes primárias, oficiais e de autoridade. Use diretórios apenas como pistas para corroborar.`,
``,
`Memorando anterior:`,
args.previousOutput,
].join("\n");
}
async function runResearchChildWithContinuation(args: SpawnSubagentArgs) {
let previous_response_id: string | undefined;
let nextInput = args.task;
let totalSearchCount = 0;
for (let pass = 0; pass < MAX_CHILD_PASSES; pass += 1) {
const child = await sdk.llm.responses.create({
model: args.model ?? "meetkai:functionary-pt",
instructions: args.instructions ?? DEEP_RESEARCH_CHILD_INSTRUCTIONS,
...(previous_response_id
? { previous_response_id, input: nextInput }
: { input: nextInput }),
tools: [
{
type: "web_search",
userLocation: { country: "pakistan" },
searchContextSize: "medium",
},
],
tool_choice: "meetkai:functionary-pt",
parallel_tool_calls: true,
max_tool_calls: 60,
store: true,
});
const passSearchCount = countCompletedWebSearches(child.output);
totalSearchCount += passSearchCount;
if (totalSearchCount >= MIN_CHILD_SEARCHES && !isWeakMemo(child.outputText)) {
return {
response_id: child.id,
output_text: child.outputText,
search_count: totalSearchCount,
};
}
previous_response_id = child.id;
nextInput = buildChildContinuationPrompt({
task: args.task,
searchCount: totalSearchCount,
previousOutput: child.outputText,
});
}
throw new Error("A resposta do filho permaneceu muito fraca após múltiplas rodadas de pesquisa");
}
O helper exato countCompletedWebSearches depende se você está usando eventos transmitidos ou itens de saída armazenados.
A ideia importante é contar operações de busca realmente concluídas, não apenas turnos.
Execute uma rodada do pai, depois reúna todos os memorandos filhos
O pai deve poder emitir várias chamadas spawn_subagent em um turno.
Trate essas chamadas de ferramenta como um lote.
Inicie todos os filhos, aguarde todos terminarem e então retome o pai uma vez com todas as saídas dos filhos.
export async function runDeepResearch(input: string) {
let response = await sdk.llm.responses.create({
model: "meetkai:functionary-urdu-large",
instructions: DEEP_RESEARCH_PARENT_INSTRUCTIONS,
input,
tools: [spawnSubagentTool],
tool_choice: "meetkai:functionary-pt",
parallel_tool_calls: true,
max_tool_calls: 18,
store: true,
});
while (true) {
const toolCalls = response.output.filter(
(item): item is {
type: "function_call";
name: string;
call_id: string;
arguments: string;
} => item.type === "function_call" && item.name === "spawn_subagent",
);
if (toolCalls.length === 0) {
return response.outputText;
}
const toolOutputs = await Promise.all(
toolCalls.map(async (toolCall) => {
const args = JSON.parse(toolCall.arguments) as SpawnSubagentArgs;
const childResult = await runResearchChildWithContinuation(args);
return {
type: "function_call_output" as const,
call_id: toolCall.call_id,
output: JSON.stringify(childResult),
};
}),
);
response = await sdk.llm.responses.create({
model: response.model,
previous_response_id: response.id,
input: toolOutputs,
tools: [spawnSubagentTool],
parallel_tool_calls: true,
max_tool_calls: 18,
store: true,
});
}
}
Este é o núcleo do loop de pesquisa profunda:
- O pai cria um plano de pesquisa.
- O pai emite um lote de chamadas
spawn_subagent.
- Seu app executa todos os filhos em paralelo.
- Filhos fracos continuam para outra rodada.
- Seu app envia todos os memorandos finais dos filhos juntos.
- O pai lança outra rodada ou responde.
Transmita e registre o processo de pesquisa
A pesquisa profunda é muito mais fácil de depurar se você registrar o ciclo de vida das buscas dos filhos.
Logs úteis incluem:
- resposta pai criada
- cada tarefa delegada
- cada consulta de busca do filho
- cada lote de resultados de busca do filho
- cada prévia de memorando do filho
- quando um filho fraco é continuado para outra rodada
- retomada do pai com o lote final de filhos
Isso permite distinguir falhas de orquestração de falhas na qualidade da pesquisa.
Por exemplo, se o sistema responde mal mas os logs mostram apenas um filho com uma busca, isso é um problema de prompt ou de continuação, não de transporte.
Regras práticas para pesquisa profunda
- Use
parallel_tool_calls: true no pai para que ele possa lançar vários subagentes em um turno.
- Mantenha as saídas dos filhos compactas. O pai deve receber resumos de evidências, não dumps brutos de pesquisa.
- Prefira várias tarefas filhas focadas a uma tarefa filha vaga.
- Se um filho encontrar principalmente diretórios ou páginas genéricas, continue insistindo nesse filho em vez de aceitar o primeiro memorando.
- Não retome o pai cedo com apenas parte de um lote de filhos.
- Mantenha
store: true ativado durante o desenvolvimento para poder inspecionar as respostas do pai e dos filhos depois.
- Se você estiver agindo em nome de um usuário final, envie o mesmo valor de
X-On-Behalf-Of nas requisições do pai e dos filhos.
Armadilhas comuns
- Poucos subagentes: o pai sintetiza antes que a pesquisa tenha real abrangência.
- Filhos fracos: um filho retorna após uma busca fraca com “próximos passos” em vez de fazer mais buscas.
- Memorandos filhos grandes demais: o pai ganha pouco porque o filho retorna contexto bruto demais.
- Reunião antecipada: retomar o pai antes de todos os filhos de um lote terminarem torna o fluxo menos previsível.
- Deriva de qualidade de fonte: filhos podem usar demais diretórios, sites de perfil e agregadores, a menos que o prompt diga explicitamente para priorizar fontes primárias.
Veja também
Revise spawn subagents using the Responses API para o padrão geral de delegação pai/filho.
Revise generate a response para o formato básico de requisição de Responses.