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

# Create native tool

> Add one of Verbeo's built-in tools to an assistant: end_call to hang up, transfer_call to hand the call to a person, send_sms to text the caller. It is switched on in the assistant's nativeTools in the same request.

Adds a native tool to an assistant, appends its id to the assistant's `config.toolIds` and switches it on in `config.nativeTools`, with the same settings. Verbeo runs a native tool itself, so its endpoint, method, headers and argument schema are set for you: you send only its own settings.

An assistant has at most one native tool of each name. A new assistant already has `end_call` unless it was [created](/api-reference/assistants/create) with `nativeTools.end_call.enabled: false`. To change a native tool that exists, find it with [List tools](/api-reference/tools/list) and `is_native: true`, then use [Update native tool](/api-reference/tools/update-native).

## Body

<ParamField body="agent_id" type="string" required>
  UUID of the assistant the tool belongs to.
</ParamField>

<ParamField body="tool_name" type="string" required>
  Which tool: `end_call`, `send_sms` or `transfer_call`. The rest of the body is that tool's settings, below; anything else is ignored.
</ParamField>

### Every native tool

<ParamField body="description" type="string | null">
  What the model is told about the tool: when to use it. Leave it out or blank and the default is written:

  * `end_call`: `End the call when user has to leave (like says bye) or you are instructed to do so.`
  * `transfer_call`: `Transfer the call to a human when the caller asks for one or the request cannot be handled.`
  * `send_sms`: empty.
</ParamField>

### `transfer_call`

<ParamField body="transfer_call_mode" type="string" default="static">
  `static` always dials `transfer_call_destination`. `dynamic` lets the assistant choose the number from the conversation: say in `description` how it should choose.
</ParamField>

<ParamField body="transfer_call_destination" type="string | null">
  The number a static transfer dials, in E.164 format: `+15551234567`. Required when the mode is `static`.
</ParamField>

<ParamField body="transfer_call_type" type="string" default="cold">
  `cold` or `warm`.
</ParamField>

<Note>
  The dashboard keeps a dynamic transfer's guidance in `description`, after a line that reads `[DYNAMIC PROMPT]`. The assistant's `nativeTools.transfer_call` shows what comes before that line as `description` and what follows as `dynamicPrompt`.
</Note>

### `send_sms`

<ParamField body="sms_content_type" type="string" default="prompt">
  `prompt`: the assistant writes the message. `static`: every SMS is `sms_static_message`.
</ParamField>

<ParamField body="sms_static_message" type="string | null">
  The text a static SMS sends. Required when `sms_content_type` is `static`.
</ParamField>

<ParamField body="twilio_account_sid" type="string | null">
  The Twilio account to send from: `AC` followed by 32 hexadecimal characters. Send it together with `twilio_auth_token`, or send neither, and Verbeo uses the Twilio account behind the call's number. Responses show it as `"********"`.
</ParamField>

<ParamField body="twilio_auth_token" type="string | null">
  That account's auth token. Write-only: no response includes it.
</ParamField>

<ParamField body="twilio_from_number" type="string | null">
  The sender: a number in E.164 format (`+14155550123`), or an alphanumeric sender ID of up to 11 letters, digits and spaces with at least one letter (`Acme`). Leave it out and Verbeo picks the sender, normally the number the call is on. It must be able to send SMS from the Twilio account that sends the message.
</ParamField>

<ParamField body="timeout_seconds" type="number" default="30">
  The tool's timeout: a whole number of seconds, from `5` to `300`.
</ParamField>

### What Verbeo sets

| Field | Value |
| - | - |
| `endpoint_url` | `native://` and the tool's name |
| `http_method` | `POST` |
| `headers` | `{}` |
| `timeout_seconds` | `30` for `end_call` and `transfer_call` |
| `parameters` | From the settings: `send_sms` with `prompt` takes a `message`, and with `static` nothing; a static `transfer_call` takes a `reason`, a dynamic one a `phone_number` and a `reason`; `end_call` takes nothing |

## Request

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.verbeo.ai/v1/tool/native" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "agent_id": "550e8400-e29b-41d4-a716-446655440000",
      "tool_name": "transfer_call",
      "description": "Transfer to the billing team when the caller asks about an invoice.",
      "transfer_call_mode": "static",
      "transfer_call_destination": "+15551234567"
    }'
  ```

  ```javascript Node.js theme={null}
  const res = await fetch("https://api.verbeo.ai/v1/tool/native", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.VERBEO_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      agent_id: "550e8400-e29b-41d4-a716-446655440000",
      tool_name: "send_sms",
      description: "Text the caller our address when they ask for it.",
      sms_content_type: "prompt",
      twilio_account_sid: process.env.TWILIO_ACCOUNT_SID,
      twilio_auth_token: process.env.TWILIO_AUTH_TOKEN,
      twilio_from_number: "+14155550123",
    }),
  });
  const { data: tool } = await res.json();
  ```

  ```python Python theme={null}
  import os, requests

  tool = requests.post(
      "https://api.verbeo.ai/v1/tool/native",
      headers={"Authorization": f"Bearer {os.environ['VERBEO_API_KEY']}"},
      json={
          "agent_id": "550e8400-e29b-41d4-a716-446655440000",
          "tool_name": "transfer_call",
          "description": "Transfer to the billing team when the caller asks about an invoice.",
          "transfer_call_mode": "static",
          "transfer_call_destination": "+15551234567",
      },
  ).json()["data"]
  ```
</CodeGroup>

## Response

`201 Created` with the new [tool object](/api-reference/tools/overview#the-tool-object).

```json theme={null}
{
  "success": true,
  "data": {
    "id": "5a7d1c3e-2b4f-4e6a-8c9d-0e1f2a3b4c5d",
    "agent_id": "550e8400-e29b-41d4-a716-446655440000",
    "tool_name": "transfer_call",
    "description": "Transfer to the billing team when the caller asks about an invoice.",
    "endpoint_url": "native://transfer_call",
    "http_method": "POST",
    "headers": {},
    "parameters": {
      "properties": {
        "reason": { "type": "string", "description": "Brief reason why the user wants to be transferred" }
      },
      "required": ["reason"]
    },
    "timeout_seconds": 30,
    "is_native": true,
    "transfer_call_mode": "static",
    "transfer_call_destination": "+15551234567",
    "transfer_call_type": "cold",
    "twilio_account_sid": null,
    "created_at": "2026-01-15T10:30:00.123456+00:00",
    "updated_at": "2026-01-15T10:30:00.123456+00:00",
    "…": "the rest of the tool object"
  }
}
```

## Errors

| Code | Status | When |
| - | - | - |
| `VALIDATION_FAILED` | 422 | A `tool_name` that is not a native tool's (`tool_name: must be end_call, send_sms or transfer_call`); a static transfer with no destination (`transfer_call_destination: required for a static transfer`); a static SMS with no message (`sms_static_message: required when sms_content_type is static`); half a Twilio credential (`twilio_auth_token: required when twilio_account_sid is set`, or the reverse); a malformed `twilio_account_sid` or `twilio_from_number`; or `"********"` for a credential, since a new tool has no saved value for it to stand for. |
| `CONFLICT` | 409 | The assistant already has this native tool: `This agent already has a tool named "end_call"`. |
| `NOT_FOUND` | 404 | No such assistant, or it belongs to another workspace: `Agent not found`. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.