[DOCS] AgentDefinition uses camelCase (disallowedTools) but ClaudeAgentOptions uses snake_case (disallowed_tools) — silent no-op on mismatch
Description
AgentDefinition (JS-style) uses camelCase field names (disallowedTools, permissionMode, maxTurns), while ClaudeAgentOptions (Python SDK) uses snake_case (disallowed_tools, permission_mode, max_turns).
If you accidentally use the wrong casing — e.g., disallowed_tools=["Bash"] on an AgentDefinition or disallowedTools=["Bash"] on ClaudeAgentOptions — it silently does nothing. No error, no warning, no enforcement. The tool remains available.
This bit us in a production security scanner where we set disallowedTools on AgentDefinition to block Bash, Write, Edit, etc. on 13 agents. The fields were accepted without error but never enforced because one layer used the wrong casing. An LLM agent then executed arbitrary SQL via the Bash tool against our database.
Steps to Reproduce
from claude_agent_sdk import AgentDefinition, ClaudeAgentOptions
# This WORKS — camelCase on AgentDefinition
defn = AgentDefinition(
description="test",
prompt="test",
disallowedTools=["Bash"], # ✅ correct casing
)
# This SILENTLY DOES NOTHING — snake_case on AgentDefinition
defn = AgentDefinition(
description="test",
prompt="test",
disallowed_tools=["Bash"], # ❌ wrong casing, no error, Bash still available
)
Expected Behavior
Either:
- Raise an error when an unknown field name is passed (strict mode / no
extrafields) - Accept both casings and normalize internally
- Document the casing contract prominently in the AgentDefinition and ClaudeAgentOptions reference, with a warning callout
Actual Behavior
The wrong-cased field is silently ignored. No error at construction time, no warning in logs. The deny list is never applied.
Environment
- Claude Agent SDK (Python, via
anthropic[bedrock]) - Claude Code CLI used as the agent runtime
- AWS Bedrock (Sonnet 4.6 / Opus 4.7)
Additional Context
The subagents.md docs show the correct casing in examples, but the two APIs using different conventions (AgentDefinition = JS camelCase, ClaudeAgentOptions = Python snake_case) is a footgun. A type-checking layer or a model_config = {"extra": "forbid"} on the Pydantic model backing AgentDefinition would catch this at construction time.
Related issues:
- #19501 (tools + disallowedTools incompatibility)
- #20242 (confusing tools vs allowed_tools descriptions)
- #31292 (disallowedTools bypass via Bash sed/awk)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