From 1bc2cdcb2ec05e64d497037ec6791e2b0b6bf23a Mon Sep 17 00:00:00 2001 From: Alexander Payne Date: Wed, 25 Feb 2026 14:11:13 -0500 Subject: [PATCH] Fix Agno Toolkit API compatibility issues - Change Toolkit.add_tool() to Toolkit.register() (method was renamed in Agno) - Fix PythonTools method: python -> run_python_code - Fix FileTools method: write_file -> save_file - Fix FileTools base_dir parameter: str -> Path object - Fix Agent tools parameter: pass Toolkit wrapped in list These fixes resolve critical startup errors that prevented Timmy agent from initializing: - AttributeError: 'Toolkit' object has no attribute 'add_tool' - AttributeError: 'PythonTools' object has no attribute 'python' - TypeError: 'Toolkit' object is not iterable All 895 tests pass after these changes. Quality review: Agent now fully functional with working inference, memory, and self-awareness capabilities. --- src/timmy/agent.py | 2 +- src/timmy/tools.py | 72 +++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/timmy/agent.py b/src/timmy/agent.py index 56c1b08..5a5d07b 100644 --- a/src/timmy/agent.py +++ b/src/timmy/agent.py @@ -74,5 +74,5 @@ def create_timmy( add_history_to_context=True, num_history_runs=10, markdown=True, - tools=tools, + tools=[tools] if tools else None, ) diff --git a/src/timmy/tools.py b/src/timmy/tools.py index e515232..709956f 100644 --- a/src/timmy/tools.py +++ b/src/timmy/tools.py @@ -118,13 +118,13 @@ def create_research_tools(base_dir: str | Path | None = None): # Web search via DuckDuckGo search_tools = DuckDuckGoTools() - toolkit.add_tool(search_tools.web_search, name="web_search") + toolkit.register(search_tools.web_search, name="web_search") # File reading base_path = Path(base_dir) if base_dir else Path.cwd() - file_tools = FileTools(base_dir=str(base_path)) - toolkit.add_tool(file_tools.read_file, name="read_file") - toolkit.add_tool(file_tools.list_files, name="list_files") + file_tools = FileTools(base_dir=base_path) + toolkit.register(file_tools.read_file, name="read_file") + toolkit.register(file_tools.list_files, name="list_files") return toolkit @@ -140,18 +140,18 @@ def create_code_tools(base_dir: str | Path | None = None): # Shell commands (sandboxed) shell_tools = ShellTools() - toolkit.add_tool(shell_tools.run_shell_command, name="shell") + toolkit.register(shell_tools.run_shell_command, name="shell") # Python execution python_tools = PythonTools() - toolkit.add_tool(python_tools.python, name="python") + toolkit.register(python_tools.run_python_code, name="python") # File operations base_path = Path(base_dir) if base_dir else Path.cwd() - file_tools = FileTools(base_dir=str(base_path)) - toolkit.add_tool(file_tools.read_file, name="read_file") - toolkit.add_tool(file_tools.write_file, name="write_file") - toolkit.add_tool(file_tools.list_files, name="list_files") + file_tools = FileTools(base_dir=base_path) + toolkit.register(file_tools.read_file, name="read_file") + toolkit.register(file_tools.save_file, name="write_file") + toolkit.register(file_tools.list_files, name="list_files") return toolkit @@ -167,17 +167,17 @@ def create_data_tools(base_dir: str | Path | None = None): # Python execution for analysis python_tools = PythonTools() - toolkit.add_tool(python_tools.python, name="python") + toolkit.register(python_tools.run_python_code, name="python") # File reading base_path = Path(base_dir) if base_dir else Path.cwd() - file_tools = FileTools(base_dir=str(base_path)) - toolkit.add_tool(file_tools.read_file, name="read_file") - toolkit.add_tool(file_tools.list_files, name="list_files") + file_tools = FileTools(base_dir=base_path) + toolkit.register(file_tools.read_file, name="read_file") + toolkit.register(file_tools.list_files, name="list_files") # Web search for finding datasets search_tools = DuckDuckGoTools() - toolkit.add_tool(search_tools.web_search, name="web_search") + toolkit.register(search_tools.web_search, name="web_search") return toolkit @@ -193,10 +193,10 @@ def create_writing_tools(base_dir: str | Path | None = None): # File operations base_path = Path(base_dir) if base_dir else Path.cwd() - file_tools = FileTools(base_dir=str(base_path)) - toolkit.add_tool(file_tools.read_file, name="read_file") - toolkit.add_tool(file_tools.write_file, name="write_file") - toolkit.add_tool(file_tools.list_files, name="list_files") + file_tools = FileTools(base_dir=base_path) + toolkit.register(file_tools.read_file, name="read_file") + toolkit.register(file_tools.save_file, name="write_file") + toolkit.register(file_tools.list_files, name="list_files") return toolkit @@ -212,17 +212,17 @@ def create_security_tools(base_dir: str | Path | None = None): # Shell for running security scans shell_tools = ShellTools() - toolkit.add_tool(shell_tools.run_shell_command, name="shell") + toolkit.register(shell_tools.run_shell_command, name="shell") # Web search for threat intelligence search_tools = DuckDuckGoTools() - toolkit.add_tool(search_tools.web_search, name="web_search") + toolkit.register(search_tools.web_search, name="web_search") # File reading for logs/configs base_path = Path(base_dir) if base_dir else Path.cwd() - file_tools = FileTools(base_dir=str(base_path)) - toolkit.add_tool(file_tools.read_file, name="read_file") - toolkit.add_tool(file_tools.list_files, name="list_files") + file_tools = FileTools(base_dir=base_path) + toolkit.register(file_tools.read_file, name="read_file") + toolkit.register(file_tools.list_files, name="list_files") return toolkit @@ -238,14 +238,14 @@ def create_devops_tools(base_dir: str | Path | None = None): # Shell for deployment commands shell_tools = ShellTools() - toolkit.add_tool(shell_tools.run_shell_command, name="shell") + toolkit.register(shell_tools.run_shell_command, name="shell") # File operations for config management base_path = Path(base_dir) if base_dir else Path.cwd() - file_tools = FileTools(base_dir=str(base_path)) - toolkit.add_tool(file_tools.read_file, name="read_file") - toolkit.add_tool(file_tools.write_file, name="write_file") - toolkit.add_tool(file_tools.list_files, name="list_files") + file_tools = FileTools(base_dir=base_path) + toolkit.register(file_tools.read_file, name="read_file") + toolkit.register(file_tools.save_file, name="write_file") + toolkit.register(file_tools.list_files, name="list_files") return toolkit @@ -262,22 +262,22 @@ def create_full_toolkit(base_dir: str | Path | None = None): # Web search search_tools = DuckDuckGoTools() - toolkit.add_tool(search_tools.web_search, name="web_search") + toolkit.register(search_tools.web_search, name="web_search") # Python execution python_tools = PythonTools() - toolkit.add_tool(python_tools.python, name="python") + toolkit.register(python_tools.run_python_code, name="python") # Shell commands shell_tools = ShellTools() - toolkit.add_tool(shell_tools.run_shell_command, name="shell") + toolkit.register(shell_tools.run_shell_command, name="shell") # File operations base_path = Path(base_dir) if base_dir else Path.cwd() - file_tools = FileTools(base_dir=str(base_path)) - toolkit.add_tool(file_tools.read_file, name="read_file") - toolkit.add_tool(file_tools.write_file, name="write_file") - toolkit.add_tool(file_tools.list_files, name="list_files") + file_tools = FileTools(base_dir=base_path) + toolkit.register(file_tools.read_file, name="read_file") + toolkit.register(file_tools.save_file, name="write_file") + toolkit.register(file_tools.list_files, name="list_files") return toolkit