Bug Description
In subprocess_cli.py, the _build_command method uses a truthiness check for allowed_tools:
if self._options.allowed_tools: # line 195
cmd.extend(["--allowedTools", ",".join(self._options.allowed_tools)])
Since [] is falsy in Python, passing allowed_tools=[] never sends --allowedTools to the CLI subprocess. The intent of allowed_tools=[] is "allow no tools from the base set", but it silently does nothing.
Expected Behavior
allowed_tools=[] should pass --allowedTools "" to the CLI, disabling all allowed tools (same behavior as tools=[] which correctly passes --tools "").
Comparison with tools handling
The tools field correctly uses an is not None check (line ~183):
if self._options.tools is not None: # Correct: distinguishes None from []
tools = self._options.tools
if isinstance(tools, list):
if len(tools) == 0:
cmd.extend(["--tools", ""])
But allowed_tools and disallowed_tools both use truthiness checks, making empty lists indistinguishable from "not set".
Root Cause
The allowed_tools field defaults to field(default_factory=list) (always []), so a truthiness check can't distinguish "not set" from "explicitly empty". The fix requires either:
- Changing the default to
None and using is not None check, or
- Using
is not None check with the current default (would always pass --allowedTools "" — breaking change)
Same issue affects disallowed_tools
if self._options.disallowed_tools: # line 204 — same truthiness bug
cmd.extend(["--disallowedTools", ",".join(self._options.disallowed_tools)])
Workaround
Use tools=[] instead of allowed_tools=[] to disable all tools.
Versions
- claude-agent-sdk 0.1.45 (also present in 0.1.39)
- Python 3.14
Bug Description
In
subprocess_cli.py, the_build_commandmethod uses a truthiness check forallowed_tools:Since
[]is falsy in Python, passingallowed_tools=[]never sends--allowedToolsto the CLI subprocess. The intent ofallowed_tools=[]is "allow no tools from the base set", but it silently does nothing.Expected Behavior
allowed_tools=[]should pass--allowedTools ""to the CLI, disabling all allowed tools (same behavior astools=[]which correctly passes--tools "").Comparison with
toolshandlingThe
toolsfield correctly uses anis not Nonecheck (line ~183):But
allowed_toolsanddisallowed_toolsboth use truthiness checks, making empty lists indistinguishable from "not set".Root Cause
The
allowed_toolsfield defaults tofield(default_factory=list)(always[]), so a truthiness check can't distinguish "not set" from "explicitly empty". The fix requires either:Noneand usingis not Nonecheck, oris not Nonecheck with the current default (would always pass--allowedTools ""— breaking change)Same issue affects
disallowed_toolsWorkaround
Use
tools=[]instead ofallowed_tools=[]to disable all tools.Versions