Browse the docs

Build an agent

Tools

Tools let the agent act during the call: look an order up, check a slot, open a ticket, text a link. A tool belongs to the account and serves every agent that references it.

Four types

TypeWhat it doesKey settings
customPosts the arguments the agent collected to your HTTPS endpoint and reads the answer back.url, parameters (JSON Schema), apiTimeout
querySearches the content of one or more web pages to answer a question.urls
sendSmsSends an SMS during the call, to a fixed number or to the caller.body, to
sendEmailSends an email during the call, with the agent's notes.subject, body, to, notesInstructions

Create a custom tool

parameters follows the function-calling format: a JSON Schema object of the arguments the agent must collect before calling.

Terminal
curl -X POST "https://api.callshift.ai/v1/tools" \
  -H "Authorization: Bearer $CALLSHIFT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "custom",
    "name": "Check order",
    "description": "Looks up an order by its number and returns its status.",
    "config": {
      "url": "https://example.com/api/orders/lookup?token=YOUR_SECRET",
      "apiTimeout": 10,
      "parameters": {
        "type": "object",
        "properties": {
          "orderNumber": { "type": "string", "description": "The order number, e.g. ORD-1234" }
        },
        "required": ["orderNumber"]
      },
      "messages": { "requestStart": { "content": "Let me look that up." } }
    }
  }'

During the call, your endpoint receives a POST: the function name, the arguments the agent collected in args, the call so far in call and, when the caller is a known contact, the contact.

JSON
{
  "name": "checkOrder",
  "args": {
    "orderNumber": "ORD-1234"
  },
  "call": {
    "id": "8f14e45f-ceea-467a-9575-6d3c0a5f2b1e",
    "type": "inbound",
    "phoneNumber": "+33612345678",
    "startedAt": "2026-10-30T09:12:00.000Z",
    "createdAt": "2026-10-30T09:11:58.000Z",
    "agentId": "550e8400-e29b-41d4-a716-446655440000",
    "agentName": "Alice",
    "transcript": "Assistant: Hello, this is Alice...\nUser: Where is my order ORD-1234?"
  },
  "contact": {
    "id": "c56a4180-65aa-42ec-a945-5fd21dec0538",
    "firstName": "Ada",
    "lastName": "Lovelace",
    "email": "ada@example.com",
    "phoneNumber": "+33612345678",
    "metadata": {
      "plan": "pro"
    }
  }
}

Answer within a few seconds, with a short JSON the agent can read: the caller is waiting. The request carries no signature: put a secret token in the URL and check it.

Transferring to a number your system picks

Do not return the number from a custom tool: the agent would read it and could get a digit wrong. Use a forwardCall node whose number is looked up by your service, which receives the same request: see Call flow.

Attach a tool to an agent

A tool is attached by referencing it in the prompt of a knowHow node, with a <tool-node> element. Its text is the instruction the agent reads.

HTML
<tool-node functionname="checkOrder" category="custom" toolslug=""
  toolid="550e8400-e29b-41d4-a716-446655440000">Use checkOrder to look up the caller's order.</tool-node>
  • functionname is the camelCase form of the tool's name (Check order becomes checkOrder).
  • category is custom or query for those types, notifications for sendSms and sendEmail.
  • toolid is the tool's id. A diagram whose tool node matches no tool by both id and function name is refused with a 422.

GET/v1/agents/{agentId} lists the tools an agent references in its tools field, read-only.

Renaming a tool

Agents find a tool by its function name. Renaming a tool detaches it from the agents that use it until their <tool-node functionname> is updated.

What the agent says around a tool

MessageSaid when
requestStartThe call starts. blocking: true waits for the sentence to finish first.
requestCompleteThe tool answered
requestFailedThe tool failed
requestDelayedThe tool has not answered after timingMilliseconds (1000 to 30000)

An omitted requestStart or requestDelayed gets a default sentence; one sent without content is silent. With async: true the agent carries on talking without waiting for the result.

Update and delete

PATCH/v1/tools/{toolId} replaces each top-level config field you send (send all of messages or parameters to change one entry), and null clears an optional one. The type cannot change. DELETE/v1/tools/{toolId} is refused with a 409 listing the agents that still reference the tool, unless you add ?force=true.