Skip to content

What is the 'Think Tool' Pattern for LLM Agents?

Problem

After 6 months of running LLM agents in production, I stopped blaming the model. My agents kept making impulsive decisions that caused cascading failures. They would execute the wrong tool, call APIs with incorrect parameters, or skip critical validation steps.

Someone on Reddit suggested:

“Add a ‘think tool’ for the agent. Anthropic provided an overview of this approach.”

I was skeptical. Why would adding a tool that does nothing help? But I tried it anyway, and my agent failure rate dropped significantly. Here’s what I learned.

What went wrong

My original agent architecture encouraged immediate action without reflection:

User Request -> Model -> Tool Selection -> Execute -> Result

This looks fine on paper. The problem is that models optimized for chat can act too quickly. Here’s a real failure I encountered:

# title: My broken agent flow
def process_user_request(user_input):
# Model immediately picks a tool
tool_choice = model.predict(f"Which tool for: {user_input}")
# No reasoning about consequences
result = execute_tool(tool_choice)
return result

When I asked the agent to “delete old log files,” it immediately called:

Tool: delete_files
Parameters: {"pattern": "*.log"}

The problem? It deleted files in the current directory instead of the logs directory. The agent saw “delete” and “log files” and jumped to action without considering:

  • Which directory should I target?
  • What’s the current working directory?
  • Should I list files first to verify?

This wasn’t a model intelligence problem. It was an architecture problem.

The think tool pattern

The solution is deceptively simple: give agents a tool that does nothing but log reasoning. The magic is that having this tool available encourages the model to think before acting.

# title: Basic think tool implementation
from typing import TypedDict
from langchain.tools import BaseTool
class ThinkResult(TypedDict):
reasoning_logged: bool
reasoning_length: int
class ThinkTool(BaseTool):
name = "think"
description = """
Use this tool to think through problems before taking action.
Describe your reasoning step by step:
- What is the current state?
- What are the options?
- What are the trade-offs?
- What should you do and why?
This tool has no side effects - it only logs your thinking.
"""
def _run(self, reasoning: str) -> ThinkResult:
# Log reasoning for debugging/transparency
self.log_reasoning(reasoning)
return ThinkResult(
reasoning_logged=True,
reasoning_length=len(reasoning)
)
def log_reasoning(self, reasoning: str):
import logging
logger = logging.getLogger("agent_reasoning")
logger.info(f"AGENT REASONING:\n{reasoning}\n{'-'*50}")

The tool does nothing. It returns confirmation that reasoning was logged. But the presence of this tool changes how the model approaches problems.

How it changed my agent’s behavior

With the think tool available, my agent now follows a different pattern:

User Request -> Model -> Think Tool -> Reasoning -> Tool Selection -> Execute

Here’s the same “delete old log files” request with the think tool:

THINK: The user wants to delete old log files. Let me reason through this:
- Current state: I'm in the project root directory
- Options: I could use delete_files with *.log pattern, or first list files to verify
- Trade-offs: Deleting without verifying is risky; listing first adds a step but prevents accidents
- Decision: First check current directory, list files matching *.log, then delete with confirmation

Then the agent executes:

Tool: list_files
Parameters: {"pattern": "*.log", "directory": "."}
Tool: change_directory
Parameters: {"path": "logs"}
Tool: list_files
Parameters: {"pattern": "*.log", "directory": "logs"}
Tool: delete_files
Parameters: {"pattern": "*.log", "directory": "logs", "older_than_days": 30}

Same model. Same prompt. Different outcome. The think tool forced explicit deliberation.

Enforcing thinking before acting

Just having the think tool available isn’t enough. Some models will skip it. I had to enforce thinking at the architecture level:

# title: Agent with mandatory think phase
from pydantic import BaseModel, Field, validator
from typing import Optional
class AgentAction(BaseModel):
thought_process: str = Field(..., min_length=50)
action_type: str
parameters: dict
confidence: float = Field(..., ge=0.0, le=1.0)
@validator('thought_process')
def must_show_reasoning(cls, v):
required_sections = ['analysis', 'options', 'decision']
for section in required_sections:
if section.lower() not in v.lower():
raise ValueError(f"Thinking must include: {section}")
return v
class StructuredAgent:
def __init__(self, llm, tools):
self.llm = llm
self.tools = {tool.name: tool for tool in tools}
self.think_tool = ThinkTool()
self.reasoning_history = []
def process(self, user_input: str) -> dict:
# Phase 1: THINK
thinking_prompt = f"""
Before taking action, think through this problem:
User request: {user_input}
Provide your reasoning in this format:
ANALYSIS: What is the user asking for?
OPTIONS: What are possible approaches?
TRADEOFFS: What are the pros/cons of each?
DECISION: What will you do and why?
"""
reasoning = self.llm.generate(thinking_prompt)
think_result = self.think_tool._run(reasoning)
self.reasoning_history.append(reasoning)
# Phase 2: ACT
action_prompt = f"""
Based on your reasoning:
{reasoning}
Now choose an action. Available tools: {list(self.tools.keys())}
Respond with JSON containing:
- action_type: tool name
- parameters: tool parameters
- confidence: 0.0 to 1.0
"""
action_json = self.llm.generate(action_prompt)
action = AgentAction.parse_raw(action_json)
# Phase 3: EXECUTE
if action.action_type in self.tools:
result = self.tools[action.action_type].run(**action.parameters)
return {
"success": True,
"result": result,
"reasoning": reasoning,
"confidence": action.confidence
}
return {"success": False, "error": "Unknown action"}

