crewAIInc / crewAIInc/crewAI

[BUG] sanitize_tool_name returns an empty string for non-ASCII tool names, breaking function calling and tool prompts

Open Beginner friendly
#7,624 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
58.8k
Forks
8.5k
Avg merge
1d 15h
Merged PRs (30d)
109

Description

Description

crewai.utilities.string_utils.sanitize_tool_name normalizes tool names for provider APIs by stripping everything outside [a-z0-9_]. When a tool name contains no ASCII letters or digits at all (for example a Chinese name like 搜索工具), the function returns the empty string "". That empty name flows unchanged into native function-calling payloads (convert_tools_to_openai_schema emits "function": {"name": ""}), which provider APIs reject because function/tool names must be non-empty and match ^[a-zA-Z0-9_-]{1,64}$. The resulting provider-side 400 error never mentions the real cause. A second non-ASCII-named tool in the same crew gets collision-renamed to "2", and the ReAct prompt lists the tools as ", ", so the text-tool-calling path cannot address them either. Tool names are unrestricted user-facing strings (BaseTool.name has no constraint), so international users hit this with perfectly valid tool definitions.

Steps to Reproduce
  1. Define a BaseTool whose name has no ASCII letters/digits, e.g. name: str = "搜索工具".
  2. Call convert_tools_to_openai_schema([tool]) (or run a crew using native function calling with that tool).
  3. Inspect the emitted schema: "function": {"name": ""}.
  4. With two such tools, the names become ["", "2"]; get_tool_names renders ", ".
Expected behavior

Every tool name sanitizes to a valid, unique, stable provider-safe name. A name with no ASCII content should get a deterministic fallback (the function already has one for over-length names: sha256(...)[:8]), never the empty string.

Screenshots/Code snippets
from crewai.utilities.string_utils import sanitize_tool_name
sanitize_tool_name("搜索工具")   # -> ''  (expected: a valid non-empty name)
sanitize_tool_name("抓取网页")   # -> ''  (identical output for a different name)

Schema emitted for two such tools: "name": "" and "name": "2".

Operating System: Windows 11 (reproduced on; the code path is platform-independent)
Python Version: 3.12 (reproduced on 3.12.7 and 3.13.12)
crewAI Version: 1.15.22 (also reproduced on main @ 3831e8b)
crewAI Tools Version: 1.15.22
Virtual Environment: Venv (uv)

Evidence
sanitize_tool_name("搜索工具") -> ''
function names in OpenAI schema: ["", "2"]
available_functions keys: ['', '2']
prompt tool list: ', '

Root cause: lib/crewai/src/crewai/utilities/string_utils.py — after the cleaning pipeline (NFKD → ASCII-drop → camelCase split → disallowed-char replacement → strip("_")), only the over-length branch has a deterministic hash fallback; the empty case returns "" unchecked.

Possible Solution

In sanitize_tool_name, after the cleaning steps, fall back to a deterministic name derived from the original input when the result is empty, e.g. f"tool_{sha256(original_name.encode())[:8]}" (hashing the original, not the empty string, keeps distinct non-ASCII names distinct). Happy to open a PR with this plus regression tests.

Additional context

This issue was found and written with AI assistance; please apply the llm-generated label per the contribution policy. Checked open issues/PRs on 2026-09-19 and found no existing report of this behavior.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in lib/crewai/src/crewai/utilities/string_utils.py at sanitize_tool_name, then trace convert_tools_to_openai_schema and get_tool_names as described. Add regression coverage for non-ASCII-only names and verify the resulting names are non-empty, provider-safe, deterministic, and distinct for different inputs.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
ai, api
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.