Skip to main content
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

  1. Define custom tool with register_tool() at module level
  2. Make the module importable in the client and on the remote agent server
  3. 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
  4. Start the server with the same module available through PYTHONPATH, OH_EXTRA_PYTHON_PATH, or --extra-python-path
  5. Server imports the module at startup or when a conversation is created, triggering registration
  6. 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 published ghcr.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.
You can pass the path as a CLI flag instead of an environment variable:
On the client side, import the same module before creating the remote conversation so the SDK knows which tool module qualname to send to the server:
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

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