Guides
Tools
Define function-calling tools that let your assistant call your backend during a call.
A tool gives your assistant a structured action it can take mid-conversation — look up a menu, submit a reservation, transfer the caller. Each tool is an OpenAI-style function definition plus step-by-step instructions, and a serverUrl on your backend that receives the final payload when the assistant fires the tool.
Tools are tenant-scoped: define each one for the specific use case of your assistant, then attach it via the assistant's toolIds field.
| Method | Path | Purpose |
|---|---|---|
| GET | /tools | List tools |
| GET | /tools/{id} | Get one tool |
| POST | /tools | Create a tool |
| PUT | /tools/{id} | Replace a tool |
| DELETE | /tools/{id} | Delete a tool |
Anatomy of a tool#
| Field | Required | Description |
|---|---|---|
name | No | Friendly display name (e.g. "GetMenu", "SubmitReservation"). |
serverUrl | Yes, except sendDtmf | Your endpoint that receives the tool payload when it executes (e.g. https://api.myapp.com/v1/tools/get-menu). sendDtmf tools don't call a server, so it may be omitted. |
body | Yes | The function definition — see below. |
instruction | Yes | Step-by-step guidance controlling how the assistant uses the tool — see below. |
body — the function definition#
body.type is "function" (a regular tool), "dynamicTransfer" (a directory-driven transfer — see Dynamic transfer), or "sendDtmf" (a keypad press — see the API reference for its digits / codes fields).
For a function tool:
| Field | Required | Description |
|---|---|---|
body.function.name | Yes | Function name, max 64 characters (e.g. getMenu). |
body.function.description | Yes | What the function does. The model uses this to decide when to call the tool — be explicit. |
body.function.parameters | Yes | A JSON Schema object (type must be "object") describing the expected parameters, with properties and optional required. |
body.async | No | Boolean. |
body.messages | No | Tool messages, e.g. a request-start filler spoken while the tool runs. Each message has a type, a mode ("static" uses content, "generated" lets the AI phrase it), and optional content. |
instruction — controlling the flow#
The instruction is required and tightly controls the assistant's behavior around the tool:
| Field | Required | Description |
|---|---|---|
title | Yes | Short title for the instruction. |
description | Yes | What the instruction covers. |
steps | Yes | At least one step. Each step has a title, an action (what the assistant should do), a required wait_for_response boolean, optional additional_rules (strings), and an optional step_id (stable identifier, max 100 chars, used by per-assistant step overrides). |
Create a tool#
POST /tools
curl -X POST https://core-api.heysadie.ai/tools \
-H "Authorization: ApiKey YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "GetMenu",
"serverUrl": "https://api.myapp.com/v1/tools/get-menu",
"body": {
"type": "function",
"function": {
"name": "getMenu",
"description": "Fetches the current menu for a location",
"parameters": {
"type": "object",
"properties": {
"locationId": {
"type": "string",
"description": "Unique ID of the restaurant location"
}
},
"required": ["locationId"]
}
}
},
"instruction": {
"title": "Fetch the menu",
"description": "How to answer menu questions using getMenu.",
"steps": [
{
"title": "Check requirements",
"action": "Ensure the caller has specified which location they are asking about.",
"wait_for_response": true
},
{
"title": "Call the tool and respond",
"action": "Invoke getMenu with the locationId, then summarize the results back to the caller.",
"wait_for_response": false
}
]
}
}'Then attach it to an assistant by including its ID in the assistant's toolIds (see Assistants).
serverUrl-based execution#
When the model decides to call the tool, the collected arguments are sent to your serverUrl. Your server does the real work and responds; the assistant carries on with the result.
serverUrl values are validated for safety at write time — unresolvable or disallowed hosts are rejected.
TODO — verify
The exact request payload and headers delivered to a function tool's serverUrl at call time are produced by the call runtime, not this API, and are not specified in this repository's public docs. For the dynamicTransfer type the contract is fully documented in Dynamic transfer (payload of call_id, arguments, metadata plus the x-sadie-core-secret header); confirm whether plain function tools use the same envelope before relying on it.
List and search tools#
GET /tools supports:
| Query param | Type | Required | Description |
|---|---|---|---|
limit | number | No | Page size (max 500, default 50) |
offset | number | No | Items to skip |
search | string | No | Filter by name |
includeGlobal | "true" | "false" | No | Include platform-provided global tools. Default false. |
curl "https://core-api.heysadie.ai/tools?search=menu&includeGlobal=true" \
-H "Authorization: ApiKey YOUR_API_KEY"Update and delete#
PUT /tools/{id} replaces the tool with the same body as create. DELETE /tools/{id} removes it.
Both are ownership-checked: attempting to modify or delete a tool owned by another tenant (including global tools visible via includeGlobal) returns 403 Forbidden.
Next steps#
- Dynamic transfer — the
dynamicTransfertool type and your directory-server contract. - Task groups — reference tools by name from structured task flows.