ThunderPhone 2.0 вече е тук.Започнете самостоятелно — от 2 цента/мин.Прочетете съобщението

Function Tools

Инструменти за функции

Предоставете на своите AI агенти инструменти за функции, които извикват външни API по време на разговор — извличат данни за клиенти, записват часове, актуализират записи — с типизирани параметри.

Функционалните инструменти позволяват на вашите AI агенти да извикват външни API по време на телефонни разговори. Използвайте ги, за да търсите данни за клиенти, да проверявате наличност, да записвате часове или да извършвате всяко действие, което вашият бекенд поддържа.

Как работи

  1. Дефинирате инструменти със схема (какви аргументи приема инструментът)
  2. Предоставяте конфигурация за endpoint (къде ThunderPhone извиква вашето API) — или я пропускате, за да получавате извикванията на инструменти в уебхука на вашата организация
  3. По време на разговор AI решава кога да използва инструмент въз основа на разговора
  4. ThunderPhone извиква вашия endpoint с аргументите на инструмента
  5. Отговорът на вашето API се подава обратно към AI, за да продължи разговорът
ВъзможностКъде се изпълняваНастройка
Вградени инструментиThunderPhoneИнструкции в промпта; някои инструменти изискват и настройка на агент
Връзки с приложенияThunderPhone и свързаният доставчикСвържете акаунта и прикачете одобрените действия
API връзки и функционални инструментиВашето HTTP APIДефинирайте endpoint и схема или получавайте функционални извиквания чрез уебхук
MCP сървъриОтдалечен MCP сървърДобавете сървъра, открийте неговите инструменти и го прикачете към агента

Схема на инструмента

Всеки инструмент следва тази структура:

{
  "type": "function",
  "function": {
    "name": "search_appointments",
    "description": "Find available appointment slots for a given date",
    "parameters": {
      "type": "object",
      "properties": {
        "date": {
          "type": "string",
          "description": "Date in YYYY-MM-DD format"
        },
        "service": {
          "type": "string",
          "description": "Type of service (e.g., 'consultation', 'follow-up')"
        }
      },
      "required": ["date"]
    }
  },
  "endpoint": {
    "url": "https://api.example.com/appointments/search",
    "method": "POST",
    "headers": {
      "X-Api-Key": "your-api-key"
    }
  },
  "timeout": 120
}

Конфигурация на инструмента

ПолеТипЗадължителноОписание
timeoutчислоНеМаксимално време за изпълнение в секунди (по подразбиране: 20, максимум: 180)

Дефиниция на функцията

ПолеТипЗадължителноОписание
nameнизДаУникален идентификатор за инструмента
descriptionнизДаОбяснява на AI кога да използва този инструмент
parametersобектДаJSON Schema за аргументите на инструмента

Конфигурация на endpoint

ПолеТипЗадължителноОписание
urlнизДаURL адресът на endpoint на вашето API
methodнизНеHTTP метод (по подразбиране: POST)
headersобектНеПерсонализирани заглавки за включване

Два пътя за извикване

Заявката, която вашият сървър получава, зависи от това дали инструментът има endpoint:

Инструмент с endpointИнструмент без endpoint
Къде се изпраща заявкатаДиректно към endpoint.urlURL адресът на наследения уебхук на вашата организация
ТялоСамо аргументите на инструментаОбвивка telephony.tool / web.tool
ЗаглавкиВашите endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
Ключ за подписванеТайната на уебхука на организациятаТайната на уебхука на организацията

И двата пътя са блокиращи — AI изчаква резултата по средата на изречение. Времето за изчакване по подразбиране е 20 s; задайте timeout на най-горното ниво на инструмента, за да позволите по-дълго изпълнение, до максимума на платформата от 180 s. Поддържайте обработчиците бързи. Възможна е комбинация: при разговор, чиято организация има URL адрес на уебхук, инструментите с endpoint се извикват директно, а останалите използват уебхука.

Директни извиквания на крайни точки

Когато AI извика инструмент, който има endpoint, ThunderPhone изпраща заявка към вашия URL адрес:

Заглавки на заявката

POST /appointments/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-key

Персонализираните заглавки от вашите endpoint.headers винаги се включват дословно, плюс две заглавки в пространството от имена на ThunderPhone:

  • X-ThunderPhone-Signature — HMAC-SHA256 на точните байтове на тялото на заявката, с ключ вашата тайна за webhook на организацията
  • X-ThunderPhone-Call-ID — Идентификаторът на текущото обаждане

