Skip to content

Commit 56ed16e

Browse files
committed
Add think tool for complex reasoning
1 parent c9e7402 commit 56ed16e

File tree

4 files changed

+82
-0
lines changed

4 files changed

+82
-0
lines changed

packages/agent/src/tools/getTools.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { shellMessageTool } from './shell/shellMessage.js';
1919
import { shellStartTool } from './shell/shellStart.js';
2020
import { waitTool } from './sleep/wait.js';
2121
import { textEditorTool } from './textEditor/textEditor.js';
22+
import { thinkTool } from './think/think.js';
2223

2324
// Import these separately to avoid circular dependencies
2425

@@ -52,6 +53,7 @@ export function getTools(options?: GetToolsOptions): Tool[] {
5253
sessionMessageTool as unknown as Tool,
5354
listSessionsTool as unknown as Tool,
5455
waitTool as unknown as Tool,
56+
thinkTool as unknown as Tool,
5557
];
5658

5759
// Add agent tools based on the configured mode
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './think.js';
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { getMockToolContext } from '../getTools.test.js';
4+
5+
import { thinkTool } from './think.js';
6+
7+
describe('thinkTool', () => {
8+
const mockContext = getMockToolContext();
9+
10+
it('should have the correct name and description', () => {
11+
expect(thinkTool.name).toBe('think');
12+
expect(thinkTool.description).toContain(
13+
'Use the tool to think about something',
14+
);
15+
});
16+
17+
it('should return the thought that was provided', async () => {
18+
const thought =
19+
'I need to consider all possible solutions before deciding on an approach.';
20+
const result = await thinkTool.execute({ thought }, mockContext);
21+
22+
expect(result).toEqual({ thought });
23+
});
24+
25+
it('should accept any string as a thought', async () => {
26+
const thoughts = [
27+
'Simple thought',
28+
'Complex thought with multiple steps:\n1. First consider X\n2. Then Y\n3. Finally Z',
29+
'A question to myself: what if we tried a different approach?',
30+
];
31+
32+
for (const thought of thoughts) {
33+
const result = await thinkTool.execute({ thought }, mockContext);
34+
expect(result).toEqual({ thought });
35+
}
36+
});
37+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { z } from 'zod';
2+
3+
/**
4+
* Schema for the think tool parameters
5+
*/
6+
const parameters = z.object({
7+
thought: z.string().describe('A thought to think about.'),
8+
});
9+
10+
/**
11+
* Schema for the think tool returns
12+
*/
13+
const returns = z.object({
14+
thought: z.string().describe('The thought that was processed.'),
15+
});
16+
17+
/**
18+
* Think tool implementation
19+
*
20+
* This tool allows the agent to explicitly think through a complex problem
21+
* without taking any external actions. It serves as a way to document the
22+
* agent's reasoning process and can improve problem-solving abilities.
23+
*
24+
* Based on research from Anthropic showing how a simple "think" tool can
25+
* improve Claude's problem-solving skills.
26+
*/
27+
export const thinkTool = {
28+
name: 'think',
29+
description:
30+
'Use the tool to think about something. It will not obtain new information or change any state, but just helps with complex reasoning.',
31+
parameters,
32+
returns,
33+
execute: async ({ thought }, { logger }) => {
34+
// Log the thought process
35+
logger.log(`Thinking: ${thought}`);
36+
37+
// Simply return the thought - no side effects
38+
return {
39+
thought,
40+
};
41+
},
42+
};

0 commit comments

Comments
 (0)