Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/claude_agent_sdk/_internal/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,9 +242,11 @@ async def _handle_control_request(self, request: SDKControlRequest) -> None:
raise Exception("canUseTool callback is not provided")

context = ToolPermissionContext(
tool_use_id=permission_request.get("tool_use_id", ""),
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

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

The tool_use_id field is marked as required (not optional) in the SDKControlPermissionRequest TypedDict, but here it's being accessed with .get() and defaulting to an empty string. This creates a mismatch: if the CLI fails to send tool_use_id, the code will silently use an empty string instead of failing fast with a clear error. Either:

  1. Change the TypedDict to make tool_use_id optional (tool_use_id: NotRequired[str]), or
  2. Access it directly without .get() since it's required: tool_use_id=permission_request["tool_use_id"]

Given that the PR description states this field is needed "to know which specific tool call is being authorized", option 2 (making it truly required) seems more appropriate.

Suggested change
tool_use_id=permission_request.get("tool_use_id", ""),
tool_use_id=permission_request["tool_use_id"],

Copilot uses AI. Check for mistakes.
signal=None, # TODO: Add abort signal support
suggestions=permission_request.get("permission_suggestions", [])
or [],
blocked_path=permission_request.get("blocked_path"),
)

response = await self.can_use_tool(
Expand Down
17 changes: 16 additions & 1 deletion src/claude_agent_sdk/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,26 @@ def to_dict(self) -> dict[str, Any]:
# Tool callback types
@dataclass
class ToolPermissionContext:
"""Context information for tool permission callbacks."""
"""Context information for tool permission callbacks.

Attributes:
tool_use_id: Unique identifier for this specific tool call within the
assistant message. Multiple tool calls in the same assistant message
will have different tool_use_ids.
signal: Reserved for future abort signal support. Currently always None.
suggestions: Permission suggestions from CLI for updating permissions
so the user won't be prompted again for this tool during this session.
blocked_path: The file path that triggered the permission request, if
applicable. For example, when a Bash command tries to access a path
outside allowed directories.
"""

tool_use_id: str
signal: Any | None = None # Future: abort signal support
suggestions: list[PermissionUpdate] = field(
default_factory=list
) # Permission suggestions from CLI
blocked_path: str | None = None


# Match TypeScript's PermissionResult structure
Expand Down Expand Up @@ -689,6 +703,7 @@ class SDKControlPermissionRequest(TypedDict):
subtype: Literal["can_use_tool"]
tool_name: str
input: dict[str, Any]
tool_use_id: str # Unique identifier for this tool call
# TODO: Add PermissionUpdate type here
permission_suggestions: list[Any] | None
blocked_path: str | None
Expand Down