# How to Create and Register Custom Tools in the Strix Tool Registry

> Learn to easily create and register custom tools in the Strix registry using the @register_tool decorator. Control sandbox, browser needs, and search with simple flags.

- Repository: [Strix/strix](https://github.com/usestrix/strix)
- Tags: how-to-guide
- Published: 2026-03-26

---

**Use the `@register_tool` decorator from [`strix/tools/registry.py`](https://github.com/usestrix/strix/blob/main/strix/tools/registry.py) on any Python function to automatically add it to the agent runtime, with optional flags to control sandbox execution, browser requirements, and web-search dependencies.**

Strix provides a centralized tool registry that automatically discovers and validates functions for agent consumption. Located in [`strix/tools/registry.py`](https://github.com/usestrix/strix/blob/main/strix/tools/registry.py), this registry enables developers to extend agent capabilities by writing plain Python functions and decorating them with `@register_tool`. This guide demonstrates how to create and register custom tools in the Strix tool registry while respecting environment constraints like sandbox mode and API availability.

## Understanding the Tool Registry Architecture

The Strix tool registry implements automatic discovery and conditional loading of tool-functions. According to the usestrix/strix source code, the registry handles four primary responsibilities:

- **Conditional registration** – evaluates sandbox mode, browser disabling, and Perplexity API key presence before adding tools
- **Module discovery** – records the tool's name, callable reference, and originating module (e.g., `terminal`, `web_search`)
- **XML schema loading** – attaches parameter descriptions from `*_schema.xml` files when not in sandbox mode
- **Parameter extraction** – parses required and optional arguments to power UI prompt rendering

The core registration logic resides in [`strix/tools/registry.py`](https://github.com/usestrix/strix/blob/main/strix/tools/registry.py), specifically within the `_should_register_tool` function (lines 75-89) and the `register_tool` decorator definition (lines 90-101).

## The @register_tool Decorator Explained

The `@register_tool` decorator evaluates environment conditions before adding a function to the internal `tools` list. It accepts three optional boolean parameters:

- `sandbox_execution` (default: `True`) – whether the tool runs in sandboxed environments
- `requires_browser_mode` (default: `False`) – whether the tool requires browser automation  
- `requires_web_search_mode` (default: `False`) – whether the tool requires a Perplexity API key

The decorator calls `_should_register_tool` to implement the following gating logic:

```python
def _should_register_tool(
    *,
    sandbox_execution: bool,
    requires_browser_mode: bool,
    requires_web_search_mode: bool,
) -> bool:
    sandbox_mode = _is_sandbox_mode()

    # Sandbox mode: only tools that explicitly allow sandbox execution are kept

    if sandbox_mode and not sandbox_execution:
        return False
    # Browser mode disabled → drop any tool that needs a browser

    if requires_browser_mode and _is_browser_disabled():
        return False
    # Web-search mode requires a Perplexity API key

    return not (requires_web_search_mode and not _has_perplexity_api())

```

When conditions pass, the decorator extracts the function name, module path, and optionally loads an XML schema file to populate the tool's metadata.

## Creating Your First Custom Tool

Building a custom tool requires three components: the Python implementation, optional XML schema documentation, and module registration.

### Writing the Python Function

Create a new file under `strix/tools/<category>/` with a typed function signature. The function must return a JSON-serializable dictionary that the agent runtime can process.

```python

# file: strix/tools/example/echo_actions.py

from strix.tools.registry import register_tool

@register_tool
def echo(message: str) -> dict[str, str]:
    """Return the input message unchanged."""
    return {"echo": message}

```

This minimal example uses default decorator settings, making it available in both sandbox and full execution modes.

### Adding XML Schema Definitions

For non-sandbox deployments, create a matching `*_schema.xml` file in the same directory. The registry loads this automatically to provide parameter descriptions to the UI layer.

```xml
<!-- file: strix/tools/example/echo_actions_schema.xml -->
<tool name="echo">
  <description>Return the input message unchanged.</description>
  <parameters>
    <parameter name="message" type="string" required="true"/>
  </parameters>
</tool>

```

If the schema file is missing while running in standard mode, the registry falls back to a placeholder message.

## Conditional Registration Patterns

Strix supports specialized execution contexts through decorator flags.

### Sandbox-Only Tools

Tools that perform filesystem operations or execute arbitrary code should disable sandbox execution to prevent security risks:

```python

# file: strix/tools/filesystem/dangerous_actions.py

from strix.tools.registry import register_tool

@register_tool(sandbox_execution=False)
def delete_file(path: str) -> dict[str, str]:
    """Delete a file at the specified path."""
    import os
    os.remove(path)
    return {"status": "deleted", "path": path}

```

### Browser-Dependent Tools

Tools requiring browser automation must specify `requires_browser_mode=True`. These automatically unregister when `STRIX_DISABLE_BROWSER=true`:

```python

# file: strix/tools/browser/open_url_actions.py

import webbrowser
from strix.tools.registry import register_tool

@register_tool(requires_browser_mode=True)
def open_url(url: str) -> dict[str, str]:
    """Open the given URL in the system browser."""
    webbrowser.open(url)
    return {"status": "opened", "url": url}

```

### Web-Search Tools

Tools integrating with Perplexity AI require both `sandbox_execution=False` and `requires_web_search_mode=True`:

```python

# file: strix/tools/web_search/custom_search_actions.py

import os
import requests
from strix.tools.registry import register_tool

@register_tool(sandbox_execution=False, requires_web_search_mode=True)
def custom_search(query: str) -> dict[str, str]:
    """Search the web using Perplexity AI."""
    api_key = os.getenv("PERPLEXITY_API_KEY")
    resp = requests.post(
        "https://api.perplexity.ai/chat/completions",
        headers={"Authorization": f"Bearer {api_key}"},
        json={
            "model": "sonar-small",
            "messages": [{"role": "user", "content": query}]
        },
        timeout=30,
    )
    return {"answer": resp.json()["choices"][0]["message"]["content"]}

```

## Activating Custom Tools

Registration occurs at module import time. To activate your custom tool, import it into [`strix/tools/__init__.py`](https://github.com/usestrix/strix/blob/main/strix/tools/__init__.py) or any module guaranteed to load at startup:

```python

# file: strix/tools/__init__.py

from .example.echo_actions import echo
from .browser.open_url_actions import open_url
from .web_search.custom_search_actions import custom_search

```

After import, the `get_tools_prompt()` function includes your tool in the generated system prompt, making it available to the agent.

## Summary

- **Use `@register_tool`** from [`strix/tools/registry.py`](https://github.com/usestrix/strix/blob/main/strix/tools/registry.py) to expose Python functions to the Strix agent runtime
- **Implement conditional logic** via `sandbox_execution`, `requires_browser_mode`, and `requires_web_search_mode` parameters to respect environment constraints
- **Provide XML schemas** in `*_schema.xml` files alongside your Python modules to enable rich UI descriptions in non-sandbox mode
- **Import the module** in [`strix/tools/__init__.py`](https://github.com/usestrix/strix/blob/main/strix/tools/__init__.py) to trigger registration at application startup
- **Reference test cases** in [`tests/tools/test_tool_registration_modes.py`](https://github.com/usestrix/strix/blob/main/tests/tools/test_tool_registration_modes.py) (lines 24-59) to understand how environment variables gate tool availability

## Frequently Asked Questions

### What happens if I don't provide an XML schema file?

If `STRIX_SANDBOX_MODE` is disabled and no schema file exists, the registry uses a placeholder description. The tool remains functional but lacks parameter documentation in the UI. In sandbox mode, schema loading is skipped entirely.

### Can I register multiple tools in the same file?

Yes. Apply `@register_tool` to each function in the module. Each decorator executes independently at import time, adding separate entries to the registry. Group related tools (e.g., all filesystem operations) in the same file under `strix/tools/<category>/`.

### Why isn't my tool appearing in the agent's tool list?

Verify that: (1) The module containing your tool is imported in [`strix/tools/__init__.py`](https://github.com/usestrix/strix/blob/main/strix/tools/__init__.py), (2) Environment flags match your decorator parameters (check `STRIX_SANDBOX_MODE`, `STRIX_DISABLE_BROWSER`, and `PERPLEXITY_API_KEY`), and (3) The function returns a dictionary or serializable object. Review the conditional logic in `_should_register_tool` in [`strix/tools/registry.py`](https://github.com/usestrix/strix/blob/main/strix/tools/registry.py) lines 75-89 to debug gating issues.

### Can I modify tool availability at runtime?

No. Registration occurs once at module import time when the `@register_tool` decorator executes. The internal `tools` list is populated during this phase based on environment variables present at startup. To change availability, you must restart the application with different environment variables (e.g., toggling `STRIX_SANDBOX_MODE`) or modify the import statements in [`strix/tools/__init__.py`](https://github.com/usestrix/strix/blob/main/strix/tools/__init__.py).