Reasoning Tools

Give any model explicit tools for structured thinking, transforming regular models into careful problem-solvers through deliberate reasoning steps.

Setup

In an activated virtual environment:

uv pip install -U agno openai
export OPENAI_API_KEY="your_openai_api_key"

Reasoning tools let a model write explicit planning and analysis notes during its normal tool loop. The model decides when to use them.

Agno provides four specialized reasoning toolkits, each optimized for different domains:

ToolkitPurposeCore Tools
ReasoningToolsGeneral-purpose thinking and analysisthink(), analyze()
KnowledgeToolsReasoning with knowledge base searchesthink(), search_knowledge(), analyze()
MemoryToolsReasoning about user memory operationsthink(), get/add/update/delete_memory(), analyze()
WorkflowToolsReasoning about workflow executionthink(), run_workflow(), analyze()

All reasoning toolkits register their think()/analyze() functions under the same names. When you combine toolkits, the agent keeps only the first implementation of each function name, drops the duplicates, and logs a warning. Disable enable_think/enable_analyze (or rename/customize functions) on the later toolkits if you still want them to expose their domain-specific actions without conflicting with the scratchpad tools.

All four toolkits follow the same Think → Act → Analyze pattern but provide domain-specific actions tailored to their use case.

This approach was first popularized by Anthropic in their "think" tool blog post, though many AI engineers (including our team) were using similar patterns long before.

Why Reasoning Tools?

Reasoning Tools give you the best of both worlds:

  1. Works with tool-capable models - Even models without native reasoning capabilities
  2. Explicit control - The agent decides when to think vs. when to act
  3. Observable notes - You can inspect the explicit tool arguments and results
  4. Flexible workflow - The agent can interleave thinking with tool calls
  5. Domain-optimized - Each toolkit is specialized for its specific use case
  6. Iterative loop - Think, act, analyze, repeat until the agent has enough information

These notes are ordinary tool data. Applications control whether tool events, stored messages, reasoning content, and logs are displayed or retained; the toolkit is not a privacy boundary.

The Four Reasoning Toolkits

1. ReasoningTools - General Purpose Thinking

For general problem-solving without domain-specific tools.

What it provides:

  • think() - Plan and reason about the problem
  • analyze() - Evaluate results and determine next steps

When to use:

  • Mathematical or logical problems
  • Strategic planning
  • Analysis tasks that don't require external data
  • Any scenario where you want structured reasoning

Example:

from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.tools.reasoning import ReasoningTools

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[ReasoningTools(add_instructions=True)],
)

agent.print_response(
    "Which is bigger: 9.11 or 9.9? Explain your reasoning.",
    stream=True,
)

2. KnowledgeTools - Reasoning with Knowledge Bases

For searching and analyzing information from knowledge bases (RAG).

What it provides:

  • think() - Plan search strategy and refine approach
  • search_knowledge() - Query the knowledge base
  • analyze() - Evaluate search results for relevance and completeness

When to use:

  • Document retrieval and analysis
  • RAG (Retrieval-Augmented Generation) workflows
  • Research tasks requiring multiple search iterations
  • When you need to verify information from knowledge bases

Example: Prepare a reachable PostgreSQL server with pgvector, and put your text research papers in data/research_papers/. Replace the example database URL with your own.

uv pip install "psycopg[binary]" pgvector sqlalchemy
mkdir -p data/research_papers
from agno.agent import Agent
from agno.knowledge.knowledge import Knowledge
from agno.models.openai import OpenAIResponses
from agno.tools.knowledge import KnowledgeTools
from agno.vectordb.pgvector import PgVector

# Create knowledge base
knowledge = Knowledge(
    vector_db=PgVector(
        table_name="research_papers",
        db_url="postgresql+psycopg://ai:ai@localhost:5532/ai",
    ),
)
knowledge.insert(path="data/research_papers/")  # Add your files before running this example.

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[KnowledgeTools(knowledge=knowledge, add_instructions=True)],
    instructions="Search thoroughly and cite your sources",
)

agent.print_response(
    "What are the latest findings on quantum entanglement in our research papers?",
    stream=True,
)

Possible tool sequence (model-dependent):

  1. Agent calls think(): "I need to search for quantum entanglement. Let me try multiple search terms."
  2. Agent calls search_knowledge("quantum entanglement")
  3. Agent calls analyze(): "Results are too broad. Need more specific search."
  4. Agent calls search_knowledge("quantum entanglement recent findings")
  5. Agent calls analyze(): "Now I have sufficient, relevant results."
  6. Agent provides final answer

3. MemoryTools - Reasoning about User Memories

For managing and reasoning about user memories with CRUD operations.

