Tools API
Manage and execute tools
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api/v1/tools | List all tools |
| GET | /api/v1/tools/filters | Get filter options (types, categories, statuses, teams, creators) |
| GET | /api/v1/tools/legacy?team_id={team_id} | Legacy team tool list (grouped by kind) |
| GET | /api/v1/tools/builtin | List every builtin tool |
| GET | /api/v1/tools/file-parsers?team_id={team_id} | List tools usable as file-upload parsers |
| GET | /api/v1/tools/id/{tool_id} | Get tool details by ID |
| GET | /api/v1/tools/name/{tool_name}?team_id={team_id} | Get tool details by name |
| POST | /api/v1/tools/test | Test a tool once (no standalone execute endpoint) |
| POST | /api/v1/tools/execute-code | Run code directly in the sandbox |
| POST | /api/v1/tools?team_id={team_id} | Create a custom tool |
| PUT | /api/v1/tools/{tool_id} | Update tool configuration |
| DELETE | /api/v1/tools/{tool_id} | Delete a custom tool |
| POST | /api/v1/tools/{tool_id}/toggle | Toggle a tool's enabled state |
| POST | /api/v1/tools/{tool_id}/duplicate | Duplicate a tool (the copy starts disabled) |
| GET | /api/v1/tools/config?team_id={team_id} | List tool configurations (credentials) |
| GET | /api/v1/tools/config/{tool_name}?team_id={team_id} | Get one tool configuration |
| POST | /api/v1/tools/config?team_id={team_id} | Create a tool configuration |
| PUT | /api/v1/tools/config/{tool_name}?team_id={team_id} | Update a tool configuration |
| DELETE | /api/v1/tools/config/{tool_name}?team_id={team_id} | Delete a tool configuration |
| POST | /api/v1/tools/{tool_id}/share | Share a tool with another team |
| GET | /api/v1/tools/{tool_id}/shares | List shares for a tool |
| DELETE | /api/v1/tools/{tool_id}/share/{team_id} | Revoke a team's share |
| GET | /api/v1/tools/shared-with-me?team_id={team_id} | List tools shared with a team |
| POST | /api/v1/tools/mcp/list-tools | Discover an MCP server's tool definitions |
| POST | /api/v1/tools/database/test-connection | Test database connectivity |
Authentication
All endpoints require an authenticated JWT user session. API-key authentication is not accepted by these management and execution routes.
Required permissions:
tool:read— View toolstool:create— Create toolstool:update— Update toolstool:delete— Delete toolstool:execute— Execute/test tools
List Tools
Get a list of all available tools, with pagination, search, and multi-dimensional filtering.
Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 1 | Page number |
page_size | integer | No | 10 | Items per page (max: 100) |
search | string | No | - | Search by name or display name |
type | array | No | - | Filter by type: builtin, custom, mcp (repeatable) |
category | array | No | - | Filter by category (repeatable) |
status | array | No | - | Filter by enabled status (repeatable) |
team_id | array | No | - | Filter by owning team (repeatable) |
creator | array | No | - | Filter by creator (repeatable) |
Request Example
curl -X GET "https://your-domain.com/api/v1/tools?category=search" \
-H "Authorization: Bearer YOUR_TOKEN"Response
Success (200 OK):
{
"code": 0,
"data": {
"items": [
{
"id": "tool-123",
"name": "web_search",
"display_name": "Web Search",
"description": "Search the internet for information",
"type": "builtin",
"category": "search",
"icon": "🔍",
"parameters": [
{
"name": "query",
"type": "string",
"description": "Search query",
"required": true
},
{
"name": "max_results",
"type": "integer",
"description": "Maximum number of results",
"required": false,
"default": 5
}
],
"is_enabled": true,
"requires_config": false,
"config_fields": [],
"custom_type": null,
"http_config": null,
"code_config": null,
"mcp_config": null,
"team_id": null,
"created_by_id": null,
"created_by_name": null,
"is_owned": true,
"owner_team_id": null,
"owner_team_name": null,
"share_permission": null,
"shared_with_count": 0
}
],
"total": 15,
"page": 1,
"page_size": 10
},
"msg": "success"
}Tool Filter Options
GET /api/v1/tools/filtersRequires tool:read. Returns the filter options for the tools the caller can access, for building list-page filters.
{
"code": 0,
"data": {
"types": [
{ "value": "builtin", "label": "builtin" },
{ "value": "custom", "label": "custom" },
{ "value": "mcp", "label": "mcp" }
],
"categories": [{ "value": "search", "label": "search" }],
"statuses": [
{ "value": "enabled", "label": "enabled" },
{ "value": "disabled", "label": "disabled" }
],
"teams": [{ "value": "team-123", "label": "Engineering" }],
"creators": [{ "value": "alice", "label": "alice" }]
},
"msg": "success"
}categories is every defined tool category combined with any custom category present on accessible tools; teams lists teams the user can access; creators lists the distinct creator names of accessible tools.
List Legacy Team Tools
GET /api/v1/tools/legacy?team_id={team_id}Legacy compatibility endpoint returning a team's tools grouped by kind (builtin / custom / mcp). New integrations should prefer List Tools.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
team_id | string | Yes | - | Team UUID |
include_shared | boolean | No | true | Include tools shared with the team by other teams |
builtin always contains the full builtin tool list; custom and mcp contain the team's own tools (excluding other members' private tools) and, when include_shared=true, tools shared into the team.
List Builtin Tools
GET /api/v1/tools/builtinReturns every builtin tool (including the sandbox tools artifact, bash, edit, read, write). Builtin tools have no database record, so their objects have id: null and custom_type: null.
List File Parsers
GET /api/v1/tools/file-parsers?team_id={team_id}Returns the tools usable as document parsers for file uploads: builtin parsers (such as markitdown) plus the team's enabled custom tools with category=file. Requires tool:read and team membership.
Get Tool Details
Supports querying by tool ID or name. Name query requires an additional team_id parameter.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tool_id | string | Yes | Tool UUID (for GET /id/{tool_id}) |
tool_name | string | Yes | Tool name (for GET /name/{tool_name}) |
Request Example
curl -X GET "https://your-domain.com/api/v1/tools/id/tool-123" \
-H "Authorization: Bearer YOUR_TOKEN"Response
Success (200 OK):
{
"code": 0,
"data": {
"id": "tool-123",
"name": "web_search",
"display_name": "Web Search",
"description": "Search the internet for information",
"type": "builtin",
"category": "search",
"icon": "🔍",
"parameters": [...],
"is_enabled": true,
"requires_config": false,
"config_fields": [],
"custom_type": null,
"http_config": null,
"code_config": null,
"mcp_config": null,
"team_id": null,
"created_by_id": null,
"created_by_name": null,
"is_owned": true,
"owner_team_id": null,
"owner_team_name": null,
"share_permission": null,
"shared_with_count": 0,
"created_at": null,
"updated_at": null
},
"msg": "success"
}Test Tool
Execute a tool once by name with arguments. Note: There is no standalone POST /tools/{tool_id}/execute endpoint; use this unified interface instead.
Request Body
{
"name": "web_search",
"arguments": {
"query": "artificial intelligence",
"max_results": 5
}
}Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Tool name |
arguments | object | No | Tool arguments |
Request Example
curl -X POST "https://your-domain.com/api/v1/tools/test" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "web_search",
"arguments": {
"query": "artificial intelligence",
"max_results": 5
}
}'Response
Success (200 OK):
{
"code": 0,
"data": {
"name": "web_search",
"success": true,
"result": {
"results": [
{
"title": "Artificial Intelligence - Wikipedia",
"url": "https://en.wikipedia.org/wiki/Artificial_intelligence",
"snippet": "Artificial intelligence (AI) is intelligence demonstrated by machines..."
}
]
},
"error": null,
"logs": null,
"artifacts": [],
"duration_ms": 1200
},
"msg": "success"
}Error (400 Bad Request):
{
"code": 1001,
"data": {
"field": "arguments.query",
"error": "Query is required"
},
"msg": "Validation failed"
}Execute Code
Run JavaScript/Python code directly in the sandbox without saving a tool.
Request Body
{
"language": "python",
"code": "print(1 + 1)",
"params": {},
"timeout": 30,
"python_packages": ["requests"]
}Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
language | string | Yes | Code language: javascript, python |
code | string | Yes | Code content |
params | object | No | Input parameters |
timeout | number | No | Timeout in seconds (1-60, default: 30) |
command | array | No | Custom command (argv array) |
python_packages | array | No | Python packages to install |
js_packages | array | No | JavaScript packages to install |
python_package_index_url | string | No | Python package mirror URL |
node_package_registry_url | string | No | JavaScript package registry URL |
artifacts | array | No | Sandbox artifact configuration |
limits | object | No | Resource limits (timeout_seconds, disk_mb, max_stdout_kb, max_stderr_kb) |
Request Example
curl -X POST "https://your-domain.com/api/v1/tools/execute-code" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"language": "python",
"code": "print(1 + 1)"
}'Response
Success (200 OK):
{
"code": 0,
"data": {
"success": true,
"result": "2\n",
"error": null,
"logs": null,
"artifacts": [],
"duration_ms": 350
},
"msg": "success"
}Create Custom Tool
Create a custom tool. team_id is a required query parameter.
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
team_id | string | Yes | Team UUID that owns the tool |
Request Body
{
"name": "crm_lookup",
"display_name": "CRM Lookup",
"description": "Look up customer information in CRM",
"category": "data",
"type": "custom",
"custom_type": "http",
"icon": "👤",
"parameters": [
{
"name": "customer_id",
"type": "string",
"required": true,
"description": "Customer ID to lookup"
}
],
"http_config": {
"method": "GET",
"url": "https://api.crm.example.com/customers/{customer_id}",
"headers": {
"X-API-Key": "crm_..."
},
"timeout": 30
},
"credentials": {},
"is_enabled": true
}Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Tool name (unique identifier, max 100 chars) |
display_name | string | Yes | Display name (max 100 chars) |
description | string | No | Tool description |
icon | string | No | Icon (emoji or URL, max 100 chars) |
category | string | No | Tool category (default: other) |
type | string | No | Tool type: builtin, custom, mcp (default: custom) |
custom_type | string | No | Custom tool type: http, code, database (only for type=custom) |
visibility | string | No | Tool visibility: private or team (default: private) |
parameters | array | No | Parameter definitions (name, type, description, required, enum, default) |
http_config | object | No | HTTP config (method, url, headers, query_params, body_template, content_type, form_fields, timeout, response_path) |
code_config | object | No | Code config (language, code, command, python_packages, js_packages, python_package_index_url, node_package_registry_url, artifacts, limits) |
database_config | object | No | Database config (db_type, host, port, database, username, password, ssl, url, db, auth_source, timeout, max_limit) |
mcp_config | object | No | MCP Server config (transport, command, args, env, url, headers) |
credentials | object | No | Tool credentials |
is_enabled | boolean | No | Enabled status (default: true) |
name must match ^[a-zA-Z][a-zA-Z0-9_]*$ (starts with a letter, letters/digits/underscores only), otherwise 1001 tool_name_invalid_format; a duplicate name within the team returns 5001 tool_name_exists.
Request Example
curl -X POST "https://your-domain.com/api/v1/tools?team_id=team-123" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "crm_lookup",
"display_name": "CRM Lookup",
"description": "Look up customer information in CRM",
"category": "data",
"type": "custom",
"custom_type": "http",
"parameters": [
{
"name": "customer_id",
"type": "string",
"required": true
}
],
"http_config": {
"method": "GET",
"url": "https://api.crm.example.com/customers/{customer_id}"
}
}'Response
Success (200 OK):
{
"code": 0,
"data": {
"id": "tool-789",
"name": "crm_lookup",
"display_name": "CRM Lookup",
"description": "Look up customer information in CRM",
"type": "custom",
"category": "data",
"custom_type": "http",
"is_enabled": true,
"team_id": "team-123",
"created_at": "2026-02-11T16:00:00Z",
"updated_at": "2026-02-11T16:00:00Z",
"created_by_name": "alice"
},
"msg": "Tool created successfully"
}Update Tool
Update tool configuration. All fields are optional; include only the fields you want to update.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tool_id | string | Yes | Tool UUID |
Request Body
{
"display_name": "CRM Lookup (Updated)",
"is_enabled": true,
"http_config": {
"timeout": 60
}
}Request Example
curl -X PUT "https://your-domain.com/api/v1/tools/tool-789" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"display_name": "CRM Lookup (Updated)",
"is_enabled": true
}'Response
Success (200 OK):
{
"code": 0,
"data": {
"id": "tool-789",
"name": "crm_lookup",
"display_name": "CRM Lookup (Updated)",
"type": "custom",
"is_enabled": true,
"team_id": "team-123",
"created_at": "2026-02-11T16:00:00Z",
"updated_at": "2026-02-11T16:05:00Z",
"created_by_name": "alice"
},
"msg": "Tool updated successfully"
}Delete Tool
Delete a custom tool.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
tool_id | string | Yes | Tool UUID |
Request Example
curl -X DELETE "https://your-domain.com/api/v1/tools/tool-789" \
-H "Authorization: Bearer YOUR_TOKEN"Response
Success (200 OK):
{
"code": 0,
"data": null,
"msg": "Tool deleted successfully"
}Toggle Tool
POST /api/v1/tools/{tool_id}/toggleFlips a tool's enabled state. There is no request body. Only database-backed tools (custom, mcp) can be toggled; builtin tools are always enabled. The caller must be the tool creator or a team admin and hold tool:update.
curl -X POST "https://your-domain.com/api/v1/tools/tool-789/toggle" \
-H "Authorization: Bearer YOUR_TOKEN"Success (200 OK): returns the updated ToolDetailOut with is_enabled flipped and msg set to "Tool updated successfully".
Duplicate Tool
POST /api/v1/tools/{tool_id}/duplicateCopies a tool within its owning team. Requires tool:create and the admin role in the tool's team.
curl -X POST "https://your-domain.com/api/v1/tools/tool-789/duplicate" \
-H "Authorization: Bearer YOUR_TOKEN"Copy rules:
- Visibility is always
privateandis_enabledis alwaysfalse(enable it manually after copying). - The name gets a
_copysuffix, falling back to_copy_1,_copy_2, … until unique. - The display name gets a
(Copy)suffix. code_config,database_config,mcp_config, andcredentialsare copied.
Duplication copies credentials, so the copy inherits the original tool's secrets. Rotate or delete unneeded credentials after copying.
Cross-Team Tool Sharing
Share custom or MCP tools with other teams within the workspace. Sharing requires admin or owner role in the tool's owner team; a tool cannot be shared with its own team.
Share Tool
POST /api/v1/tools/{tool_id}/share| Field | Type | Required | Description |
|---|---|---|---|
team_id | string | Yes | Target team UUID |
permission | string | No | read_only (view and use) or read_execute (view, use, and see execution results), default read_only |
curl -X POST "https://your-domain.com/api/v1/tools/tool-789/share" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"team_id": "team-456", "permission": "read_execute"}'Returns the created share record with id, tool_id, tool_name, tool_display_name, shared_with_team_id, shared_with_team_name, permission, shared_by_id, shared_by_name, and shared_at.
List Shares for a Tool
GET /api/v1/tools/{tool_id}/sharesReturns { "shares": [...], "total": N }. Accessible only to members of the tool's owner team.
List Tools Shared With a Team
GET /api/v1/tools/shared-with-me?team_id={team_id}team_id is a required query parameter. Items in the list return is_owned: false, owner_team_id, owner_team_name, and share_permission.
Revoke Share
DELETE /api/v1/tools/{tool_id}/share/{team_id}Tool Configuration (Credentials)
Tool configurations store credentials (API keys, tokens) for builtin or database tools, either globally (superusers only) or per team.
GET /api/v1/tools/config?team_id={team_id}
GET /api/v1/tools/config/{tool_name}?team_id={team_id}
POST /api/v1/tools/config?team_id={team_id}
PUT /api/v1/tools/config/{tool_name}?team_id={team_id}
DELETE /api/v1/tools/config/{tool_name}?team_id={team_id}| Parameter | Location | Required | Description |
|---|---|---|---|
team_id | Query | No | Team UUID; omit to operate on the global configuration (superusers only) |
tool_name | Path | Yes (get/put/delete) | Tool name, e.g. web_search |
Create body:
{
"tool_name": "web_search",
"credentials": {
"TAVILY_API_KEY": "tvly-..."
}
}Update body contains only credentials:
{
"credentials": {
"TAVILY_API_KEY": "tvly-updated"
}
}Permissions and behavior:
- With
team_id, create/update/delete require the team admin role and reads require team membership. - Without
team_id, both reads and writes are limited to superusers. - Reading a team configuration for a known builtin tool name that has no record yet creates an empty configuration automatically; an unknown name returns
404. - Deleting returns
data: null.
MCP & Database Tool Diagnostics
Discover MCP Server Tools
POST /api/v1/tools/mcp/list-toolsConnect to an MCP server dynamically to inspect its declared tools before creating a tool record.
{
"mcp_config": {
"transport": "sse",
"command": null,
"args": [],
"env": {},
"url": "https://mcp.internal.example.com/sse",
"headers": {}
}
}mcp_config.transport accepts stdio, sse, and http: stdio uses command, args, and env; sse/http use url and headers.
The response returns tools (each with name, description, and input parameter schema), server_name, and server_version.
This endpoint initiates a real network request or process launch. Target URLs are subject to the deployment outbound network allowlist.
Test Database Tool Connection
POST /api/v1/tools/database/test-connection{
"db_type": "postgresql",
"host": "db.example.com",
"port": 5432,
"database": "analytics",
"username": "readonly",
"password": "secret_password",
"ssl": true,
"timeout": 15,
"max_limit": 100
}| Field | Type | Required | Description |
|---|---|---|---|
db_type | string | Yes | postgresql, mysql, redis, mongodb |
host | string | No | Hostname or IP |
port | integer | No | Port |
database | string | No | Database name |
username | string | No | Username |
password | string | No | Password |
ssl | string | boolean | No | SSL mode |
url | string | No | Connection URL for Redis or MongoDB (replaces host/port) |
db | integer | No | Redis database index |
auth_source | string | No | MongoDB authentication source |
timeout | integer | No | Query timeout in seconds (1–120, default 15) |
max_limit | integer | No | Maximum rows returned (1–1000, default 100) |
Returns 400 with msg set to the failure reason (such as database_connection_failed) when connection testing fails.
Error Codes
| Code | Message | Description |
|---|---|---|
4000 | Not found | Tool does not exist |
4004 | Team not found | Target team does not exist |
3000 | Permission denied | Insufficient permissions (sharing requires team admin) |
3003 | Team admin required | Admin role required in the tool owner team |
5001 | Already exists | A tool with the same name already exists in the team |
5104 | Duplicate name | The tool is already shared with that team, or the tool configuration already exists |
1001 | Validation failed | Invalid request data (including an invalid tool-name format) |
1002 | Bad request | Sharing to the tool's own team or failed connection test |
Note: No per-endpoint rate limits are implemented. There is no rate-limit middleware on these endpoints. Codes
6300-6306are reserved for SSO errors and are not used by the Tools API.
Code Examples
Python
import requests
def list_tools(token):
"""List all available tools."""
url = "https://your-domain.com/api/v1/tools"
headers = {
"Authorization": f"Bearer {token}"
}
response = requests.get(url, headers=headers)
result = response.json()
if result['code'] == 0:
return result['data']['items']
else:
raise Exception(f"Error: {result['msg']}")
def test_tool(token, name, arguments):
"""Execute a tool once."""
url = "https://your-domain.com/api/v1/tools/test"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
data = {
"name": name,
"arguments": arguments
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
if result['code'] == 0:
return result['data']['result']
else:
raise Exception(f"Error: {result['msg']}")
# Usage
tools = list_tools("YOUR_TOKEN")
for tool in tools:
print(f"Tool: {tool['display_name']} ({tool['category']})")
# Execute web search
result = test_tool(
"YOUR_TOKEN",
"web_search",
{"query": "artificial intelligence", "max_results": 5}
)
print(f"Search results: {result['results']}")JavaScript
async function listTools(token) {
const response = await fetch(
'https://your-domain.com/api/v1/tools',
{
headers: {
'Authorization': `Bearer ${token}`,
},
}
);
const result = await response.json();
if (result.code === 0) {
return result.data.items;
} else {
throw new Error(result.msg);
}
}
async function testTool(token, name, arguments) {
const response = await fetch(
'https://your-domain.com/api/v1/tools/test',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: name,
arguments: arguments,
}),
}
);
const result = await response.json();
if (result.code === 0) {
return result.data.result;
} else {
throw new Error(result.msg);
}
}
// Usage
const tools = await listTools('YOUR_TOKEN');
tools.forEach(tool => {
console.log(`Tool: ${tool.display_name} (${tool.category})`);
});
// Execute web search
const result = await testTool(
'YOUR_TOKEN',
'web_search',
{ query: 'artificial intelligence', max_results: 5 }
);
console.log('Search results:', result.results);Related Documentation
- Agent Configuration — Using tools with agents
- Tool Management — Tool admin
- Authentication — Authentication methods
How is this guide?