Skip to content

Commit 1e4cd75

Browse files
committed
task_completed tool!
1 parent d5e4c5d commit 1e4cd75

File tree

11 files changed

+139
-6
lines changed

11 files changed

+139
-6
lines changed

.agents/types/tools.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type ToolName =
1717
| 'set_output'
1818
| 'spawn_agents'
1919
| 'str_replace'
20+
| 'task_completed'
2021
| 'think_deeply'
2122
| 'web_search'
2223
| 'write_file'
@@ -41,6 +42,7 @@ export interface ToolParamsMap {
4142
set_output: SetOutputParams
4243
spawn_agents: SpawnAgentsParams
4344
str_replace: StrReplaceParams
45+
task_completed: TaskCompletedParams
4446
think_deeply: ThinkDeeplyParams
4547
web_search: WebSearchParams
4648
write_file: WriteFileParams
@@ -193,6 +195,16 @@ export interface StrReplaceParams {
193195
}[]
194196
}
195197

198+
/**
199+
* Signal that the task is complete. Use this tool when:
200+
- The user's request is completely fulfilled
201+
- You need clarification from the user before continuing
202+
- You are stuck or need help from the user to continue
203+
204+
This tool explicitly marks the end of your work on the current task.
205+
*/
206+
export interface TaskCompletedParams {}
207+
196208
/**
197209
* Deeply consider complex tasks by brainstorming approaches and tradeoffs step-by-step.
198210
*/
@@ -227,7 +239,7 @@ export interface WriteFileParams {
227239
* Write a todo list to track tasks. Use this frequently to maintain a step-by-step plan.
228240
*/
229241
export interface WriteTodosParams {
230-
/** List of todos with their completion status */
242+
/** List of todos with their completion status. Try to order the todos the same way you will complete them. Do not mark todos as completed if you have not completed them yet! */
231243
todos: {
232244
/** Description of the task */
233245
task: string

common/src/templates/initial-agents-dir/types/tools.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export type ToolName =
1717
| 'set_output'
1818
| 'spawn_agents'
1919
| 'str_replace'
20+
| 'task_completed'
2021
| 'think_deeply'
2122
| 'web_search'
2223
| 'write_file'
@@ -41,6 +42,7 @@ export interface ToolParamsMap {
4142
set_output: SetOutputParams
4243
spawn_agents: SpawnAgentsParams
4344
str_replace: StrReplaceParams
45+
task_completed: TaskCompletedParams
4446
think_deeply: ThinkDeeplyParams
4547
web_search: WebSearchParams
4648
write_file: WriteFileParams
@@ -193,6 +195,16 @@ export interface StrReplaceParams {
193195
}[]
194196
}
195197

198+
/**
199+
* Signal that the task is complete. Use this tool when:
200+
- The user's request is completely fulfilled
201+
- You need clarification from the user before continuing
202+
- You are stuck or need help from the user to continue
203+
204+
This tool explicitly marks the end of your work on the current task.
205+
*/
206+
export interface TaskCompletedParams {}
207+
196208
/**
197209
* Deeply consider complex tasks by brainstorming approaches and tradeoffs step-by-step.
198210
*/
@@ -227,7 +239,7 @@ export interface WriteFileParams {
227239
* Write a todo list to track tasks. Use this frequently to maintain a step-by-step plan.
228240
*/
229241
export interface WriteTodosParams {
230-
/** List of todos with their completion status */
242+
/** List of todos with their completion status. Try to order the todos the same way you will complete them. Do not mark todos as completed if you have not completed them yet! */
231243
todos: {
232244
/** Description of the task */
233245
task: string

common/src/tools/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const TOOLS_WHICH_WONT_FORCE_NEXT_STEP = [
1414
'add_message',
1515
'update_subgoal',
1616
'create_plan',
17+
'task_completed',
1718
]
1819

1920
// List of all available tools
@@ -37,6 +38,7 @@ export const toolNames = [
3738
'spawn_agents',
3839
'spawn_agent_inline',
3940
'str_replace',
41+
'task_completed',
4042
'think_deeply',
4143
'update_subgoal',
4244
'web_search',
@@ -60,6 +62,7 @@ export const publishedTools = [
6062
'set_output',
6163
'spawn_agents',
6264
'str_replace',
65+
'task_completed',
6366
'think_deeply',
6467
'web_search',
6568
'write_file',

common/src/tools/list.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { setOutputParams } from './params/tool/set-output'
2020
import { spawnAgentInlineParams } from './params/tool/spawn-agent-inline'
2121
import { spawnAgentsParams } from './params/tool/spawn-agents'
2222
import { strReplaceParams } from './params/tool/str-replace'
23+
import { taskCompletedParams } from './params/tool/task-completed'
2324
import { thinkDeeplyParams } from './params/tool/think-deeply'
2425
import { updateSubgoalParams } from './params/tool/update-subgoal'
2526
import { webSearchParams } from './params/tool/web-search'
@@ -58,6 +59,7 @@ export const $toolParams = {
5859
spawn_agents: spawnAgentsParams,
5960
spawn_agent_inline: spawnAgentInlineParams,
6061
str_replace: strReplaceParams,
62+
task_completed: taskCompletedParams,
6163
think_deeply: thinkDeeplyParams,
6264
update_subgoal: updateSubgoalParams,
6365
web_search: webSearchParams,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import z from 'zod/v4'
2+
3+
import type { $ToolParams } from '../../constants'
4+
5+
const toolName = 'task_completed'
6+
const endsAgentStep = true
7+
export const taskCompletedParams = {
8+
toolName,
9+
endsAgentStep,
10+
parameters: z.object({}).describe(
11+
`Signal that the task is complete. Use this tool when:
12+
- The user's request is completely fulfilled
13+
- You need clarification from the user before continuing
14+
- You are stuck or need help from the user to continue
15+
16+
This tool explicitly marks the end of your work on the current task.`,
17+
),
18+
outputs: z.tuple([]),
19+
} satisfies $ToolParams

npm-app/src/utils/tool-renderers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,9 @@ export const toolRenderers: Record<ToolName, ToolCallRenderer> = {
117117
end_turn: {
118118
// Don't render anything
119119
},
120+
task_completed: {
121+
// Don't render anything
122+
},
120123
run_terminal_command: {
121124
// Don't render anything
122125
},

packages/agent-runtime/src/run-agent-step.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -383,10 +383,25 @@ export const runAgentStep = async (
383383
}
384384
}
385385

386-
let shouldEndTurn =
387-
toolCalls.some((call) => call.toolName === 'end_turn') ||
388-
hasNoToolResults ||
389-
hasOnlyFinishedTodos
386+
const hasTaskCompleted = toolCalls.some(
387+
(call) =>
388+
call.toolName === 'task_completed' || call.toolName === 'end_turn',
389+
)
390+
391+
// If the agent has the task_completed tool, it must be called to end its turn.
392+
const requiresExplicitCompletion =
393+
agentTemplate.toolNames.includes('task_completed')
394+
395+
let shouldEndTurn: boolean
396+
if (requiresExplicitCompletion) {
397+
// For models requiring explicit completion, only end turn when:
398+
// - task_completed is called, OR
399+
// - end_turn is called (backward compatibility)
400+
shouldEndTurn = hasTaskCompleted
401+
} else {
402+
// For other models, also end turn when there are no tool calls or only a call to finished todos
403+
shouldEndTurn = hasTaskCompleted || hasNoToolResults || hasOnlyFinishedTodos
404+
}
390405

391406
agentState = {
392407
...agentState,

packages/agent-runtime/src/tools/definitions/list.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { setOutputTool } from './tool/set-output'
1919
import { spawnAgentInlineTool } from './tool/spawn-agent-inline'
2020
import { spawnAgentsTool } from './tool/spawn-agents'
2121
import { strReplaceTool } from './tool/str-replace'
22+
import { taskCompletedTool } from './tool/task-completed'
2223
import { thinkDeeplyTool } from './tool/think-deeply'
2324
import { updateSubgoalTool } from './tool/update-subgoal'
2425
import { webSearchTool } from './tool/web-search'
@@ -49,6 +50,7 @@ const toolDescriptions = {
4950
spawn_agents: spawnAgentsTool,
5051
spawn_agent_inline: spawnAgentInlineTool,
5152
str_replace: strReplaceTool,
53+
task_completed: taskCompletedTool,
5254
think_deeply: thinkDeeplyTool,
5355
update_subgoal: updateSubgoalTool,
5456
web_search: webSearchTool,
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { getToolCallString } from '@codebuff/common/tools/utils'
2+
3+
import type { ToolDescription } from '../tool-def-type'
4+
5+
const toolName = 'task_completed'
6+
export const taskCompletedTool = {
7+
toolName,
8+
description: `
9+
Use this tool to signal that the task is complete.
10+
11+
- When to use:
12+
* The user's request is completely fulfilled and you have nothing more to do
13+
* You need clarification from the user before continuing
14+
* You need help from the user to continue (e.g., missing information, unclear requirements)
15+
* You've encountered a blocker that requires user intervention
16+
17+
- Before calling:
18+
* Ensure all pending work is finished
19+
* Resolve all tool results
20+
* Provide any outputs or summaries the user needs
21+
22+
- Effect: Signals completion of the current task and returns control to the user
23+
24+
*EXAMPLE USAGE*:
25+
26+
All changes have been implemented and tested successfully!
27+
28+
${getToolCallString(toolName, {})}
29+
30+
OR
31+
32+
I need more information to proceed. Which database schema should I use for this migration?
33+
34+
${getToolCallString(toolName, {})}
35+
36+
OR
37+
38+
I can't get the tests to pass after several different attempts. I need help from the user to proceed.
39+
40+
${getToolCallString(toolName, {})}
41+
42+
`.trim(),
43+
} satisfies ToolDescription

packages/agent-runtime/src/tools/handlers/list.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { handleSetOutput } from './tool/set-output'
1717
import { handleSpawnAgentInline } from './tool/spawn-agent-inline'
1818
import { handleSpawnAgents } from './tool/spawn-agents'
1919
import { handleStrReplace } from './tool/str-replace'
20+
import { handleTaskCompleted } from './tool/task-completed'
2021
import { handleThinkDeeply } from './tool/think-deeply'
2122
import { handleUpdateSubgoal } from './tool/update-subgoal'
2223
import { handleWebSearch } from './tool/web-search'
@@ -55,6 +56,7 @@ export const codebuffToolHandlers = {
5556
spawn_agents: handleSpawnAgents,
5657
spawn_agent_inline: handleSpawnAgentInline,
5758
str_replace: handleStrReplace,
59+
task_completed: handleTaskCompleted,
5860
think_deeply: handleThinkDeeply,
5961
update_subgoal: handleUpdateSubgoal,
6062
web_search: handleWebSearch,

0 commit comments

Comments
 (0)