Skip to content
Python Custom Tools

Python Custom Tools

Python custom tools let you write full Python code that runs inside a Docker sandbox. Unlike HTTP custom tools that call external APIs, Python tools can perform complex logic, data transformations, calculations, and multi-step operations — all within an isolated container.

Creating a Python Tool

Navigate to Tools in the sidebar and click New Custom Tool. The creation wizard offers three paths:

  • HTTP Request — Create a tool that calls an external API via HTTP (existing flow).
  • Tool Builder — Describe what you need and a specialised assistant writes the code for you.
  • Write Python — Start from a template and write the tool code yourself in a code editor.

Write Python

Click Write Python to open the code editor. The form has these sections:

Basic Info

  • Display Name — A human-friendly name shown in the UI.
  • Tool Name Suffix — The tool identifier in snake_case. Automatically prefixed with custom_ (e.g. fetch_price becomes custom_fetch_price).
  • Description — Describe what the tool does. This is shown to the AI assistant.
  • Category — Optional grouping for the tools list.

Source Code

Write a Python class that inherits from BaseTool. The editor includes syntax highlighting and starts with a working template:

from typing import Any
from base import BaseTool, SandboxToolContext


class MyTool(BaseTool):
    """Description of what this tool does."""

    name = "custom_example"
    description = "What this tool does, explained to the AI assistant."
    category = "Custom"
    input_schema: dict[str, Any] = {
        "type": "object",
        "properties": {
            "param1": {
                "type": "string",
                "description": "Description of param1.",
            },
        },
        "required": ["param1"],
    }

    def execute(self, params: dict[str, Any], ctx: SandboxToolContext) -> str:
        """Execute the tool.

        Args:
            params: Tool input parameters matching input_schema.
            ctx: Sandbox execution context.

        Returns:
            Result string.
        """
        return f"Result: {params['param1']}"
Import from base, not app.plugins.base. The sandbox provides its own minimal base module with BaseTool and SandboxToolContext.

Requirements

Your class must have:

AttributeDescription
nameString starting with custom_ in snake_case
descriptionString describing the tool for the AI assistant
input_schemaJSON Schema dict defining the input parameters
execute()Method that takes params and ctx, returns a string

The source code is validated before saving. The validator checks syntax, class structure, and rejects obviously dangerous patterns (like subprocess calls). The Docker sandbox is the real security boundary — validation provides defense-in-depth and better error messages.

Settings

  • Allow Network Access — Enable this if the tool needs to call external APIs. Disabled by default.
  • Timeout — Maximum execution time (1–120 seconds, default 30).
  • Active — Toggle the tool on or off.

Tool Builder

The Tool Builder is a specialised assistant that writes Python tools for you. Click Tool Builder in the creation wizard to open a dedicated split-pane interface for AI-assisted tool creation. No setup is required; the Tool Builder assistant is created automatically on first use.

The Tool Builder Interface

The Tool Builder has two panes:

  • Left pane — A multi-turn chat with the Tool Builder. Describe the tool you need, ask for changes, and iterate until you’re happy.
  • Right pane — A code editor (with syntax highlighting) that shows the latest AI-generated code, plus an Info tab with extracted metadata like the tool name, description, and input schema.

Workflow

  1. Click Tool Builder in the creation wizard (or navigate to Tools → Tool Builder).

  2. Describe the tool you need. For example:

    “Create a tool called fetch_stock_price that takes a ticker parameter and returns the current stock price using the Alpha Vantage API. It needs network access.”

  3. The Tool Builder writes the Python code, tests it in the sandbox, and displays it in the editor pane.

  4. You can edit the code directly in the editor. When you send another message, the Tool Builder sees your changes and responds accordingly.

  5. Continue the conversation to iterate — ask for new parameters, better error handling, or different behaviour.

  6. When the code passes testing, the Tool Builder saves it automatically. The session is marked Complete and a link to the saved tool appears in the status bar.

The new tool appears immediately in the tools list and can be enabled for any assistant.

Sessions

Each Tool Builder conversation is tracked as a session. Navigate to Tools → Tool Builder to see your recent sessions and resume any previous conversation. Sessions show their current status:

  • In Progress — The conversation is ongoing.
  • Complete — The tool has been saved successfully.

SandboxToolContext

The ctx parameter passed to execute() provides context about the current execution:

FieldTypeDescription
projectdict or None{"id": ..., "name": ...}
conversation_idint or NoneCurrent conversation ID
assistantdict or None{"id": ..., "name": ...}
userdict or None{"id": ..., "email": ...}
plugin_configdictAlways {} for custom tools
app_configdictAlways {} for custom tools

Available Packages

The sandbox image includes these pre-installed packages:

requests, beautifulsoup4, lxml, pandas, numpy, openpyxl, Pillow, pyyaml, python-dateutil, chardet, html2text, markdown, jinja2, pydantic, httpx, feedparser

Plus the full Python standard library.

Testing

From the Python tool’s detail page, use the Test panel to run the tool in the sandbox. Enter parameters as JSON and click Run Test to see the result. Test results (output and timestamp) are saved for reference.

Sandbox Execution

Python custom tools always run in a Docker sandbox. This provides:

  • Isolation — Tools cannot access the host file system, database, or other containers.
  • Network control — Network access is disabled by default and enabled per-tool.
  • Timeouts — Each execution has a configurable time limit.
  • No persistent state — Each execution starts fresh.

For more about sandbox configuration, see the Sandbox documentation.