The validator ensures the model can’t skip reasoning. If the thought_process field doesn’t contain “analysis”, “options”, and “decision” sections, the action fails validation.

Multi-step reasoning with checkpoints

For complex tasks, I added reasoning checkpoints at each phase:

# title: Multi-step agent with reasoning checkpoints
from enum import Enum
class ReasoningPhase(Enum):
UNDERSTAND = "understand" # What is being asked?
PLAN = "plan" # What steps are needed?
VALIDATE = "validate" # Is the plan sound?
EXECUTE = "execute" # Run the plan
REFLECT = "reflect" # Did it work?
class MultiStepAgent:
REASONING_PROMPTS = {
ReasoningPhase.UNDERSTAND: """
UNDERSTANDING PHASE:
- What is the user actually asking for?
- What constraints or requirements exist?
- What information do I have vs. need?
""",
ReasoningPhase.PLAN: """
PLANNING PHASE:
- What are the steps to solve this?
- What tools do I need?
- What could go wrong?
""",
ReasoningPhase.VALIDATE: """
VALIDATION PHASE:
- Is this plan complete?
- Are there better alternatives?
- Should I proceed or reconsider?
""",
ReasoningPhase.REFLECT: """
REFLECTION PHASE:
- Did the action achieve the goal?
- What did I learn?
- Should I try a different approach?
"""
}
def __init__(self, llm, tools):
self.llm = llm
self.tools = tools
self.think_tool = ThinkTool()
self.reasoning_trace = {}
def think(self, phase: ReasoningPhase, context: str) -> str:
prompt = self.REASONING_PROMPTS[phase] + f"\nContext: {context}"
reasoning = self.llm.generate(prompt)
self.think_tool._run(reasoning)
self.reasoning_trace[phase] = reasoning
return reasoning
def run(self, task: str) -> dict:
# Checkpoint 1: Understand
understanding = self.think(ReasoningPhase.UNDERSTAND, task)
# Checkpoint 2: Plan
plan = self.think(ReasoningPhase.PLAN, understanding)
# Checkpoint 3: Validate
validation = self.think(ReasoningPhase.VALIDATE, plan)
# Execute only if validation passes
if "proceed" in validation.lower() or "yes" in validation.lower():
results = self.execute_plan(plan)
# Checkpoint 4: Reflect
reflection = self.think(ReasoningPhase.REFLECT, str(results))
return {
"success": True,
"results": results,
"reasoning_trace": self.reasoning_trace
}
return {
"success": False,
"reason": "Validation failed",
"reasoning_trace": self.reasoning_trace
}

This structure prevents the agent from rushing through phases. Each checkpoint creates a traceable reasoning step I can review when things go wrong.

Common mistakes I made

1. Not enforcing think tool usage

At first, I just added the tool to the available tools list. The model sometimes used it, sometimes didn’t. I had to add enforcement at the architecture level.

2. Accepting shallow reasoning

Initially, I accepted any thinking as valid. But the model would output one-liners like “I should delete the files.” I added validators requiring structured sections.

3. No reasoning structure

When I let the model think freely, the reasoning was often vague. Adding guiding questions to the think tool description improved reasoning quality significantly.

4. Skipping validation

I initially trusted all reasoning. But models can justify bad decisions. Adding a validation phase where the model critiques its own plan caught many potential errors.

Why this works

The think tool pattern addresses three fundamental problems in LLM agents:

1. Impulsive action selection - Models trained for chat completion tend to produce the next token immediately. The think tool creates a pause between understanding and acting.

2. No reasoning visibility - When an agent fails, you often can’t tell why it made a decision. Think tools create a log of reasoning that helps debugging.

3. No backtracking - Once an agent commits to an action, it’s done. Structured thinking phases allow the model to reconsider before execution.

Why models act impulsively

LLMs are trained on next-token prediction. When given a user request and a list of tools, the model’s training pushes it toward immediate tool selection. This is great for speed but bad for complex decision-making.

Extended thinking vs think tools

Anthropic’s Claude models now support “extended thinking” - a built-in reasoning mode. The think tool pattern is different: it works with any model and creates explicit, logged reasoning that you can inspect. Extended thinking is internal to the model; think tools are external and auditable.

When you don’t need think tools

For simple, single-step tasks, think tools add overhead. If your agent only needs to “get the current weather,” the think tool will just slow things down. Think tools shine in multi-step workflows where wrong decisions compound.

Summary

The think tool pattern changed my approach to building LLM agents. Instead of hoping models make good decisions, I now force explicit reasoning at the architecture level.

The key principles I follow:

  1. Force deliberation - Make thinking mandatory, not optional
  2. Structure reasoning - Guide models with specific questions to answer
  3. Create traceability - Log all reasoning for debugging and improvement

If your agents are making impulsive decisions, try adding a think tool. It’s a simple change that often produces dramatic improvements in reliability.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments