Skip to content

fix(think): implement automatic recursion prevention for think tool#167

Merged
cagataycali merged 1 commit intostrands-agents:mainfrom
cagataycali:fix/think-tool-recursion-prevention
Jul 22, 2025
Merged

fix(think): implement automatic recursion prevention for think tool#167
cagataycali merged 1 commit intostrands-agents:mainfrom
cagataycali:fix/think-tool-recursion-prevention

Conversation

@cagataycali
Copy link
Copy Markdown
Contributor

Description

This PR implements automatic recursion prevention for the think tool to resolve a critical bug where nested agents could call the think tool recursively, causing infinite loops and stack overflow errors.

Problem

The think tool was vulnerable to infinite recursion when:

  • Nested agents inherited all tools from their parent (including the think tool itself)
  • Tools were explicitly specified and included the think tool
  • Multi-cycle thinking operations created nested agents that could call think again

This created a dangerous recursion pattern: think → nested agent → think → nested agent → ∞

Solution

Implemented automatic exclusion of the think tool from nested agents with:

  • Smart filtering: Automatically removes think tool from nested agent tool lists
  • Comprehensive logging: Warning messages for explicit requests, debug messages for inheritance scenarios
  • Backward compatibility: All other tools remain available, no breaking changes to existing functionality
  • Multiple scenario handling: Works for explicit tool requests, tool inheritance, and edge cases

Key Changes

  • Core Logic: Modified tool filtering in think.py to exclude think tool from nested agents
  • System Prompts: Updated prompts to encourage use of other tools instead of prohibiting recursion
  • Logging: Added appropriate warning/debug messages for recursion prevention tracking
  • Comprehensive Testing: Added 5 new test cases covering all recursion scenarios:
    • Explicit tool requests including think
    • Tool inheritance from parent agents
    • Edge case with only think tool requested
    • Multi-cycle operations with recursion prevention
    • Various tool filtering combinations

Related Issues

Fixes infinite recursion bug in think tool that could cause stack overflow and system instability.

Documentation PR

No documentation changes required - this is an internal bug fix that maintains existing API compatibility.

Type of Change

  • Bug fix
  • New Tool
  • Breaking change
  • Other (please describe):

Testing

Comprehensive testing completed with all quality assurance checks passing:

Pre-commit Hooks (All Passed ✅)

  • hatch fmt --linter - ✅ Passed
  • hatch fmt --formatter - ✅ Passed
  • Type linting - ✅ Passed
  • Unit tests - ✅ Passed
  • Commit message validation - ✅ Passed

Additional Testing

  • New Test Coverage: Added 5 comprehensive test cases covering all recursion scenarios
  • Edge Case Testing: Verified behavior with empty tool lists, single tool requests, multi-cycle operations
  • Integration Testing: Tested with actual think tool usage to ensure no functional regression
  • Logging Verification: Confirmed appropriate warning/debug messages are generated
  • Backward Compatibility: Verified existing think tool functionality remains unchanged

Checklist

  • I have read the CONTRIBUTING document
  • I have added tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

Test Results Summary

fix(think): implement automatic recursion prevention for think tool
✅ Format code: Passed
✅ Lint code: Passed  
✅ Type linting: Passed
✅ Unit tests: Passed (including 5 new recursion prevention tests)
✅ Check commit message: Passed

Before/After Behavior

Before (Problematic):

# This would cause infinite recursion
think_tool(thought="analyze this", tools=["think", "calculator"])
# Result: Stack overflow due to think → nested agent → think → ...

After (Fixed):

# Same call now safely excludes think tool from nested agent
think_tool(thought="analyze this", tools=["think", "calculator"])
# Result: Nested agent gets only ["calculator"], recursion prevented
# Warning logged: "Excluding 'think' tool from nested agent to prevent recursion"

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

The think tool was vulnerable to infinite recursion when nested agents
would call the think tool again, creating a loop. This fix implements
automatic exclusion of the 'think' tool from nested agents to prevent
this recursion issue.

Key changes:
- Automatically filter out 'think' tool when creating nested agents
- Added logging for recursion prevention (warning for explicit requests, debug for inheritance)
- Updated system prompts to encourage use of other tools instead of prohibiting think tool
- Comprehensive test coverage for all recursion scenarios

The fix handles both explicit tool requests and tool inheritance scenarios:
- When tools are explicitly specified and include 'think', it logs a warning and excludes it
- When inheriting all tools from parent, it automatically excludes 'think' with debug logging
- Maintains compatibility with existing functionality while preventing recursion

Root cause was the think tool being available to its own nested agents,
allowing infinite recursive calls. The solution preserves all other tools
and functionality while safely preventing this specific recursion pattern.

Tested with multiple scenarios including explicit requests, inheritance,
empty tool lists, and multi-cycle operations.
@cagataycali cagataycali requested a review from a team as a code owner July 22, 2025 17:17
@cagataycali cagataycali merged commit 327f17b into strands-agents:main Jul 22, 2025
14 of 28 checks passed
TAKEDA-Takashi added a commit to TAKEDA-Takashi/tools that referenced this pull request Feb 5, 2026
…revent recursion

When _create_task_agent() inherits tools from the parent agent, the
workflow tool itself was included, which could cause infinite recursion
if a task agent invoked the workflow tool again.

This follows the same recursion prevention pattern established by the
think tool (PR strands-agents#167): the workflow tool is automatically excluded from
task agents in both the explicit tool list path and the inherit-all path.

Closes strands-agents#383

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants