From 899f201f2d6ce56748e8d42be1bf222d5c44fcaf Mon Sep 17 00:00:00 2001 From: can1357 Date: Wed, 28 Jan 2026 04:00:32 +0100 Subject: [PATCH] refactor(coding-agent): renamed output parameter to schema and restructured task metadata format - Renamed 'output' parameter to 'schema' throughout task configuration and documentation for clarity. - Updated task schema definition to use 'schema' field with improved description clarifying it defines expected response structure. - Restructured task summary output format to consolidate metadata into tag attributes and simplify XML structure. - Added truncation detection for task output exceeding 5000 character threshold with truncated flag. - Removed charCount from task metadata, retaining only lineCount and charSize properties. --- .../src/commit/agentic/tools/analyze-file.ts | 2 +- .../src/prompts/tools/task-summary.md | 22 +++++++++---------- .../coding-agent/src/prompts/tools/task.md | 14 +++++++----- packages/coding-agent/src/task/index.ts | 6 +++-- packages/coding-agent/src/task/types.ts | 4 ++-- 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/packages/coding-agent/src/commit/agentic/tools/analyze-file.ts b/packages/coding-agent/src/commit/agentic/tools/analyze-file.ts index 713a1bde5..09635591a 100644 --- a/packages/coding-agent/src/commit/agentic/tools/analyze-file.ts +++ b/packages/coding-agent/src/commit/agentic/tools/analyze-file.ts @@ -82,7 +82,7 @@ export function createAnalyzeFileTool(options: { const taskParams: TaskParams = { agent: "quick_task", context, - output: analyzeFileOutputSchema, + schema: analyzeFileOutputSchema, tasks, }; return taskTool.execute(toolCallId, taskParams, signal, onUpdate); diff --git a/packages/coding-agent/src/prompts/tools/task-summary.md b/packages/coding-agent/src/prompts/tools/task-summary.md index 34c100fa2..e81743aad 100644 --- a/packages/coding-agent/src/prompts/tools/task-summary.md +++ b/packages/coding-agent/src/prompts/tools/task-summary.md @@ -2,28 +2,28 @@
{{successCount}}/{{totalCount}} succeeded{{#if hasCancelledNote}} ({{cancelledCount}} cancelled){{/if}} [{{duration}}]
{{#each summaries}} - -{{agent}} + {{status}} -{{#if meta}}{{/if}} -{{id}} - +{{#if meta}}{{/if}} +{{#if truncated}} + {{preview}} +{{else}} + +{{preview}} - +{{/if}} + {{#unless @last}} --- {{/unless}} {{/each}} -{{#if (len outputIds)}} -Use read with agent:// for full logs: {{join outputIds ", "}} -{{/if}} {{#if schemaOverridden}} -Note: Agent '{{agentName}}' has a fixed output schema; your 'output' parameter was ignored. -Required schema: {{requiredSchema}} +Note: Agent '{{agentName}}' has a fixed output schema: +{{requiredSchema}} {{/if}} diff --git a/packages/coding-agent/src/prompts/tools/task.md b/packages/coding-agent/src/prompts/tools/task.md index f8e9af557..76a3f1caa 100644 --- a/packages/coding-agent/src/prompts/tools/task.md +++ b/packages/coding-agent/src/prompts/tools/task.md @@ -14,7 +14,8 @@ Use a single Task call with multiple `tasks` entries when parallelizing. Multipl For code changes, have subagents write files directly with Edit/Write. Do not ask them to return patches for you to apply. -Agents with `output="structured"` enforce their own schema; the `output` parameter is ignored for those agents. +Agents with `output="structured"` enforce their own schema; the `schema` parameter is ignored for those agents. +**Never describe expected output in `context` or task descriptions.** All response format requirements go in the `schema` parameter. Use structured schemas with typed properties—not `{ "type": "string" }`. Prose like "respond as a bullet list" is prohibited. @@ -29,9 +30,9 @@ Agents with `output="structured"` enforce their own schema; the `output` paramet This matters. Be thorough. 1. Plan before acting. Define the goal, acceptance criteria, and scope per task. -2. Put shared constraints and decisions in `context`; keep each task request short and unambiguous. +2. Put shared constraints and decisions in `context`; keep each task request short and unambiguous. **Do not describe response format here.** 3. State whether each task is research-only or should modify files. -4. Provide an `output` schema whenever possible. Do not repeat the schema in `context`; the agent does not need it there. +4. **Always provide a `schema`** with typed properties. Avoid `{ "type": "string" }`—if data has any structure (list, fields, categories), model it. Plain text is almost never the right choice. 5. Assign distinct file scopes per task to avoid conflicts. 6. Trust the returned data, then verify with tools when correctness matters. @@ -45,14 +46,14 @@ This matters. Be thorough. - `description`: Short human-readable description of what the task does - `args`: Object with keys matching `\{{placeholders}}` in context (always include this, even if empty) - `skills`: (optional) Array of skill names to preload into this task's system prompt. When set, the skills index section is omitted and the full SKILL.md contents are embedded. -- `output`: (optional) JTD schema for structured subagent output (used by the submit_result tool). Do not duplicate this schema in `context`. +- `schema`: JTD schema defining expected response structure. **Required.** Use objects with typed properties—e.g., `{ "properties": { "items": { "elements": { "type": "string" } } } }` for lists. Returns task results for each spawned agent: - Truncated preview of agent output (use `read agent://` for full content if truncated) - Summary with line/character counts -- For agents with `output` schema: structured JSON accessible via `agent://?q=` or `agent:///` +- For agents with `schema`: structured JSON accessible via `agent://?q=` or `agent:///` Results are keyed by task `id` (e.g., "AuthProvider", "AuthApi"). @@ -64,7 +65,7 @@ assistant: Uses the Task tool: { "agent": "task", "context": "Refactoring the auth module into separate concerns.\n\nPlan:\n1. AuthProvider - Extract React context and provider from src/auth/index.tsx\n2. AuthApi - Extract API calls to src/auth/api.ts, use existing fetchJson helper\n3. AuthTypes - Move types to types.ts, re-export from index\n\nConstraints:\n- Preserve all existing exports from src/auth/index.tsx\n- Use project's fetchJson (src/utils/http.ts), don't use raw fetch\n- No new dependencies\n\nTask: \{{step}}\n\nFiles: \{{files}}", - "output": { + "schema": { "properties": { "summary": { "type": "string" }, "decisions": { "elements": { "type": "string" } }, @@ -80,6 +81,7 @@ assistant: Uses the Task tool: +- Describing response format in `context` (e.g., "respond as JSON", "return a bullet list")—use `schema` parameter instead - Confirmation bias: ask for factual discovery instead of yes/no exploration prompts - Reading a specific file path → Use Read tool instead - Finding files by pattern/name → Use Find tool instead diff --git a/packages/coding-agent/src/task/index.ts b/packages/coding-agent/src/task/index.ts index e6b34457b..10c63dd2b 100644 --- a/packages/coding-agent/src/task/index.ts +++ b/packages/coding-agent/src/task/index.ts @@ -162,7 +162,7 @@ export class TaskTool implements AgentTool> { const startTime = Date.now(); const { agents, projectAgentsDir } = await discoverAgents(this.session.cwd); - const { agent: agentName, context, output: outputSchema, isolated } = params; + const { agent: agentName, context, schema: outputSchema, isolated } = params; const isIsolated = isolated === true; const isDefaultModelAlias = (value: string | string[] | undefined): boolean => { @@ -704,20 +704,22 @@ export class TaskTool implements AgentTool fullOutputThreshold) { const slice = output.slice(0, fullOutputThreshold); const lastNewline = slice.lastIndexOf("\n"); preview = lastNewline >= 0 ? slice.slice(0, lastNewline) : slice; + truncated = true; } return { agent: r.agent, status, id: r.id, preview, + truncated, meta: r.outputMeta ? { lineCount: r.outputMeta.lineCount, - charCount: r.outputMeta.charCount, charSize: formatBytes(r.outputMeta.charCount), } : undefined, diff --git a/packages/coding-agent/src/task/types.ts b/packages/coding-agent/src/task/types.ts index 35b064349..18f8ef7fe 100644 --- a/packages/coding-agent/src/task/types.ts +++ b/packages/coding-agent/src/task/types.ts @@ -63,8 +63,8 @@ export const taskSchema = Type.Object({ agent: Type.String({ description: "Agent type for all tasks" }), context: Type.String({ description: "Template with {{placeholders}} for args" }), isolated: Type.Optional(Type.Boolean({ description: "Run in isolated git worktree" })), - output: Type.Optional( - Type.Record(Type.String(), Type.Unknown(), { description: "JTD schema for structured output" }), + schema: Type.Optional( + Type.Record(Type.String(), Type.Unknown(), { description: "JTD schema defining expected response structure" }), ), tasks: Type.Array(taskItemSchema, { description: "Tasks to run in parallel", maxItems: MAX_PARALLEL_TASKS }), });