@@ -84,6 +84,7 @@ def __getattr__(self, name: str) -> Callable[..., Any]:
84
84
"""Call tool as a function.
85
85
86
86
This method enables the method-style interface (e.g., `agent.tool.tool_name(param="value")`).
87
+ It matches underscore-separated names to hyphenated tool names (e.g., 'some_thing' matches 'some-thing').
87
88
88
89
Args:
89
90
name: The name of the attribute (tool) being accessed.
@@ -92,9 +93,34 @@ def __getattr__(self, name: str) -> Callable[..., Any]:
92
93
A function that when called will execute the named tool.
93
94
94
95
Raises:
95
- AttributeError: If no tool with the given name exists.
96
+ AttributeError: If no tool with the given name exists or if multiple tools match the given name .
96
97
"""
97
98
99
+ def find_normalized_tool_name () -> Optional [str ]:
100
+ """Lookup the tool represented by name, replacing characters with underscores as necessary."""
101
+ tool_registry = self ._agent .tool_registry .registry
102
+
103
+ if tool_registry .get (name , None ):
104
+ return name
105
+
106
+ # If the desired name contains underscores, it might be a placeholder for characters that can't be
107
+ # represented as python identifiers but are valid as tool names, such as dashes. In that case, find
108
+ # all tools that can be represented with the normalized name
109
+ if "_" in name :
110
+ filtered_tools = [
111
+ tool_name
112
+ for (tool_name , tool ) in tool_registry .items ()
113
+ if "-" in tool_name and tool_name .replace ("-" , "_" ) == name
114
+ ]
115
+
116
+ if len (filtered_tools ) > 1 :
117
+ raise AttributeError (f"Multiple tools matching '{ name } ' found: { ', ' .join (filtered_tools )} " )
118
+
119
+ if filtered_tools :
120
+ return filtered_tools [0 ]
121
+
122
+ raise AttributeError (f"Tool '{ name } ' not found" )
123
+
98
124
def caller (** kwargs : Any ) -> Any :
99
125
"""Call a tool directly by name.
100
126
@@ -115,14 +141,13 @@ def caller(**kwargs: Any) -> Any:
115
141
Raises:
116
142
AttributeError: If the tool doesn't exist.
117
143
"""
118
- if name not in self ._agent .tool_registry .registry :
119
- raise AttributeError (f"Tool '{ name } ' not found" )
144
+ normalized_name = find_normalized_tool_name ()
120
145
121
146
# Create unique tool ID and set up the tool request
122
147
tool_id = f"tooluse_{ name } _{ random .randint (100000000 , 999999999 )} "
123
148
tool_use = {
124
149
"toolUseId" : tool_id ,
125
- "name" : name ,
150
+ "name" : normalized_name ,
126
151
"input" : kwargs .copy (),
127
152
}
128
153
0 commit comments