crewai - ✅(Solved) Fix [BUG] Regression in CrewAI 1.9.3: custom BaseTool wrapper around BedrockKBRetrieverTool gets called without args (_run() missing query) and enters infinite tool-use loop [2 pull requests, 26 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
crewAIInc/crewAI#4495Fetched 2026-04-08 00:41:47
View on GitHub
Comments
26
Participants
3
Timeline
49
Reactions
0
Timeline (top)
commented ×26mentioned ×9subscribed ×9cross-referenced ×2

After upgrading CrewAI from 1.6.1 → 1.9.3, a custom tool wrapper around BedrockKBRetrieverTool no longer receives its required query argument. The tool call fails with: • ParsedBedrockKBRetrieverTool._run() missing 1 required positional argument: 'query' …and the agent repeatedly attempts to use the tool, effectively entering an infinite tool-calling loop. In crewai==1.6.1, the same code and workflow work as expected.

The logs also show an events mismatch warning during the loop: [CrewAIEventsBus] Warning: Event pairing mismatch. 'tool_usage_finished' closed 'flow_started' (expected 'tool_usage_started') Tool kb_retrieve executed with result: Error executing tool: ParsedBedrockKBRetrieverTool._run() missing 1 required positional argument: 'query'

This looks like a regression in how tool arguments are passed from the agent → tool execution in newer CrewAI versions.

Environment • crewai==1.9.3 (broken) • crewai==1.6.1 (works) • Tool involved: crewai_tools.aws.bedrock.knowledge_base.retriever_tool.BedrockKBRetrieverTool  • Custom tool extends crewai.tools.BaseTool (wrapper with post-processing)

Error Message

Tool kb_retrieve executed with result: Error executing tool: ParsedBedrockKBRetrieverTool._run() missing 1 required positional argument: 'query' except Exception: Tool kb_retrieve executed with result: Error executing tool: ParsedBedrockKBRetrieverTool._run() missing 1 required positional argument: 'query'...

Root Cause

Actual behavior • Tool execution fails because _run() is called without the required query parameter. • The agent loops, repeatedly trying to use the tool. • Event bus warning appears: “Event pairing mismatch … expected tool_usage_started”.

Fix Action

Fixed

PR fix notes

PR #4496: fix: extract Bedrock-style dict tool call arguments correctly (#4495)

Description (problem / solution / changelog)

fix: extract Bedrock-style dict tool call arguments correctly (#4495)

Summary

One-line fix for a regression where Bedrock-style dict tool calls ({"toolUseId": "...", "name": "...", "input": {...}}) silently lost their arguments, causing _run() to be called with no args.

Root cause: In _handle_native_tool_calls, the expression:

func_args = func_info.get("arguments", "{}") or tool_call.get("input", {})

For Bedrock dicts without a "function" key, func_info is {}, so .get("arguments", "{}") returns the default string "{}" — which is truthy. The or short-circuits and the actual arguments from tool_call["input"] are never read.

Fix:

func_args = func_info.get("arguments") or tool_call.get("input") or {}

Without a default, .get("arguments") returns None (falsy), allowing proper fallback to tool_call.get("input").

Review & Testing Checklist for Human

  • Confirm edge case: if an OpenAI response ever has "arguments": "" (empty string, falsy), the fix would now fall through to tool_call.get("input") instead of using the empty string. This should not happen in practice (OpenAI always sends valid JSON strings), but worth a mental trace to confirm acceptability.
  • End-to-end test with an actual Bedrock model using a custom BaseTool with args_schema (like the ParsedBedrockKBRetrieverTool from the issue) to confirm the fix resolves the reported issue. The new unit tests mock the tool call dicts directly and do not go through a real LLM provider.
  • Verify the fix doesn't break OpenAI-style dict tool calls where "function"."arguments" is present (test_openai_dict_tool_call_passes_arguments covers this, but worth a manual trace).

Recommended test plan: Deploy against a Bedrock-backed agent with a custom BaseTool that has required arguments and verify the tool receives its arguments correctly.

Notes

  • Tests index executor.messages[-2] to find the tool result message, relying on the internal message ordering (assistant → tool → reasoning prompt). This is correct per current code but couples tests to implementation detail.
  • All CI checks passed (lint, type-checker, tests across Python 3.10–3.13).
  • Requested by: João
  • Link to Devin run: https://app.devin.ai/sessions/79c3dd11772349d58fe284a62f8c8119

Changed files

  • lib/crewai/src/crewai/agents/crew_agent_executor.py (modified, +1/-1)
  • lib/crewai/tests/agents/test_native_tool_calling.py (modified, +247/-0)

PR #4507: fix: validate tool args_schema before execution in native mode (#4495)

Description (problem / solution / changelog)

Summary

Native tool calling mode bypasses CrewStructuredTool.invoke() / _parse_args() and calls BaseTool.run() directly via available_functions. When required arguments are missing, this produces a raw TypeError that can trigger deterministic retry loops.

Fix

Validate args_dict against the matched tool's args_schema before execution in _handle_native_tool_calls().

if original_tool and getattr(original_tool, "args_schema", None):
    validated = original_tool.args_schema.model_validate(args_dict)
    args_dict = validated.model_dump()

Missing or invalid arguments now raise ValidationError, which is handled by the existing outer exception block.

Native mode now normalizes arguments via Pydantic (including filling schema defaults), which aligns behavior with the ReAct path.

Scope

  • Minimal change limited to native tool-calling path
  • No changes to ReAct path
  • No signature changes
  • No new imports
  • Backward compatible

Tests

  • Added regression tests covering missing required args
  • Verified valid args still execute correctly

Closes #4495

<!-- CURSOR_SUMMARY -->

[!NOTE] Low Risk Small, localized change to the native tool execution path with added tests; main risk is minor behavior change in how invalid tool args are surfaced.

Overview Native tool calling now validates the parsed args_dict against the matched tool’s Pydantic args_schema before invoking the tool function, normalizing defaults and turning missing/invalid args into handled validation errors instead of raw TypeErrors.

Adds regression tests that reproduce the missing-required-arg scenario in native mode (ensuring _run is not called and a validation-style error is returned) and a sanity check that valid arguments still execute successfully.

<sup>Written by Cursor Bugbot for commit cc3ffb6b1ce1eef0c2324e297dec6ac9f68cc07e. This will update automatically on new commits. Configure here.</sup>

<!-- /CURSOR_SUMMARY -->

Changed files

  • lib/crewai/src/crewai/agents/crew_agent_executor.py (modified, +9/-0)
  • lib/crewai/tests/agents/test_native_tool_calling.py (modified, +179/-0)
RAW_BUFFERClick to expand / collapse

Description

After upgrading CrewAI from 1.6.1 → 1.9.3, a custom tool wrapper around BedrockKBRetrieverTool no longer receives its required query argument. The tool call fails with: • ParsedBedrockKBRetrieverTool._run() missing 1 required positional argument: 'query' …and the agent repeatedly attempts to use the tool, effectively entering an infinite tool-calling loop. In crewai==1.6.1, the same code and workflow work as expected.

The logs also show an events mismatch warning during the loop: [CrewAIEventsBus] Warning: Event pairing mismatch. 'tool_usage_finished' closed 'flow_started' (expected 'tool_usage_started') Tool kb_retrieve executed with result: Error executing tool: ParsedBedrockKBRetrieverTool._run() missing 1 required positional argument: 'query'

This looks like a regression in how tool arguments are passed from the agent → tool execution in newer CrewAI versions.

Environment • crewai==1.9.3 (broken) • crewai==1.6.1 (works) • Tool involved: crewai_tools.aws.bedrock.knowledge_base.retriever_tool.BedrockKBRetrieverTool  • Custom tool extends crewai.tools.BaseTool (wrapper with post-processing)

Steps to Reproduce

  1. Install and run with crewai==1.9.3 2. Create an agent (in a Crew) that has a tool list including a custom wrapper tool around BedrockKBRetrieverTool. 3. Ask the agent a question that triggers retrieval from the knowledge base. 4. Observe that the tool fails with a missing query arg, and the agent repeatedly retries tool usage.

Expected behavior

Expected behavior • The tool should be invoked with the query argument (as defined by the tool schema), execute once, and return retrieval results (JSON).

Actual behavior • Tool execution fails because _run() is called without the required query parameter. • The agent loops, repeatedly trying to use the tool. • Event bus warning appears: “Event pairing mismatch … expected tool_usage_started”.

Screenshots/Code snippets

from typing import Type import json from pydantic import BaseModel, Field, PrivateAttr from crewai.tools import BaseTool from crewai_tools.aws.bedrock.knowledge_base.retriever_tool import BedrockKBRetrieverTool

class KBQueryInput(BaseModel): """Input schema for KB retrieval tool.""" query: str = Field(..., description="Natural language query for the knowledge base.")

class ParsedBedrockKBRetrieverTool(BaseTool): name: str = "kb.retrieve" description: str = "Retrieve from Bedrock KB and parse results into RetrievedRef-shaped objects." args_schema: Type[BaseModel] = KBQueryInput _inner: BedrockKBRetrieverTool = PrivateAttr()

def __init__(self, inner: BedrockKBRetrieverTool):
    super().__init__()
    self._inner = inner

def _run(self, query: str) -> str:
    raw = self._inner._run(query)

    try:
        payload = json.loads(raw) if isinstance(raw, str) else raw
    except Exception:
        return json.dumps({"message": "Failed to parse BedrockKBRetrieverTool response as JSON."})

    if not isinstance(payload, dict):
        return json.dumps({"message": "Unexpected BedrockKBRetrieverTool response type."})

    results = payload.get("results")
    if results is None:
        return json.dumps({"message": payload.get("message", "No results found for the given query.")})

    # parsing logic omitted for brevity...
    return json.dumps({"results": results})

def build_kb_retrieval_tool(knowledge_base_id: str, n_results: int = 100) -> BaseTool: inner = BedrockKBRetrieverTool( knowledge_base_id=knowledge_base_id, number_of_results=n_results ) return ParsedBedrockKBRetrieverTool(inner=inner)

Operating System

Ubuntu 22.04

Python Version

3.12

crewAI Version

1.9.3

crewAI Tools Version

1.9.3

Virtual Environment

Poetry

Evidence

[CrewAIEventsBus] Warning: Event pairing mismatch. 'tool_usage_finished' closed 'flow_started' (expected 'tool_usage_started') Tool kb_retrieve executed with result: Error executing tool: ParsedBedrockKBRetrieverTool._run() missing 1 required positional argument: 'query'...

Possible Solution

None in early version its works

Additional context

None

extent analysis

Fix Plan

The issue seems to be related to how tool arguments are passed from the agent to tool execution in newer CrewAI versions.

To fix this, we need to modify the ParsedBedrockKBRetrieverTool class to accept the query argument from the args dictionary instead of as a positional argument.

Here are the steps:

  • Modify the _run method to accept args instead of query.
  • Extract the query from the args dictionary.

Example code:

class ParsedBedrockKBRetrieverTool(BaseTool):
    # ...

    def _run(self, args: dict) -> str:
        query = args.get("query")
        if query is None:
            raise ValueError("Missing required 'query' argument")

        raw = self._inner._run(query)
        # ... rest of the method remains the same

Additionally, ensure that the args_schema is correctly defined and validated.

Verification

To verify that the fix worked, follow these steps:

  • Run the agent with the modified ParsedBedrockKBRetrieverTool class.
  • Ask the agent a question that triggers retrieval from the knowledge base.
  • Check that the tool is invoked with the query argument and returns the expected results.

Extra Tips

  • Make sure to test the modified tool with different input scenarios to ensure it works as expected.
  • Consider adding logging or debugging statements to help diagnose any future issues.
  • Review the CrewAI documentation and release notes to ensure you are using the latest and recommended approaches for tool development.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Expected behavior • The tool should be invoked with the query argument (as defined by the tool schema), execute once, and return retrieval results (JSON).

Actual behavior • Tool execution fails because _run() is called without the required query parameter. • The agent loops, repeatedly trying to use the tool. • Event bus warning appears: “Event pairing mismatch … expected tool_usage_started”.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING