From 933831b19adf27321010d61cabe599d42aaf07d3 Mon Sep 17 00:00:00 2001 From: tjdoomer Date: Thu, 2 Apr 2026 17:48:11 +1100 Subject: [PATCH 1/2] docs: add roadmap for think/plan tool No-op reasoning tool that forces structured deliberation before acting. Highest impact-to-effort ratio for local model workflows. --- docs/roadmap/07-think-tool.md | 99 +++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 docs/roadmap/07-think-tool.md diff --git a/docs/roadmap/07-think-tool.md b/docs/roadmap/07-think-tool.md new file mode 100644 index 00000000000..b145e917f87 --- /dev/null +++ b/docs/roadmap/07-think-tool.md @@ -0,0 +1,99 @@ +# Think / Plan Tool + +## Branch: `feature/think-tool` + +## Problem + +Local models (7B-32B running on LM Studio) make impulsive tool calls — they +jump straight to editing without understanding the problem. Larger API models +do this too but less often. There's no mechanism to force structured reasoning +before acting. + +Delta has `Kind.Think` in its enum but no actual tool backing it. + +## What it is + +A no-op tool that accepts the model's reasoning and returns it back into context. +No side effects. The model calls it to think before it acts. + +``` +Model → think({ reasoning: "The user wants X. I see files A, B, C are involved. + The dependency chain is A→B→C. I should modify B first because..." }) +← Returns the same text back into context +``` + +## Why it works + +Research on process reward models shows that models which checkpoint reasoning +mid-task make fewer cascading errors. For weaker models this is even more +pronounced — a 7B model that plans before acting outperforms the same model +that jumps straight to edits. + +## Implementation + +### Tool declaration + +```typescript +{ + name: 'think', + description: 'Use this tool to plan your approach before taking action. ' + + 'Write out your reasoning about the problem, what files are involved, ' + + 'what changes are needed, and in what order. This helps you avoid ' + + 'mistakes by thinking before acting. The output is returned to you ' + + 'for reference — no side effects occur.', + parameters: { + type: 'object', + properties: { + reasoning: { + type: 'string', + description: 'Your structured reasoning about the current task.', + }, + }, + required: ['reasoning'], + }, +} +``` + +### Tool implementation + +```typescript +// The entire tool is ~10 lines +async execute({ reasoning }: { reasoning: string }): Promise { + return reasoning; +} +``` + +### System prompt integration + +Add to the system prompt for weaker models (configurable): + +> Before making changes to code, use the `think` tool to plan your approach. +> Outline which files need to change, in what order, and why. This is +> especially important for multi-file changes. + +### Optional: structured think mode + +For models that support it, enforce a schema: + +```typescript +{ + goal: string; + files_involved: string[]; + steps: string[]; + risks: string[]; + current_step: number; +} +``` + +This could be a `think_structured` variant or a config flag. + +## Files to create +- `packages/core/src/tools/think.ts` — tool implementation +- `packages/core/src/tools/think.test.ts` + +## Files to modify +- `packages/core/src/config/config.ts` — register tool in `registerCoreTool()` +- `packages/core/src/core/prompts.ts` — add think guidance to system prompt + (gated on config flag or model capability) + +## Effort: ~1 hour From b011b9a575c0f598706fd4637b571a55b200b422 Mon Sep 17 00:00:00 2001 From: tjdoomer Date: Thu, 2 Apr 2026 21:38:32 +1100 Subject: [PATCH 2/2] feat: add think tool for structured reasoning before acting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No-op tool that returns the model's reasoning back into context. Forces deliberation before tool calls — highest impact-to-effort compensator for weaker local models. --- packages/core/src/config/config.ts | 2 + packages/core/src/tools/think.ts | 73 ++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 packages/core/src/tools/think.ts diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 942d4c0e3c0..7d41caa0fe0 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -30,6 +30,7 @@ import { import { TodoWriteTool } from '../tools/todoWrite.js'; import { WebSearchTool } from '../tools/web-search.js'; import { SubAgentTool } from '../tools/subAgentTool.js'; +import { ThinkTool } from '../tools/think.js'; import { DeltaClient } from '../core/client.js'; import { FileDiscoveryService } from '../services/fileDiscoveryService.js'; import { GitService } from '../services/gitService.js'; @@ -916,6 +917,7 @@ export class Config { registerCoreTool(WebSearchTool, this); } registerCoreTool(SubAgentTool, this); + registerCoreTool(ThinkTool); await registry.discoverAllTools(); return registry; diff --git a/packages/core/src/tools/think.ts b/packages/core/src/tools/think.ts new file mode 100644 index 00000000000..c27655e4256 --- /dev/null +++ b/packages/core/src/tools/think.ts @@ -0,0 +1,73 @@ +/** + * Think tool — forces the model to reason before acting. + * + * A no-op tool that accepts structured reasoning and returns it back into + * context. No side effects. The model calls it to plan before making changes. + * + * This is the single best compensator for weaker local models — research on + * process reward models shows that models which checkpoint reasoning mid-task + * make fewer cascading errors. + */ + +import { + BaseDeclarativeTool, + BaseToolInvocation, + Kind, + ToolResult, +} from './tools.js'; +import { FunctionDeclaration } from '@google/genai'; + +interface ThinkParams { + reasoning: string; +} + +const thinkToolSchemaData: FunctionDeclaration = { + name: 'think', + description: + 'Use this tool to plan your approach before taking action. Write out your reasoning about the problem, what files are involved, what changes are needed, and in what order. This helps you avoid mistakes by thinking before acting. The output is returned to you for reference — no side effects occur.', + parametersJsonSchema: { + type: 'object', + properties: { + reasoning: { + type: 'string', + description: 'Your structured reasoning about the current task.', + }, + }, + required: ['reasoning'], + $schema: 'http://json-schema.org/draft-07/schema#', + }, +}; + +// The invocation is trivially simple — return the reasoning back to the model. +// No file I/O, no side effects, no confirmation needed. +class ThinkToolInvocation extends BaseToolInvocation { + getDescription(): string { + const preview = this.params.reasoning.substring(0, 80); + return preview.length < this.params.reasoning.length ? `${preview}...` : preview; + } + + async execute(): Promise { + return { + llmContent: [{ text: this.params.reasoning }], + returnDisplay: this.params.reasoning, + }; + } +} + +export class ThinkTool extends BaseDeclarativeTool { + static readonly Name: string = thinkToolSchemaData.name!; + + constructor() { + super( + ThinkTool.Name, + 'Think', + thinkToolSchemaData.description!, + Kind.Think, + thinkToolSchemaData.parametersJsonSchema, + ); + } + + protected createInvocation(params: ThinkParams) { + return new ThinkToolInvocation(params); + } +}