Content-Type: application/json се задава, освен ако вашите endpoint.headers не го заменят — персонализиран Content-Type има предимство.

Тяло на заявката

За POST / PUT / PATCH тялото съдържа само аргументите на инструмента (без обвивка), сериализирани канонично (сортирани ключове, компактни разделители):

{"date":"2025-01-02","service":"consultation"}

За GET / DELETE аргументите се изпращат като параметри на заявката и тялото е празно — тогава подписът се изчислява върху празния низ от байтове. Вижте Проверка на подписи за webhook.

Отговор

Върнете JSON отговор с резултата от инструмента:

{
  "available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
  "timezone": "America/Los_Angeles"
}

Отговорът се форматира и предоставя на AI, за да продължи разговора. Отговорите, които не са JSON, се обвиват като {"data": "<text>"}; изчакванията и неуспешните връзки се съобщават на AI като грешки, така че агентът да може да се извини и да продължи, вместо да блокира.

Диспечиране в режим webhook

Инструментите без endpoint се диспечират към наследения URL адрес за webhook на вашата организация като подписана заявка telephony.tool (телефонни обаждания) или web.tool (уеб обаждания). За разлика от известията за одит, доставяни до крайни точки за webhook след изпълнение, тази заявка е изпълнението — вашият HTTP отговор е резултатът от инструмента.

{
  "type": "telephony.tool",
  "data": {
    "call_id": 987654321,
    "tool_name": "search_appointments",
    "arguments": { "date": "2026-04-21" },
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  }
}

web.tool съдържа origin_domain вместо from_number / to_number. Отговорете с резултата от инструмента като JSON — същия договор за отговор като при директните извиквания на крайни точки. Заявката се подписва с тайната за webhook на организацията върху необработеното тяло, както всеки друг webhook.


Проверка на подписа

Директните извиквания на инструменти се подписват по същия начин като уебхуковете:

  • HMAC-SHA256 върху точните байтове на тялото на заявката (каноничният JSON — сортирани ключове, без допълнителни интервали)
  • С ключ, който е вашата тайна за уебхукове на организацията
  • Инструментите GET / DELETE подписват празния низ от байтове
Python
import hmac
import hashlib
 
def verify_tool_call(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
 
@app.post("/appointments/search")
async def search_appointments(request: Request):
    body = await request.body()
    signature = request.headers.get("X-ThunderPhone-Signature", "")
 
    if not verify_tool_call(body, signature, WEBHOOK_SECRET):
        raise HTTPException(status_code=401)
 
    data = json.loads(body)
    date = data["date"]
 
    # Look up availability
    slots = await get_available_slots(date)
 
    return {"available_slots": slots}
Node.js
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-thunderphone-signature'] || '';
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');
 
  if (!signature ||
      signature.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    return res.status(401).send('Invalid signature');
  }
 
  const { date, service } = JSON.parse(req.body);
 
  // Look up availability
  const slots = getAvailableSlots(date, service);
 
  res.json({ available_slots: slots });
});

Пълните примери — включително случая с празно тяло и уточнението при липса на тайна — са в Проверка на подписи на уебхукове.


Пример: Пълен процес за записване на час

Ето набор от инструменти за цялостна система за записване на часове:

{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_appointments",
        "description": "Find available appointment slots",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "service": { "type": "string" }
          },
          "required": ["date"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/search",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "book_appointment",
        "description": "Book an appointment at a specific time",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "time": { "type": "string", "description": "HH:MM format" },
            "customer_name": { "type": "string" },
            "customer_phone": { "type": "string" }
          },
          "required": ["date", "time", "customer_name"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/book",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "cancel_appointment",
        "description": "Cancel an existing appointment",
        "parameters": {
          "type": "object",
          "properties": {
            "confirmation_number": { "type": "string" }
          },
          "required": ["confirmation_number"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/cancel",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    }
  ]
}

Най-добри практики

Пишете ясни описания

Полето description помага на AI да разбере кога да използва инструмента. Посочете конкретно какво прави и кога е подходящо да се използва.

Обработвайте грешките коректно

Връщайте съобщения за грешка, които AI може да разбере: {"error": "No slots available for that date"}, вместо общи грешки 500.

Поддържайте отговорите кратки

Връщайте само това, от което AI се нуждае, за да продължи разговора. Големите полезни товари забавят времето за отговор.

Използвайте задължителните полета разумно

Маркирайте полетата като required само когато това е наистина необходимо. AI ще поиска от потребителя задължителната информация, преди да извика инструмента.


Свързани