What it provides:

  • think() - Plan memory operations
  • get_memories() - Retrieve user memories
  • add_memory() - Store new memories
  • update_memory() - Modify existing memories
  • delete_memory() - Remove memories
  • analyze() - Evaluate memory operations

When to use:

  • Personalized agent interactions
  • User preference management
  • Maintaining conversation context across sessions
  • Building user profiles over time

Example:

from agno.agent import Agent
from agno.db.postgres import PostgresDb
from agno.models.openai import OpenAIResponses
from agno.tools.memory import MemoryTools

# Reuse the PostgreSQL server prepared above.
db = PostgresDb(
    db_url="postgresql+psycopg://ai:ai@localhost:5532/ai",
)

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[MemoryTools(db=db, enable_update_memory=False, enable_delete_memory=False, add_instructions=True)],
    db=db,
)

agent.print_response(
    "I prefer vegetarian recipes and I'm allergic to nuts.",
    user_id="user_123",
)

Possible tool sequence (model-dependent):

  1. Agent calls think(): "User is sharing dietary preferences. I should store this."
  2. Agent calls add_memory(memory="User prefers vegetarian recipes and is allergic to nuts", topics=["dietary_preferences", "allergies"])
  3. Agent calls analyze(): "Memory successfully stored with appropriate topics."
  4. Agent responds to user confirming the information was saved

The example disables update/delete. Those built-in operations look up memory IDs without checking the current user; enforce ownership in application wrappers before enabling them on a shared store.

4. WorkflowTools - Reasoning about Workflow Execution

For executing and analyzing complex workflows.

What it provides:

  • think() - Plan workflow inputs and strategy
  • run_workflow() - Execute a workflow with specific inputs
  • analyze() - Evaluate workflow results

WorkflowTools registers only run_workflow() by default. Set enable_think=True and enable_analyze=True to add the thinking tools.

When to use:

  • Multi-step automated processes
  • Complex task orchestration
  • When workflows need different inputs based on context
  • A/B testing different workflow configurations

Example:

from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.tools.workflow import WorkflowTools
from agno.workflow import Workflow
from agno.workflow.step import Step

# Use real web retrieval; install ddgs with: uv pip install ddgs
from agno.tools.websearch import WebSearchTools

search_agent = Agent(model=OpenAIResponses(id="gpt-5.2"), tools=[WebSearchTools()])
summary_agent = Agent(model=OpenAIResponses(id="gpt-5.2"), instructions="Summarize the supplied research and preserve source URLs.")
fact_check_agent = Agent(model=OpenAIResponses(id="gpt-5.2"), tools=[WebSearchTools()], instructions="Check the supplied claims against sources and flag unsupported claims.")

# Define a research workflow
research_workflow = Workflow(
    name="research-workflow",
    steps=[
        Step(name="search", agent=search_agent),
        Step(name="summarize", agent=summary_agent),
        Step(name="fact-check", agent=fact_check_agent),
    ],
)

# Create agent with workflow tools
orchestrator = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[
        WorkflowTools(
            workflow=research_workflow,
            enable_think=True,
            enable_analyze=True,
            add_instructions=True,
        )
    ],
)

orchestrator.print_response(
    "Research climate change impacts on agriculture",
    stream=True,
)

Possible tool sequence (model-dependent):

  1. Agent calls think(): "I need to run the research workflow with 'climate change agriculture' as input."
  2. Agent calls run_workflow(input={"input_data": "climate change impacts on agriculture"})
  3. Workflow executes all steps (search → summarize → fact-check)
  4. Agent calls analyze(): "Workflow completed successfully. All fact-checks passed."
  5. Agent provides final synthesized answer

Common Pattern: Think → Act → Analyze

All four toolkits follow the same reasoning cycle:

  1. THINK - Plan what to do, refine approach, brainstorm
  2. ACT (Domain-Specific)
    • ReasoningTools: Direct reasoning
    • KnowledgeTools: search_knowledge()
    • MemoryTools: get/add/update/delete_memory()
    • WorkflowTools: run_workflow()
  3. ANALYZE - Evaluate results, decide next action
  4. REPEAT - Loop back to THINK if needed, or provide answer

The agent thinks before acting, evaluates results, and adjusts its approach based on what it learns.

Choosing the Right Reasoning Toolkit

If you need to...UseExample
Solve logic puzzles or math problemsReasoningTools"Solve: If x² + 5x + 6 = 0, what is x?"
Search through documentsKnowledgeTools"Find all mentions of user authentication in our docs"
Remember user preferencesMemoryTools"Remember that I'm allergic to shellfish"
Orchestrate complex multi-step tasksWorkflowTools"Research, write, and fact-check an article"
Combine multiple domainsUse multiple toolkitsSee examples for more patterns

