A ready-to-run example is available here!When using a remote agent server, custom tools must be importable by both the client process and the server process. This guide shows two ways to bring your own tools to the agent server: build a custom base image for source-mode development, or run a prebuilt/binary agent server image with an extra Python path that points at your tool modules.
For standalone custom tools (without remote agent server), see the Custom Tools guide.
How It Works
- Define custom tool with
register_tool()at module level - Make the module importable in the client and on the remote agent server
- Import the tool module in the client before creating the conversation so the SDK can include the toolโs module qualname in the remote request
- Start the server with the same module available through
PYTHONPATH,OH_EXTRA_PYTHON_PATH, or--extra-python-path - Server imports the module at startup or when a conversation is created, triggering registration
- Agent uses the tool remotely while execution happens inside the server workspace
Key Files
Custom Tool (custom_tools/log_data.py)
examples/02_remote_agent_server/06_custom_tool/custom_tools/log_data.py
Dockerfile
Running with a Prebuilt Binary Image
If you are using the publishedghcr.io/openhands/agent-server:* binary images, you do not need to rebuild the image just to load a .py file. Mount or copy your tool package into the container, then point the agent server at the parent directory with OH_EXTRA_PYTHON_PATH or --extra-python-path.
The value passed to
OH_EXTRA_PYTHON_PATH or --extra-python-path should be the directory that makes the module importable by its full module name. For custom_tools.log_data, use the parent directory that contains the custom_tools/ package. Multiple directories can be separated with the platform path separator (: on Linux/macOS, ; on Windows).Troubleshooting
| Issue | Solution |
|---|---|
| Tool not found | Ensure register_tool() is called at module level and import the tool module in the client before creating the conversation |
| Works in client but not on server | Make the same module path importable on the server; for binary images, mount/copy the tools and set OH_EXTRA_PYTHON_PATH or --extra-python-path |
| Import errors on server | Check PYTHONPATH, OH_EXTRA_PYTHON_PATH, or --extra-python-path; verify any third-party dependencies are installed in the server image |
| Build failures | Verify file paths in COPY commands, ensure Python 3.12+ |
For
DockerDevWorkspace with a custom base image, source mode is still the most convenient path because the tool code and dependencies are baked into the image before the server starts. For prebuilt or PyInstaller binary images, use OH_EXTRA_PYTHON_PATH or --extra-python-path to make external tool modules importable at runtime.Ready-to-run Example
This example is available on GitHub: examples/02_remote_agent_server/06_custom_tool/
examples/02_remote_agent_server/06_custom_tool/custom_tool_example.py
Running the Example
Next Steps
- Custom Tools (Standalone) - For local execution without remote server
- Agent Server Overview - Understanding remote agent servers

