Custom tools
By the end of this page one of your project’s tools will execute on your own infrastructure — which is what makes it possible for an agent to call an internal API or query a private database.
Prerequisites
- An executor showing Online.
- A custom tool, or the intent to create one. See Tools.
Point the tool at an executor
The setting is on the tool itself, so every agent that calls the tool inherits it. You don’t set it per agent.
Open the tool
Agentic Workspace → Agent Tools, then create a new tool or open an existing one for editing.
Set Execution Location
| Option | Effect |
|---|---|
| Auto (Platform Decides) | Defers to the project default. |
| Local (Platform) | Always runs on the hosted runtime. |
| Remote (Executor) | Runs on one of your executors. |
Pick a target, or don’t
Remote reveals the executor picker. Any (round-robin) spreads calls across your online executors; picking one by name pins the tool to it.
If no executors are online you’ll see “No remote executors registered. Add an executor in Project Settings → Executors.”
Both tool types can go remote
The Execution Location is independent of what the tool is:
- HTTP tools make their request from your network, so they can call an internal service that has no public address. This is the most common reason to use an executor.
- Python tools run their handler on the executor, with access to whatever that host can reach.
Python tools running remotely have the same limitation as remote code nodes — ctx["db"], ctx["llm"] and ctx["config"] aren’t available. The tool builder shows this warning when you combine a Python tool with Remote execution. Use {'{{'} config.xxx {'}}'} templates for secrets instead; they’re resolved on the platform before the call is dispatched.
Either way, secrets stay on the platform. Connection strings, API keys and headers are substituted into the request before it’s sent to the executor, so the executor never reads your secret store.
Test it before you ship it
The tool builder’s Test button honours the Execution Location. With Remote selected, the test runs on your executor exactly as a real call would — the same dispatch path, the same network position.
That makes it the quickest way to answer “can this executor actually reach our database?” without building an agent first. It also produces a real execution record, so the run shows up in monitoring alongside production traffic.
If no executor is online
Unlike a code node, a tool falls back to the platform and runs locally — unless it’s pinned to a specific executor, in which case it fails.
| Setup | No executor online |
|---|---|
| Remote, target Any | Runs on the platform |
| Remote, pinned to one executor | Fails |
The distinction is about intent. Pinning says “it must be this host”; leaving it open says “anywhere is fine”, and the platform is somewhere. If the tool exists specifically to reach something private, pin it — a silent fallback would fail against the wrong network, or worse, succeed against the wrong data.
When a fallback does happen and the local attempt also fails, the error keeps the original remote failure attached so you can see which one is the real cause.
Common issues
- The tool works in test but not from an agent — check the agent has the tool attached. Execution Location is a property of the tool, not of the agent.
- Connection refused / timeout from an HTTP tool — the executor’s host can’t reach the target. Test connectivity from the host itself, not from your laptop.
- It ran on the platform when you expected remote — no executor was online and the tool wasn’t pinned, so it fell back. Pin it if that shouldn’t be allowed.
ModuleNotFoundErrorin a Python tool — the package isn’t on the executor. Add it to the image orQRAPTOR_EXTRA_PACKAGES.
Next
- MCP servers — reach an MCP server that only exists inside your network.