Combining Multiple Reasoning Toolkits

Reuse knowledge and db configured above to combine toolkits. Tool names must stay unique, so disable overlapping think/analyze entries (or rename the later ones) to prevent duplicates from being dropped:

from agno.agent import Agent
from agno.models.openai import OpenAIResponses
from agno.tools.knowledge import KnowledgeTools
from agno.tools.memory import MemoryTools
from agno.tools.reasoning import ReasoningTools

agent = Agent(
    model=OpenAIResponses(id="gpt-5.2"),
    tools=[
        ReasoningTools(add_instructions=True),
        KnowledgeTools(
            knowledge=knowledge,
            enable_think=False,
            enable_analyze=False,
            add_instructions=False,
        ),
        MemoryTools(
            db=db,
            enable_update_memory=False,
            enable_delete_memory=False,
            enable_think=False,
            enable_analyze=False,
            add_instructions=False,
        ),
    ],
    instructions="Use reasoning for planning, knowledge for facts, and memory for personalization",
)

With this setup:

  • ReasoningTools supplies the shared think/analyze scratchpad.
  • KnowledgeTools still exposes search_knowledge() (and any other unique methods) without trying to register duplicate scratchpad functions.
  • MemoryTools contributes retrieval and creation; update/delete remain disabled in this shared-store example.

If you need separate scratchpads per domain, create custom wrappers around think()/analyze() so each toolkit registers uniquely named functions (e.g., knowledge_think, memory_analyze).

Configuration Options

Enable/Disable Specific Tools

You can control which reasoning tools are available:

# Only thinking, no analysis
ReasoningTools(enable_think=True, enable_analyze=False)

# Only analysis, no thinking
ReasoningTools(enable_think=False, enable_analyze=True)

# Both (default)
ReasoningTools(enable_think=True, enable_analyze=True)

# Shorthand for both
ReasoningTools()

Add Instructions Automatically

Many toolkits ship with pre-written guidance that explains how to use their tools. Setting add_instructions=True injects those instructions into the agent prompt (when the toolkit actually has any):

ReasoningTools(add_instructions=True)
  • ReasoningTools, KnowledgeTools, MemoryTools, and WorkflowTools all include Agno-authored instructions (and optional few-shot examples) describing their Think → Act → Analyze workflow.
  • Other toolkits may not define default instructions; in that case add_instructions=True is a no-op unless you supply your own instructions=....

The built-in instructions cover when to use think() vs analyze(), how to iterate, and best practices for each domain. Turn them on unless you plan to provide custom guidance.

Add Few-Shot Examples

Want to show your agent some examples of good reasoning? Some toolkits come with pre-written few-shot examples that demonstrate the workflow in action. Turn them on with add_few_shot=True:

ReasoningTools(add_instructions=True, add_few_shot=True)

Right now, ReasoningTools, KnowledgeTools, and MemoryTools have built-in examples. Other toolkits won't use add_few_shot=True unless you provide your own examples.

These examples show the agent how to iterate through problems, decide on next actions, and mix thinking with actual tool calls.

When should you use them?

  • You're using a smaller or cheaper model that needs extra guidance
  • Your reasoning workflow has multiple stages or is complex
  • You want more consistent behavior across different runs

Custom Instructions

Provide your own custom instructions for specialized reasoning:

custom_instructions = """
Use the think and analyze tools for rigorous scientific reasoning:
- Always think before making claims
- Cite evidence in your analysis
- Acknowledge uncertainty
- Consider alternative hypotheses
"""

ReasoningTools(
    instructions=custom_instructions,  # Replaces the default instructions
    add_instructions=True,  # Inject your custom instructions into the prompt
)

Custom Few-Shot Examples

You can also write your own examples tailored to your domain:

medical_examples = """
Example: Medical Diagnosis

User: Patient has fever and cough for 3 days.

Agent thinks:
think(
    title="Gather Symptoms",
    thought="Need to collect all symptoms and their duration. Fever and cough suggest respiratory infection. Should check for other symptoms.",
    action="Ask about additional symptoms",
    confidence=0.9
)
"""

ReasoningTools(
    add_instructions=True,
    add_few_shot=True,
    few_shot_examples=medical_examples  # Your custom examples
)

Monitoring Your Agent's Thinking

Use show_full_reasoning=True and stream_events=True to display reasoning steps in real-time. See Display Options in Reasoning Agents for details and Reasoning Reference for programmatic access to reasoning steps.

Reasoning Tools vs. Reasoning Agents

Reasoning tools are explicit calls chosen by the model during the tool loop. A separate reasoning agent uses a supported native reasoning_model before the main response. Neither approach guarantees a particular analysis sequence or a correct result.