Skip to content

Custom tools

Subclass Tool (pycodeloop.abc.tool.Tool):

from pycodeloop.abc.tool import Tool, ToolResult

class MyTool(Tool):
    name = "my_tool"
    description = "Does a thing."
    parameters = {
        "type": "object",
        "properties": {"x": {"type": "string"}},
        "required": ["x"],
    }

    def run(self, x: str) -> ToolResult:
        return ToolResult(output=f"did {x}")

parameters is a JSON schema — it's sent to the provider verbatim so the model knows what arguments to pass.

Making it dangerous

If the tool changes state, set dangerous = True and override preview() to summarize what will happen before it happens:

class DeployTool(Tool):
    name = "deploy"
    description = "Deploys the current branch to production."
    dangerous = True

    def preview(self, **kwargs) -> str:
        return f"Deploy branch {kwargs.get('branch', 'main')} to production"

    def run(self, branch: str = "main") -> ToolResult:
        ...
        return ToolResult(output=f"Deployed {branch}")

See Permission prompts for how preview() and the confirm hook interact.

Wiring it in

from pycodeloop import Config
from pycodeloop.core.tools import DEFAULT_TOOLS

config = Config(tools=DEFAULT_TOOLS + [MyTool()])

Or replace the built-in set entirely by passing only your own tools.