"""Meta-tool: dynamically create new tools at runtime.""" from __future__ import annotations import importlib import textwrap from pathlib import Path from . import tool @tool("build_tool", "Create a new tool from a description. The agent writes Python code with @tool decorator.", category="meta") def build_tool(name: str, description: str, code: str, ctx: dict = None) -> str: """Generate a new tool module and hot-load it. Args: name: Tool name (snake_case) description: What the tool does code: Full Python code for the tool function (must use @tool decorator) """ if not name.isidentifier(): return f"Invalid tool name: {name}. Must be a valid Python identifier." # Wrap code in a module with the import module_code = textwrap.dedent(f'''\ """Auto-generated tool: {description}""" from __future__ import annotations from . import tool {code} ''') # Write to tools directory tools_dir = Path(__file__).parent file_path = tools_dir / f"{name}.py" if file_path.exists(): return f"Tool module '{name}' already exists. Choose a different name." file_path.write_text(module_code, encoding="utf-8") # Hot-import the new module try: importlib.import_module(f".{name}", package=__package__) return f"Tool '{name}' created and loaded successfully at {file_path}" except Exception as e: # Clean up on failure file_path.unlink(missing_ok=True) return f"Failed to load tool '{name}': {e}"