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 você quiser que uma resposta divida o trabalho em tarefas menores.
Este padrão implementa um loop síncrono de delegação de respostas filhas.
Uma resposta pai chama uma ferramenta de função que seu aplicativo resolve executando outra solicitação de Responses.
Um ou vários resultados filhos são retornados ao pai como function_call_output, e o pai continua a geração.
Uma resposta filha às vezes é chamada de subagente.
Neste guia, é apenas outra solicitação de Responses que executa uma tarefa focada.
Resposta pai
-> function_call spawn_subagent
-> seu aplicativo executa uma ou mais respostas filhas
-> resultados filhos retornados como function_call_output
-> resposta pai retoma a geração
Como o loop funciona
Neste padrão, a resposta pai pausa sempre que chama spawn_subagent.
Seu aplicativo executa as tarefas delegadas e depois retoma o pai com os resultados.
- Crie uma resposta pai com uma ferramenta de função
spawn_subagent.
- Quando o modelo chamar a ferramenta, analise os argumentos de cada chamada de ferramenta.
- Execute uma ou mais solicitações de Responses filhas para realizar as tarefas delegadas.
- Aguarde todas as respostas filhas terminarem.
- Retorne cada resultado filho como
function_call_output usando o call_id correspondente.
- Retome a resposta pai com
previous_response_id.
- Repita até que o pai produza uma
message normal do assistente.
Defina uma ferramenta para delegação
Mantenha a ferramenta focada.
Passe apenas os campos que a resposta filha precisa.
{
"type": "function",
"name": "spawn_subagent",
"description": "Delegue uma tarefa focada para uma resposta filha e retorne o resultado.",
"strict": true,
"parameters": {
"type": "object",
"properties": {
"task": {
"type": "string",
"description": "A tarefa para a resposta filha."
},
"instructions": {
"type": "string",
"description": "Instruções opcionais para a resposta filha."
},
"model": {
"type": "string",
"description": "Substituição de modelo opcional para a resposta filha."
}
},
"required": ["task"],
"additionalProperties": false
}
}
Use tool_choice: "auto" quando o modelo deve decidir quando delegar.
Use tool_choice: "required" quando toda rodada deve passar por uma ferramenta.
Receita do SDK TypeScript
Este exemplo usa sdk.llm.responses.create tanto para as respostas pai quanto para as filhas.
Ele permite que o pai emita múltiplas chamadas spawn_subagent em uma rodada.
Seu aplicativo executa essas respostas filhas em paralelo, aguarda todas terminarem e então retoma o pai uma vez com todos os resultados das ferramentas.
Mantenha cada resultado filho pequeno para que o pai possa usá-lo na próxima rodada sem consumir muito contexto.
import { SDK } from "@meetkai/mka1";
const sdk = new SDK({
bearerAuth: process.env.MKA1_API_KEY!,
});
const spawnSubagentTool = {
type: "function" as const,
name: "spawn_subagent",
description: "Delegue uma tarefa focada para uma resposta filha e retorne o resultado.",
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;
};
async function runChildResponse(args: SpawnSubagentArgs) {
const child = await sdk.llm.responses.create({
model: args.model ?? "meetkai:functionary-pt",
instructions:
args.instructions ??
"Você é um assistente especialista. Complete a tarefa e retorne apenas o resultado.",
input: args.task,
store: true,
});
return {
response_id: child.id,
output_text: child.outputText,
};
}
export async function runDelegatingAgent(input: string) {
let response = await sdk.llm.responses.create({
model: "meetkai:functionary-pt",
instructions:
"Você é um orquestrador. Use spawn_subagent para tarefas paralelas e focadas. Você pode chamá-lo várias vezes em uma rodada quando as tarefas puderem ser paralelizadas. Após todos os resultados das ferramentas retornarem, responda ao usuário diretamente.",
input,
tools: [spawnSubagentTool],
tool_choice: "meetkai:functionary-pt",
parallel_tool_calls: true,
max_tool_calls: 8,
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 runChildResponse(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: 8,
store: true,
});
}
}
Distribua e aguarde todas as respostas filhas
Quando parallel_tool_calls é true, o pai pode emitir vários itens function_call em uma rodada.
Trate esse conjunto de chamadas de ferramentas como um lote.
Inicie todas as respostas filhas, aguarde todas terminarem e só então retome o pai.
Isso cria uma barreira:
- A resposta pai emite vários itens
function_call.
- Seu aplicativo inicia várias respostas filhas.
- Seu aplicativo aguarda todas as respostas filhas serem concluídas.
- Seu aplicativo envia todos os itens
function_call_output de volta em uma solicitação de acompanhamento.
- A resposta pai continua com o conjunto completo de resultados delegados.
Se você retomar o pai cedo com apenas parte do lote, o modelo continua sem os resultados ausentes.
Isso geralmente torna a orquestração menos previsível.
O passo chave de junção (fan-in) é assim:
const toolOutputs = await Promise.all(
toolCalls.map(async (toolCall) => {
const args = JSON.parse(toolCall.arguments) as SpawnSubagentArgs;
const childResult = await runChildResponse(args);
return {
type: "function_call_output" as const,
call_id: toolCall.call_id,
output: JSON.stringify(childResult),
};
}),
);
Se seu aplicativo age em nome de um usuário final, envie o mesmo valor de X-On-Behalf-Of nas solicitações pai e filhas.
Se uma resposta filha puder demorar mais, você pode definir background: true na solicitação filha e fazer polling com sdk.llm.responses.get até que ela seja concluída.
Quando você distribuir para várias respostas filhas, aguarde até que todos os resultados estejam disponíveis antes de retomar a resposta pai.
Solicitação bruta de Responses para o passo de retomada
A transferência crítica é a solicitação de acompanhamento.
Você passa todos os resultados das ferramentas em input e aponta para a rodada anterior do pai com previous_response_id.
curl https://apigw.mka1.com/api/v1/llm/responses \
--request POST \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer <mka1-api-key>' \
--header 'X-On-Behalf-Of: <end-user-id>' \
--data '{
"model": "meetkai:functionary-pt",
"previous_response_id": "resp_parent123",
"input": [
{
"type": "function_call_output",
"call_id": "call_abc123",
"output": "{\"response_id\":\"resp_child456\",\"output_text\":\"Pesquisa concluída. Recomendo uma implementação em etapas.\"}"
},
{
"type": "function_call_output",
"call_id": "call_def456",
"output": "{\"response_id\":\"resp_child789\",\"output_text\":\"Rascunho concluído. Manchete: Implementação mais rápida com menor risco.\"}"
}
]
}'
Se você não estiver agindo em nome de um usuário final, omita X-On-Behalf-Of.
Tratamento básico de erros e recuperação
Em sistemas reais, esse loop falhará às vezes.
Falhas comuns incluem argumentos de ferramentas malformados, timeouts em solicitações filhas, erros 5xx ascendentes, limites de taxa e saídas filhas muito fracas para serem úteis.
O padrão mais seguro é:
- Analise os argumentos das ferramentas de forma defensiva.
- Retente falhas transitórias de solicitações filhas algumas vezes com backoff.
- Retorne um payload estruturado de falha ao pai em vez de travar todo o lote quando uma filha falhar.
- Mantenha os resultados das filhas pequenos e explícitos para que o pai possa decidir se continua, retenta ou responde com resultados parciais.
Uma abordagem simples é envolver a execução da filha e sempre retornar um objeto de sucesso ou de erro:
type ChildSuccess = {
ok: true;
response_id: string;
output_text: string;
};
type ChildFailure = {
ok: false;
error_code: "invalid_arguments" | "child_request_failed";
message: string;
};
type ChildResult = ChildSuccess | ChildFailure;
function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function runChildResponseWithRecovery(rawArgs: string): Promise<ChildResult> {
let args: SpawnSubagentArgs;
try {
args = JSON.parse(rawArgs) as SpawnSubagentArgs;
if (!args.task || typeof args.task !== "string") {
return {
ok: false,
error_code: "invalid_arguments",
message: "spawn_subagent requer uma tarefa do tipo string",
};
}
} catch {
return {
ok: false,
error_code: "invalid_arguments",
message: "Não foi possível analisar os argumentos de spawn_subagent como JSON",
};
}
for (let attempt = 0; attempt < 3; attempt += 1) {
try {
const child = await sdk.llm.responses.create({
model: args.model ?? "meetkai:functionary-pt",
instructions:
args.instructions ??
"Você é um assistente especialista. Complete a tarefa e retorne apenas o resultado.",
input: args.task,
store: true,
});
return {
ok: true,
response_id: child.id,
output_text: child.outputText,
};
} catch (error) {
const isLastAttempt = attempt === 2;
if (isLastAttempt) {
return {
ok: false,
error_code: "child_request_failed",
message:
error instanceof Error ? error.message : "Falha na resposta filha",
};
}
await sleep(500 * (attempt + 1));
}
}
return {
ok: false,
error_code: "child_request_failed",
message: "Falha na resposta filha",
};
}
Depois, envie os resultados de volta ao pai mesmo que algumas filhas falhem:
const toolOutputs = await Promise.all(
toolCalls.map(async (toolCall) => {
const childResult = await runChildResponseWithRecovery(toolCall.arguments);
return {
type: "function_call_output" as const,
call_id: toolCall.call_id,
output: JSON.stringify(childResult),
};
}),
);
Isso permite que o pai veja falhas parciais e continue o raciocínio.
Por exemplo, o pai pode decidir tentar novamente com uma tarefa mais restrita, lançar um subagente substituto ou responder com os resultados filhos bem-sucedidos disponíveis enquanto observa a lacuna.
Para filhas de longa duração, você também pode combinar isso com background: true mais polling.
A lógica de recuperação permanece a mesma: aguarde a filha atingir um estado terminal, depois retorne um payload de sucesso ou um payload estruturado de falha ao pai.
Limites práticos
- Mantenha
parallel_tool_calls definido como true quando o pai deve poder delegar várias respostas filhas em uma rodada.
- Defina
parallel_tool_calls como false apenas quando as respostas filhas compartilharem estado ou precisarem ser executadas em ordem.
- Defina
max_tool_calls para que uma resposta pai não possa entrar em loop infinito.
- Mantenha as saídas das filhas compactas para que o pai possa incorporar o resultado sem consumir muito contexto.
- Mantenha
store: true enquanto constrói o fluxo de trabalho para poder inspecionar respostas pai e filhas depois.
- Use a página de itens de entrada de Responses na Referência da API quando precisar depurar os itens exatos enviados de volta ao modelo.
Veja também
Revise realizando pesquisas profundas com subagentes para uma implementação concreta orientada a pesquisa deste padrão.
Revise gerar uma resposta para o padrão básico de solicitação de Responses.
Use gerenciar conversas quando quiser que o fluxo de trabalho pai ou filho mantenha estado durável fora de uma única cadeia de respostas.