curl --request POST \
--url https://api.conduit.ai/v1/custom-tools \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"workspace_id": "j57demo8f8x7c9v0n2q4r6t8y1u3i5o",
"name": "lookup-order-status",
"description": "Look up the fulfillment status of an order by id.",
"language": "python",
"code": "def main(**params):\n order_id = params[\"order_id\"]\n return {\"message\": f\"Order {order_id} is shipped\"}",
"parameters": {
"order_id": {
"type": "string",
"required": true,
"description": "The order id to look up."
}
},
"execution_message_description": "Looking up order status",
"enable_globally": false
}
'import requests
url = "https://api.conduit.ai/v1/custom-tools"
payload = {
"workspace_id": "j57demo8f8x7c9v0n2q4r6t8y1u3i5o",
"name": "lookup-order-status",
"description": "Look up the fulfillment status of an order by id.",
"language": "python",
"code": "def main(**params):
order_id = params[\"order_id\"]
return {\"message\": f\"Order {order_id} is shipped\"}",
"parameters": { "order_id": {
"type": "string",
"required": True,
"description": "The order id to look up."
} },
"execution_message_description": "Looking up order status",
"enable_globally": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
workspace_id: 'j57demo8f8x7c9v0n2q4r6t8y1u3i5o',
name: 'lookup-order-status',
description: 'Look up the fulfillment status of an order by id.',
language: 'python',
code: 'def main(**params):\n order_id = params["order_id"]\n return {"message": f"Order {order_id} is shipped"}',
parameters: {
order_id: {type: 'string', required: true, description: 'The order id to look up.'}
},
execution_message_description: 'Looking up order status',
enable_globally: false
})
};
fetch('https://api.conduit.ai/v1/custom-tools', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.conduit.ai/v1/custom-tools",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'workspace_id' => 'j57demo8f8x7c9v0n2q4r6t8y1u3i5o',
'name' => 'lookup-order-status',
'description' => 'Look up the fulfillment status of an order by id.',
'language' => 'python',
'code' => 'def main(**params):
order_id = params["order_id"]
return {"message": f"Order {order_id} is shipped"}',
'parameters' => [
'order_id' => [
'type' => 'string',
'required' => true,
'description' => 'The order id to look up.'
]
],
'execution_message_description' => 'Looking up order status',
'enable_globally' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.conduit.ai/v1/custom-tools"
payload := strings.NewReader("{\n \"workspace_id\": \"j57demo8f8x7c9v0n2q4r6t8y1u3i5o\",\n \"name\": \"lookup-order-status\",\n \"description\": \"Look up the fulfillment status of an order by id.\",\n \"language\": \"python\",\n \"code\": \"def main(**params):\\n order_id = params[\\\"order_id\\\"]\\n return {\\\"message\\\": f\\\"Order {order_id} is shipped\\\"}\",\n \"parameters\": {\n \"order_id\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"The order id to look up.\"\n }\n },\n \"execution_message_description\": \"Looking up order status\",\n \"enable_globally\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.conduit.ai/v1/custom-tools")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"workspace_id\": \"j57demo8f8x7c9v0n2q4r6t8y1u3i5o\",\n \"name\": \"lookup-order-status\",\n \"description\": \"Look up the fulfillment status of an order by id.\",\n \"language\": \"python\",\n \"code\": \"def main(**params):\\n order_id = params[\\\"order_id\\\"]\\n return {\\\"message\\\": f\\\"Order {order_id} is shipped\\\"}\",\n \"parameters\": {\n \"order_id\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"The order id to look up.\"\n }\n },\n \"execution_message_description\": \"Looking up order status\",\n \"enable_globally\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.conduit.ai/v1/custom-tools")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"workspace_id\": \"j57demo8f8x7c9v0n2q4r6t8y1u3i5o\",\n \"name\": \"lookup-order-status\",\n \"description\": \"Look up the fulfillment status of an order by id.\",\n \"language\": \"python\",\n \"code\": \"def main(**params):\\n order_id = params[\\\"order_id\\\"]\\n return {\\\"message\\\": f\\\"Order {order_id} is shipped\\\"}\",\n \"parameters\": {\n \"order_id\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"The order id to look up.\"\n }\n },\n \"execution_message_description\": \"Looking up order status\",\n \"enable_globally\": false\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "kg77c0dy0mgdpzmqz6tesry8w184002s",
"workspace_id": "j57demo8f8x7c9v0n2q4r6t8y1u3i5o",
"name": "lookup-order-status",
"description": "Look up the fulfillment status of an order by id.",
"language": "python",
"code": "def main(**params):\n order_id = params[\"order_id\"]\n # ... fetch status ...\n return {\n \"message\": f\"Order {order_id} is shipped\",\n \"rawData\": {\"status\": \"shipped\"},\n }",
"parameters": {
"order_id": {
"type": "string",
"required": true,
"description": "The order id to look up."
}
},
"execution_message_description": "Looking up order status",
"enable_globally": false,
"validated": true,
"version": 1,
"created_at": "2026-04-01T17:22:10.000Z"
}
}{
"error": "Invalid workspace id"
}{
"error": "Invalid workspace id"
}{
"error": "Invalid workspace id"
}{
"error": "Invalid workspace id"
}{
"error": "Invalid workspace id"
}Create Custom Tool
Creates a custom code tool from Python or JavaScript source. Requires a token with write access. See List Custom Tool Runtimes for the code contract.
curl --request POST \
--url https://api.conduit.ai/v1/custom-tools \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"workspace_id": "j57demo8f8x7c9v0n2q4r6t8y1u3i5o",
"name": "lookup-order-status",
"description": "Look up the fulfillment status of an order by id.",
"language": "python",
"code": "def main(**params):\n order_id = params[\"order_id\"]\n return {\"message\": f\"Order {order_id} is shipped\"}",
"parameters": {
"order_id": {
"type": "string",
"required": true,
"description": "The order id to look up."
}
},
"execution_message_description": "Looking up order status",
"enable_globally": false
}
'import requests
url = "https://api.conduit.ai/v1/custom-tools"
payload = {
"workspace_id": "j57demo8f8x7c9v0n2q4r6t8y1u3i5o",
"name": "lookup-order-status",
"description": "Look up the fulfillment status of an order by id.",
"language": "python",
"code": "def main(**params):
order_id = params[\"order_id\"]
return {\"message\": f\"Order {order_id} is shipped\"}",
"parameters": { "order_id": {
"type": "string",
"required": True,
"description": "The order id to look up."
} },
"execution_message_description": "Looking up order status",
"enable_globally": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
workspace_id: 'j57demo8f8x7c9v0n2q4r6t8y1u3i5o',
name: 'lookup-order-status',
description: 'Look up the fulfillment status of an order by id.',
language: 'python',
code: 'def main(**params):\n order_id = params["order_id"]\n return {"message": f"Order {order_id} is shipped"}',
parameters: {
order_id: {type: 'string', required: true, description: 'The order id to look up.'}
},
execution_message_description: 'Looking up order status',
enable_globally: false
})
};
fetch('https://api.conduit.ai/v1/custom-tools', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.conduit.ai/v1/custom-tools",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'workspace_id' => 'j57demo8f8x7c9v0n2q4r6t8y1u3i5o',
'name' => 'lookup-order-status',
'description' => 'Look up the fulfillment status of an order by id.',
'language' => 'python',
'code' => 'def main(**params):
order_id = params["order_id"]
return {"message": f"Order {order_id} is shipped"}',
'parameters' => [
'order_id' => [
'type' => 'string',
'required' => true,
'description' => 'The order id to look up.'
]
],
'execution_message_description' => 'Looking up order status',
'enable_globally' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.conduit.ai/v1/custom-tools"
payload := strings.NewReader("{\n \"workspace_id\": \"j57demo8f8x7c9v0n2q4r6t8y1u3i5o\",\n \"name\": \"lookup-order-status\",\n \"description\": \"Look up the fulfillment status of an order by id.\",\n \"language\": \"python\",\n \"code\": \"def main(**params):\\n order_id = params[\\\"order_id\\\"]\\n return {\\\"message\\\": f\\\"Order {order_id} is shipped\\\"}\",\n \"parameters\": {\n \"order_id\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"The order id to look up.\"\n }\n },\n \"execution_message_description\": \"Looking up order status\",\n \"enable_globally\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.conduit.ai/v1/custom-tools")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"workspace_id\": \"j57demo8f8x7c9v0n2q4r6t8y1u3i5o\",\n \"name\": \"lookup-order-status\",\n \"description\": \"Look up the fulfillment status of an order by id.\",\n \"language\": \"python\",\n \"code\": \"def main(**params):\\n order_id = params[\\\"order_id\\\"]\\n return {\\\"message\\\": f\\\"Order {order_id} is shipped\\\"}\",\n \"parameters\": {\n \"order_id\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"The order id to look up.\"\n }\n },\n \"execution_message_description\": \"Looking up order status\",\n \"enable_globally\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.conduit.ai/v1/custom-tools")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"workspace_id\": \"j57demo8f8x7c9v0n2q4r6t8y1u3i5o\",\n \"name\": \"lookup-order-status\",\n \"description\": \"Look up the fulfillment status of an order by id.\",\n \"language\": \"python\",\n \"code\": \"def main(**params):\\n order_id = params[\\\"order_id\\\"]\\n return {\\\"message\\\": f\\\"Order {order_id} is shipped\\\"}\",\n \"parameters\": {\n \"order_id\": {\n \"type\": \"string\",\n \"required\": true,\n \"description\": \"The order id to look up.\"\n }\n },\n \"execution_message_description\": \"Looking up order status\",\n \"enable_globally\": false\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "kg77c0dy0mgdpzmqz6tesry8w184002s",
"workspace_id": "j57demo8f8x7c9v0n2q4r6t8y1u3i5o",
"name": "lookup-order-status",
"description": "Look up the fulfillment status of an order by id.",
"language": "python",
"code": "def main(**params):\n order_id = params[\"order_id\"]\n # ... fetch status ...\n return {\n \"message\": f\"Order {order_id} is shipped\",\n \"rawData\": {\"status\": \"shipped\"},\n }",
"parameters": {
"order_id": {
"type": "string",
"required": true,
"description": "The order id to look up."
}
},
"execution_message_description": "Looking up order status",
"enable_globally": false,
"validated": true,
"version": 1,
"created_at": "2026-04-01T17:22:10.000Z"
}
}{
"error": "Invalid workspace id"
}{
"error": "Invalid workspace id"
}{
"error": "Invalid workspace id"
}{
"error": "Invalid workspace id"
}{
"error": "Invalid workspace id"
}Authorizations
Conduit API token. Use Authorization: Bearer <token>. Read/write endpoints require a token with write access.
Body
Request body for creating a custom code tool. Requires a token with write access.
Unique tool name within the workspace. Lowercase kebab-case (e.g. lookup-order-status), at most 64 characters. This is how the agent references the tool.
1 - 64^[a-z0-9]+(?:-[a-z0-9]+)*$Runtime the tool's code is executed in. Determines the entrypoint signature and which dependencies are available (see GET /v1/custom-tools/runtimes).
python, javascript The tool's source code. Must define a single entrypoint named main.
Python: def main(**params): — parameters arrive as keyword args. Return a dict containing a string message key, optionally a rawData key with structured data.
JavaScript: async function main(params) { ... } — parameters arrive as a single object. Return an object containing a string message key, optionally a rawData key.
Writes statically validate that the code defines main and includes a return statement; runtime execution validates the returned object.
Standard library modules are always importable. A curated set of third-party packages installs automatically on first import. Query GET /v1/custom-tools/runtimes for the exact signature, return contract, and available dependencies per language.
11024Parameters the tool accepts, keyed by parameter name. Each becomes a key in the params object/dict passed to main.
Show child attributes
Show child attributes
Short status line shown to the user while the tool runs, e.g. Looking up order status.
When true, the tool is available to every agent in the workspace without per-agent enablement.
Response
Custom tool created
Single custom code tool response.
Show child attributes
Show child attributes
Was this page helpful?