Skip to content

fix: stop double-counting tool usage, halving max_usage_count - #6769

Open
NishchayMahor wants to merge 1 commit into
crewAIInc:mainfrom
NishchayMahor:fix/tool-usage-count-double-increment
Open

fix: stop double-counting tool usage, halving max_usage_count#6769
NishchayMahor wants to merge 1 commit into
crewAIInc:mainfrom
NishchayMahor:fix/tool-usage-count-double-increment

Conversation

@NishchayMahor

Copy link
Copy Markdown

Summary

A tool configured with max_usage_count=N is blocked after only N/2 successful calls because its usage count is incremented twice per call.

tool = MyTool(max_usage_count=2)   # expect 2 uses
# through an agent / ToolUsage: only 1 call runs, then:
# "Tool 'MyTool' has reached its usage limit of 2 times and cannot be used anymore."

Root cause

CrewStructuredTool.invoke() and ainvoke() already call self._increment_usage_count() (co-located with the has_reached_max_usage_count() check). ToolUsage._use / _ause run the tool via that same invoke()/ainvoke(), then increment the same tool object a second time via available_tool._increment_usage_count(). So current_usage_count rises by 2 on every successful (non-cached) call.

The two increments were introduced by separate PRs (#3362 added the one in structured_tool.py; #4258 added the one in tool_usage.py), so this is a merge-time regression.

Fix

Remove the redundant increment in ToolUsage._use/_ause, keeping the authoritative one inside invoke()/ainvoke() where it is paired with the limit check. The elif branch — for tools that expose current_usage_count but have no self-incrementing invoke — still increments manually and is unchanged.

Verification

max_usage_count = 2
# before: call 1 -> count=2 (runs once), call 2 -> blocked
# after:  call 1 -> count=1, call 2 -> count=2 (runs twice), call 3 -> blocked

Added test_tool_usage_use_does_not_double_count which drives the real ToolUsage.use() path and asserts the tool runs exactly max_usage_count times. Fails on main, passes with the fix.

pytest lib/crewai/tests/tools/test_tool_usage_limit.py   # 8 passed

ruff clean.

This fix was developed with AI assistance; I verified the double-count and the fix end-to-end with the reproduction above and reviewed every line.

CrewStructuredTool.invoke()/ainvoke() already increment the tool's usage
count, but ToolUsage._use/_ause incremented the same tool object a second
time after running it. A tool with max_usage_count=N was therefore blocked
after N/2 successful calls. Remove the redundant increment in ToolUsage and
keep the authoritative one co-located with the limit check in invoke().
Tools without a self-incrementing invoke (the elif branch) are unaffected.
@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Tool usage counting

Layer / File(s) Summary
Execution usage counting
lib/crewai/src/crewai/tools/tool_usage.py
Asynchronous and synchronous execution paths no longer duplicate usage increments for tools with _increment_usage_count. Fallback counter updates remain unchanged.
Usage limit regression coverage
lib/crewai/tests/tools/test_tool_usage_limit.py
The regression test verifies one increment per call, execution through the two-use limit, and blocking after the limit is reached.

Suggested reviewers: greysonlalonde

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the fix for double-counted tool usage and the resulting reduction in the configured usage limit.
Description check ✅ Passed The description clearly explains the double-counting cause, the fix, and the regression test for tool usage limits.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
lib/crewai/tests/tools/test_tool_usage_limit.py (1)

155-193: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add regression coverage for asynchronous execution.

The new test covers ToolUsage.use() only. This PR also changes ToolUsage._ause() at Line 422-424 in lib/crewai/src/crewai/tools/tool_usage.py. Add an async test that calls await tool_usage.ause(...) and verifies one increment per call and blocking after max_usage_count.

As per coding guidelines, write behavior-focused unit tests for new functionality.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/crewai/tests/tools/test_tool_usage_limit.py` around lines 155 - 193, Add
an asynchronous regression test alongside
test_tool_usage_use_does_not_double_count that invokes ToolUsage.ause(...) with
the CountingTool setup, verifies current_usage_count increases once per allowed
call, confirms both allowed calls execute, and confirms a subsequent call over
max_usage_count neither executes nor increments the count.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@lib/crewai/tests/tools/test_tool_usage_limit.py`:
- Around line 155-193: Add an asynchronous regression test alongside
test_tool_usage_use_does_not_double_count that invokes ToolUsage.ause(...) with
the CountingTool setup, verifies current_usage_count increases once per allowed
call, confirms both allowed calls execute, and confirms a subsequent call over
max_usage_count neither executes nor increments the count.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dd5b81e5-bfab-41db-af67-6de5a9763d97

📥 Commits

Reviewing files that changed from the base of the PR and between c8f441c and 13a7f2e.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/tools/tool_usage.py
  • lib/crewai/tests/tools/test_tool_usage_limit.py

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.

1 participant