From 70bb710715408d06b7b63128f7b01625c38e73e9 Mon Sep 17 00:00:00 2001
From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Date: Thu, 4 Jun 2026 00:44:00 -0500
Subject: [PATCH] refactor(opencode): clean up task tool prompts (#30687)
---
packages/opencode/src/tool/task.ts | 90 +++++++++++++----------------
packages/opencode/src/tool/task.txt | 11 ++--
2 files changed, 46 insertions(+), 55 deletions(-)
diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts
index ca80d113c..041a56571 100644
--- a/packages/opencode/src/tool/task.ts
+++ b/packages/opencode/src/tool/task.ts
@@ -23,14 +23,20 @@ export interface TaskPromptOps {
const id = "task"
const BACKGROUND_DESCRIPTION = [
- "",
- "",
- [
- "Background mode: background=true launches the subagent asynchronously and returns immediately.",
- "Foreground is the default; use it when you need the result before continuing.",
- "Use background only for independent work that can run while you continue elsewhere.",
- "You will be notified automatically when it finishes.",
- ].join(" "),
+ "Background mode: background=true launches the subagent asynchronously and returns immediately.",
+ "Foreground is the default; use it when you need the result before continuing.",
+ "Use background only for independent work that can run while you continue elsewhere.",
+ "You will be notified automatically when it finishes.",
+].join(" ")
+const BACKGROUND_STARTED = [
+ "Background task started. You will be notified automatically when it finishes.",
+ "Do not poll for progress, ask the task for status, or duplicate its work by investigating the same files or topic yourself.",
+ "Continue only with non-overlapping work, or briefly tell the user what you launched and stop.",
+].join("\n")
+const BACKGROUND_UPDATED = [
+ "Additional context sent to the running background task.",
+ "The task is still running; wait for the automatic completion notification.",
+ "Do not poll for progress or duplicate its work.",
].join("\n")
const BaseParameterFields = {
@@ -53,47 +59,16 @@ export const Parameters = Schema.Struct({
}),
})
-function output(sessionID: SessionID, text: string) {
- return [``, "", text, "", ""].join("\n")
-}
-
-function backgroundOutput(sessionID: SessionID) {
- return [
- ``,
- "Background task started",
- "",
- "Background task started. You will be notified automatically when it finishes; do not poll for progress.",
- "Do not duplicate its work. Continue only with non-overlapping work, or stop if there is nothing else useful to do.",
- "",
- "",
- ].join("\n")
-}
-
-function backgroundUpdateOutput(sessionID: SessionID) {
- return [
- ``,
- "Background task updated",
- "",
- "Additional context sent to the background task.",
- "",
- "",
- ].join("\n")
-}
-
-function backgroundMessage(input: {
+function renderOutput(input: {
sessionID: SessionID
- description: string
- state: "completed" | "error"
+ state: "running" | "completed" | "error"
+ summary?: string
text: string
}) {
- const tag = input.state === "completed" ? "task_result" : "task_error"
- const title =
- input.state === "completed"
- ? `Background task completed: ${input.description}`
- : `Background task failed: ${input.description}`
+ const tag = input.state === "error" ? "task_error" : "task_result"
return [
``,
- `${title}`,
+ ...(input.summary ? [`${input.summary}`] : []),
`<${tag}>`,
input.text,
`${tag}>`,
@@ -228,10 +203,13 @@ export const TaskTool = Tool.define(
{
type: "text",
synthetic: true,
- text: backgroundMessage({
+ text: renderOutput({
sessionID: nextSession.id,
- description: params.description,
state,
+ summary:
+ state === "completed"
+ ? `Background task completed: ${params.description}`
+ : `Background task failed: ${params.description}`,
text,
}),
},
@@ -248,7 +226,12 @@ export const TaskTool = Tool.define(
background: true,
jobId: nextSession.id,
},
- output: backgroundUpdateOutput(nextSession.id),
+ output: renderOutput({
+ sessionID: nextSession.id,
+ state: "running",
+ summary: "Background task updated",
+ text: BACKGROUND_UPDATED,
+ }),
}
}
@@ -275,7 +258,12 @@ export const TaskTool = Tool.define(
...metadata,
jobId: info.id,
},
- output: backgroundOutput(nextSession.id),
+ output: renderOutput({
+ sessionID: nextSession.id,
+ state: "running",
+ summary: "Background task started",
+ text: BACKGROUND_STARTED,
+ }),
}
}
@@ -296,7 +284,7 @@ export const TaskTool = Tool.define(
return {
title: params.description,
metadata,
- output: output(nextSession.id, text),
+ output: renderOutput({ sessionID: nextSession.id, state: "completed", text }),
}
}),
(_, exit) =>
@@ -313,7 +301,9 @@ export const TaskTool = Tool.define(
})
return {
- description: flags.experimentalBackgroundSubagents ? DESCRIPTION + BACKGROUND_DESCRIPTION : DESCRIPTION,
+ description: flags.experimentalBackgroundSubagents
+ ? [DESCRIPTION, BACKGROUND_DESCRIPTION].join("\n\n")
+ : DESCRIPTION,
parameters: Parameters,
jsonSchema: flags.experimentalBackgroundSubagents ? undefined : ToolJsonSchema.fromSchema(BaseParameters),
execute: (params: Schema.Schema.Type, ctx: Tool.Context) =>
diff --git a/packages/opencode/src/tool/task.txt b/packages/opencode/src/tool/task.txt
index e2ac60500..b14fb886e 100644
--- a/packages/opencode/src/tool/task.txt
+++ b/packages/opencode/src/tool/task.txt
@@ -11,8 +11,9 @@ When NOT to use the Task tool:
Usage notes:
1. Launch multiple agents concurrently whenever possible, to maximize performance; to do that, use a single message with multiple tool uses
-2. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result. The output includes a task_id you can reuse later to continue the same subagent session.
-3. Each agent invocation starts with a fresh context unless you provide task_id to resume the same subagent session (which continues with its previous messages and tool outputs). When starting fresh, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.
-4. The agent's outputs should generally be trusted
-5. Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent. Tell it how to verify its work if possible (e.g., relevant test commands).
-6. If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.
+2. Once you have delegated work to an agent, do not duplicate that work yourself. Continue with non-overlapping tasks, or wait for the result.
+3. When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result. The output includes a task_id you can reuse later to continue the same subagent session.
+4. Each agent invocation starts with a fresh context unless you provide task_id to resume the same subagent session (which continues with its previous messages and tool outputs). When starting fresh, your prompt should contain a highly detailed task description for the agent to perform autonomously and you should specify exactly what information the agent should return back to you in its final and only message to you.
+5. The agent's outputs should generally be trusted
+6. Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.), since it is not aware of the user's intent. Tell it how to verify its work if possible (e.g., relevant test commands).
+7. If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.