*_custom_tool tools).
Before you write code, call
List Custom Tool Runtimes
(GET /v1/custom-tools/runtimes). It returns the exact signature, return
contract, starter template, built-in modules, and installable packages for each
language, straight from the runtime, so you never have to guess.
The function signature
Every tool defines a single entrypoint namedmain. The parameters you declare
on the tool are passed in to it.
| Language | Entrypoint | Parameters arrive as |
|---|---|---|
| Python | def main(**params) | keyword arguments (params dict) |
| JavaScript | async function main(params) | a single params object |
The return shape
main must return an object/dict containing a string message key. The
message is what the agent reads back. Optionally include a rawData key with
structured data for the agent to reason over.
main entrypoint and a return
statement. When the tool runs, a return value without a string message key
will fail runtime validation.
Parameters
Declare each parameter your tool accepts in theparameters map. The keys become
the fields available inside main.
| Field | Required | Meaning |
|---|---|---|
type | yes | string, number, boolean, object, or array. |
required | yes | Whether the agent must supply the value. |
description | yes | Shown to the model so it fills the value correctly. |
enum_values | no | A closed set of allowed string values. |
execution_message_description | no | Per-parameter note shown while the tool runs. |
Available dependencies
The full, authoritative list per language is returned byGET /v1/custom-tools/runtimes. In
short:
- Standard library modules are always importable with no install step
(Python:
json,math,datetime,re,urllib, …; JavaScript:fs,path,crypto,https, …). - A curated set of third-party packages installs automatically the first
time you import it. For Python this includes
requests,httpx,numpy,pandas, and more. JavaScript tools run on Bun with its built-in modules.
Naming rules
Tool names are lowercase kebab-case: letters, numbers, and single hyphens only (for examplelookup-order-status). No spaces, no uppercase, no leading,
trailing, or consecutive hyphens. The name is how the agent references the tool,
and it must be unique within the workspace.
Lifecycle
POST /v1/custom-tools(orcreate_custom_tool) creates the tool.PATCH /v1/custom-tools/{id}updates it. Changingcodebumps the tool’sversion.- Set
enable_globally: trueto make the tool available to every agent in the workspace without per-agent enablement. DELETE /v1/custom-tools/{id}removes the tool and its access-control rows.
Turning a tool on for an agent
Creating a custom tool does not automatically expose it to your agents. Chat agents are opt-in: a tool is disabled until you turn it on for that agent.GET /v1/agents/{id}/toolslists the built-in and custom tools an agent can resolve, each with itsenabledstate.PATCH /v1/agents/{id}/toolstoggles one tool for that agent. Identify it by the(tool_name, source)pair, wheresourceisbuiltinorcustom.
list_agent_tools and set_agent_tool_access tools.