This commit is contained in:
seb
2026-10-18 14:29:01 +02:00
parent badce6819c
commit d0a2ede749
4 changed files with 16 additions and 14 deletions

2
mcp.md
View File

@@ -208,7 +208,7 @@ server.registerTool('dash-subagent', {
task: z.string().describe('Specific instructions and goal for the subagent.'),
skills: z.array(z.string()).nullable().optional().describe('Array of SKILL names or slugs to inject.'),
conversation_id: z.number().int().positive().nullable().optional().describe('Existing subagent conversation ID to follow up on, or null to create a new one.'),
max_iterations: z.number().int().min(1).max(30).nullable().optional().describe('Safety bound on tool loops (default 15, max 30).'),
max_iterations: z.number().int().min(10).max(50).nullable().optional().describe('Safety bound on tool loops (min 10, default 20, max 50).'),
model: z.string().nullable().optional().describe('Optional OpenRouter model override.'),
note: z.string().nullable().optional(),
},

View File

@@ -189,7 +189,7 @@ function createDashbackMcpServer({ user }) {
task: z.string().describe(TOOL_PARAMETER_DESCRIPTIONS.subagent?.task || 'Specific instructions and goal for the subagent.'),
skills: z.array(z.string()).nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.subagent?.skills || 'Array of SKILL names or slugs to inject into the subagent prompt.'),
conversation_id: z.number().int().positive().nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.subagent?.conversation_id || 'Existing subagent conversation ID to follow up on, or null to create a new one.'),
max_iterations: z.number().int().min(1).max(30).nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.subagent?.max_iterations || 'Safety bound on tool loops (default 15, max 30).'),
max_iterations: z.number().int().min(10).max(50).nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.subagent?.max_iterations || 'Safety bound on tool loops (min 10, default 20, max 50).'),
model: z.string().nullable().optional().describe('Optional OpenRouter model override. Defaults to company default model.'),
note: z.string().nullable().optional().describe(TOOL_PARAMETER_DESCRIPTIONS.subagent?.note || 'Status message shown during execution.'),
},

View File

@@ -259,7 +259,7 @@ export const TOOL_PARAMETER_DESCRIPTIONS = {
task: 'Specific instructions and goal for the subagent.',
skills: 'Array of SKILLs (e.g. ["api-article.SKILL", "label.SKILL"]) to inject directly into the subagent system prompt.',
conversation_id: 'Existing subagent conversation ID to follow up on, or null to create a new one.',
max_iterations: 'Safety bound on tool loops (default 15, max 30).',
max_iterations: 'Safety bound on tool loops (min 10, default 20, max 50).',
},
draft_delivery_manifest: {

View File

@@ -40,19 +40,21 @@ import { createDraftDeliveryManifestTool } from './draft-delivery-manifest.js';
* stays in the subagent's conversation.
*/
// #region Constants
const DEFAULT_MAX_ITERATIONS = 15;
const MAX_ITERATIONS_LIMIT = 30;
const MIN_ITERATIONS_LIMIT = 10;
const DEFAULT_MAX_ITERATIONS = 20;
const MAX_ITERATIONS_LIMIT = 50;
/** Subagents never spawn subagents: the parent runs at depth 0, its child at depth 1. */
const MAX_SUBAGENT_DEPTH = 1;
const SUBAGENT_PROVIDER = 'openrouter';
const SUBAGENT_PROMPT_NOTICE = [
function buildSubagentPromptNotice(maxIterations) {
return [
'SUBAGENT MODE:',
'- You are a subagent working for a primary agent, not talking to the end user. You cannot ask the user questions.',
`- You have a strict limit of ${maxIterations} iterations for this task. Budget your tool calls efficiently to finish and return your final answer within this limit.`,
'- Finish with a concise, self-contained final answer: what was done, key findings, and any file paths or IDs the primary agent needs.',
].join('\n');
].join('\n');
}
// #endregion
@@ -242,7 +244,7 @@ export function createSubagentTool({ googleAuthId, companyId, conversationId: pa
if (!Number.isInteger(iterationLimit) || iterationLimit < 1) {
throw new ToolError(`"max_iterations" must be a positive integer (received ${maxIterations}).`);
}
const boundedIterations = Math.min(iterationLimit, MAX_ITERATIONS_LIMIT);
const boundedIterations = Math.max(MIN_ITERATIONS_LIMIT, Math.min(iterationLimit, MAX_ITERATIONS_LIMIT));
const vfsRoot = await prepareVfs({ googleAuthId });
const injectedSkills = buildInjectedSkillsBlock(vfsRoot, skills);
@@ -291,7 +293,7 @@ export function createSubagentTool({ googleAuthId, companyId, conversationId: pa
const fullHistory = await db.listMessages(googleAuthId, subagentConversationId);
const systemPrompt = [
await buildSystemPrompt(vfsRoot, googleAuthId),
SUBAGENT_PROMPT_NOTICE,
buildSubagentPromptNotice(boundedIterations),
injectedSkills,
].filter(Boolean).join('\n\n');