Клиентские инструменты

Клиентские инструменты

Клиентские инструменты выполняются на вашей стороне. Когда модель вызывает такой инструмент, задача переходит в interrupted, а вы возвращаете результат и обработка продолжается.

В отличие от инструментов ассистента (которые вызывает сервер), клиентские инструменты задаёте вы прямо в запросе. Их удобно использовать, когда данные или действие доступны только на вашей стороне: геолокация пользователя, доступ к вашей БД, интерактивное подтверждение.

1. Объявить инструменты

Добавьте client_tools в тело POST /api/tasks:

{
  "assistant_id": 1,
  "input": [{ "type": "text", "text": "Что рядом со мной?" }],
  "client_tools": [
    {
      "name": "get_user_location",
      "description": "Возвращает город пользователя",
      "input_schema": {
        "type": "object",
        "properties": { "precision": { "type": "string" } }
      }
    }
  ]
}

Поля name и description обязательны, input_schema (JSON Schema) — опционально.

2. Дождаться прерывания

Если модель вызвала клиентский инструмент, опрос GET /api/tasks/{uuid} вернёт статус interrupted и список ожидающих вызовов в pending_tool_calls:

{
  "uuid": "550e8400-…",
  "status": "interrupted",
  "pending_tool_calls": [
    { "id": "call_abc", "name": "get_user_location", "arguments": { "precision": "city" } }
  ]
}

3. Вернуть результаты

POST /api/tasks/{uuid}/tool-results

Выполните инструменты у себя и отправьте результаты. Нужно покрыть все вызовы из pending_tool_calls.

{
  "tool_results": [
    { "id": "call_abc", "content": "Берлин" }
  ]
}

Ошибку инструмента верните так:

{ "id": "call_abc", "error": "Location unavailable", "reason": "permission_denied" }

Каждый элемент несёт id (из pending_tool_calls) и либо content, либо error (+опциональный reason).

4. Продолжение

После отправки результатов задача возвращается в processing. Продолжайте опрашивать: цикл interrupted → tool-results → processing может повториться несколько раз, пока задача не достигнет completed или failed.

POST /api/tasks         → pending
GET  /api/tasks/{uuid}  → interrupted   # модель вызвала client-инструмент
POST …/tool-results     → processing    # вернули результат
GET  /api/tasks/{uuid}  → completed      # готово (или снова interrupted)

Итоговый tool_call в output

После завершения вызов клиентского инструмента появляется в output как обычный tool_call (без префикса):

{
  "type": "tool_call",
  "tool_call": {
    "name": "get_user_location",
    "input": { "precision": "city" },
    "output": { "type": "content", "content": [{ "type": "text", "text": "Берлин" }] }
  }
}
Важно
  • tool_results должны покрывать все ожидающие вызовы, иначе 422.
  • POST /tool-results для задачи не в статусе interrupted вернёт 409.
  • Прерванная задача считается активной и учитывается в лимите одновременных задач.
SDK делает это автоматически
Метод runTask сам проходит весь interrupt-цикл: вызывает ваш обработчик, отправляет результат и продолжает — до завершения.