You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The SDK's tool system has zero security classification. Every registered tool — whether it reads a file or deletes a database — is treated identically by the event loop. There is no way to declare a tool's safety profile, and no built-in permission gate before tool execution.
Phase 1: Security metadata on tools (non-breaking)
Add optional fields to @tool decorator and AgentTool:
@tool(read_only=True)deflist_files(directory: str) ->list[str]:
"""List files in a directory."""
...
@tool(destructive=True, requires_confirmation=True)defdelete_file(path: str) ->str:
"""Permanently delete a file."""
...
Add corresponding optional properties to AgentTool with safe defaults:
classAgentTool(ABC):
@propertydefis_read_only(self) ->bool:
"""Whether this tool only reads state without modification."""returnFalse# safe default: assume not read-only@propertydefis_destructive(self) ->bool:
"""Whether this tool performs irreversible actions."""returnFalse@propertydefrequires_confirmation(self) ->bool:
"""Whether this tool should require user confirmation before execution."""returnFalse
Users opt in by adding hooks=[PermissionPolicy()] to their Agent.
Trade-offs
Concern
Analysis
MCP tools can't use @tool decorator
MCPAgentTool can override is_read_only / is_destructive with defaults based on tool name heuristics, or expose a tool_permissions mapping on MCPClient.
Defaults matter
is_read_only=False and is_destructive=False are safe defaults. An unclassified tool is "unknown safety" — neither auto-approved nor auto-blocked.
Doesn't this duplicate hooks?
Hooks enable custom logic, but without metadata on the tool, every hook must hardcode tool-name-to-permission mappings. Metadata makes policies declarative and portable across projects.
Breaking change risk
Zero. All new fields are optional with backward-compatible defaults. Existing @tool functions and AgentTool subclasses work unchanged.
References
@tool decorator: src/strands/tools/decorator.py
ToolSpec: src/strands/types/tools.py
AgentTool: src/strands/tools/tools.py
BeforeToolCallEvent: src/strands/hooks/events.py
Hook dispatch in executor: src/strands/tools/executors/_executor.py
Problem Statement
The SDK's tool system has zero security classification. Every registered tool — whether it reads a file or deletes a database — is treated identically by the event loop. There is no way to declare a tool's safety profile, and no built-in permission gate before tool execution.
What exists today:
@tooldecorator supports only:func,description,inputSchema,name,context. No security parameters.ToolSpecTypedDict has only:description,inputSchema,name,outputSchema. No permission fields.AgentToolbase class has:tool_name,tool_spec,tool_type,supports_hot_reload,is_dynamic. No security properties.BeforeToolCallEventwithcancel_toolfield enables permission gating via hooks, but requires users to implement all classification logic externally.MCPClient.ToolFiltersfilters tools at load time by name pattern, but no runtime permission checks.What's missing:
Why this matters:
BeforeToolCallEvent+cancel_tool). What's missing is the metadata on tools for hooks to reason about, and a reference implementation that users can adopt.Related Issues
AgentToolproperties for hook-based policies (type metadata)Proposed Solution
Phase 1: Security metadata on tools (non-breaking)
Add optional fields to
@tooldecorator andAgentTool:Add corresponding optional properties to
AgentToolwith safe defaults:Phase 2: Reference PermissionPolicy hook (optional, opt-in)
Provide a reference
PermissionPolicyhook that uses the metadata:Users opt in by adding
hooks=[PermissionPolicy()]to their Agent.Trade-offs
@tooldecoratorMCPAgentToolcan overrideis_read_only/is_destructivewith defaults based on tool name heuristics, or expose atool_permissionsmapping onMCPClient.is_read_only=Falseandis_destructive=Falseare safe defaults. An unclassified tool is "unknown safety" — neither auto-approved nor auto-blocked.@toolfunctions andAgentToolsubclasses work unchanged.References
@tooldecorator:src/strands/tools/decorator.pyToolSpec:src/strands/types/tools.pyAgentTool:src/strands/tools/tools.pyBeforeToolCallEvent:src/strands/hooks/events.pysrc/strands/tools/executors/_executor.py