> ## Documentation Index
> Fetch the complete documentation index at: https://docs.powabase.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools

> Manage custom tools and view builtin tools available to agents.

Tools extend agent capabilities beyond conversation. The platform provides builtin tools (database\_query, database\_write, http\_request, code\_execute, storage\_read, storage\_write, web\_search, web\_scrape) and lets you create custom tools that call your own endpoints. A custom tool is defined with a name, description, JSON Schema for inputs, and an endpoint URL that the platform calls when the agent uses the tool.

## Common Patterns

List available tools with GET /api/tools to see both builtin and custom tools. Create custom tools with a clear description and input schema; agents use the description to decide when to call the tool. Assign tools to agents via the agent tools API (POST /api/agents/\{id}/tools).

### GET /api/tools

List all tools (builtin: database\_query, database\_write, http\_request, code\_execute, storage\_read, storage\_write, web\_search, web\_scrape + custom).

<CodeGroup>
  ```python Python theme={null}
  response = requests.get(f"{BASE_URL}/api/tools", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  const res = await fetch(`${BASE_URL}/api/tools`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/tools' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

### POST /api/tools

Create a custom tool. Required: `name`, `description`, `type`, `input_schema`. The route also accepts an optional `config` object. For HTTP-callable tools, the runtime reads `config.endpoint`, `config.method` (default `POST`), `config.headers`, and `config.timeout_seconds` when an agent invokes the tool.

<ParamField body="name" type="string" required>
  Display name; agents see this when deciding to call the tool.
</ParamField>

<ParamField body="description" type="string" required>
  Free-text description; the LLM uses it to decide when to call the tool.
</ParamField>

<ParamField body="type" type="string" required>
  Free-form tag (≤50 chars). Stored verbatim; not used by runtime dispatch. Pick something descriptive (e.g. `http`).
</ParamField>

<ParamField body="input_schema" type="object" required>
  JSON Schema for the tool's arguments. Not validated at create-time; passed straight through.
</ParamField>

<ParamField body="config" type="object">
  Tool-specific config. For custom HTTP tools, set `{ endpoint, method?, headers?, timeout_seconds? }` here; that's where the runtime reads them.
</ParamField>

<Note>
  Top-level `endpoint_url` / `method` / `headers` are silently dropped at create-time; only `name`, `description`, `type`, `input_schema`, and `config` are persisted. `type` is stored as a free-form `String(50)`; the runtime does NOT switch on it. Agent-tool dispatch uses the assignment's own `tool_type` (`builtin` vs `custom`), not the Tool's `type` field.
</Note>

<RequestExample>
  ```json Request theme={null}
  {
    "name": "weather_lookup",
    "description": "Get current weather for a city",
    "type": "http",
    "input_schema": {
      "type": "object",
      "properties": { "city": { "type": "string" } },
      "required": ["city"]
    },
    "config": {
      "endpoint": "https://api.weather.com/v1/current",
      "method": "GET"
    }
  }
  ```
</RequestExample>

<CodeGroup>
  ```python Python theme={null}
  response = requests.post(f"{BASE_URL}/api/tools", headers=headers, json={
      "name": "weather_lookup",
      "description": "Get current weather",
      "type": "http",
      "input_schema": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},
      "config": {"endpoint": "https://api.weather.com/v1/current", "method": "GET"},
  })
  ```

  ```typescript TypeScript theme={null}
  const res = await fetch(`${BASE_URL}/api/tools`, { method: "POST", headers, body: JSON.stringify({
    name: "weather_lookup",
    description: "Get current weather",
    type: "http",
    input_schema: { type: "object", properties: { city: { type: "string" } }, required: ["city"] },
    config: { endpoint: "https://api.weather.com/v1/current", method: "GET" },
  }) });
  ```

  ```bash cURL theme={null}
  curl -X POST '{BASE_URL}/api/tools' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"name": "weather_lookup", "description": "...", "type": "http", "input_schema": {"type": "object"}, "config": {"endpoint": "https://api.weather.com/v1/current"}}'
  ```
</CodeGroup>

### GET /api/tools/{id}

Get a tool definition by ID.

<ParamField path="id" type="string" required>
  Tool ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  response = requests.get(f"{BASE_URL}/api/tools/{tool_id}", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  const res = await fetch(`${BASE_URL}/api/tools/${toolId}`, { headers });
  ```

  ```bash cURL theme={null}
  curl '{BASE_URL}/api/tools/{id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

### PUT /api/tools/{id}

Update a custom tool.

<ParamField path="id" type="string" required>
  Tool ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  response = requests.put(f"{BASE_URL}/api/tools/{tool_id}", headers=headers, json={"description": "Updated"})
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/tools/${toolId}`, { method: "PUT", headers, body: JSON.stringify({ description: "Updated" }) });
  ```

  ```bash cURL theme={null}
  curl -X PUT '{BASE_URL}/api/tools/{id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}" -H "Content-Type: application/json" -d '{"description": "Updated"}'
  ```
</CodeGroup>

### DELETE /api/tools/{id}

Delete a custom tool.

<ParamField path="id" type="string" required>
  Tool ID
</ParamField>

<CodeGroup>
  ```python Python theme={null}
  response = requests.delete(f"{BASE_URL}/api/tools/{tool_id}", headers=headers)
  ```

  ```typescript TypeScript theme={null}
  await fetch(`${BASE_URL}/api/tools/${toolId}`, { method: "DELETE", headers });
  ```

  ```bash cURL theme={null}
  curl -X DELETE '{BASE_URL}/api/tools/{id}' -H "apikey: {API_KEY}" -H "Authorization: Bearer {API_KEY}"
  ```
</CodeGroup>

## Error Responses

Tool routes return `{"error": "<message>"}`.

| Status | Description                                                                       |
| ------ | --------------------------------------------------------------------------------- |
| 400    | Missing required field (`name`, `description`, `type`, or `input_schema`) on POST |
| 404    | No tool exists with the given ID                                                  |
