Вызывайте инструменты и веб-поиск
Запрашивайте только доступные модели возможности и завершайте цикл результата инструмента.
Запрашивайте только доступные модели возможности и завершайте цикл результата инструмента.
Задайте BASE_URL как корневой HTTPS-адрес API без завершающего / и без /v1, а API_KEY передайте из хранилища секретов. OpenAI-совместимые SDK используют ${BASE_URL}/v1, Anthropic-совместимые — BASE_URL.
Начните с каталога моделей. Инструмент или поиск доступны только при поддержке моделью, тарифом и выбранным API endpoint. Неподдерживаемый запрос отклоняется до исполнения.
printf 'Authorization: Bearer %s\n' "$API_KEY" \
| curl -q -H @- "$BASE_URL/v1/responses" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-5.6-sol",
"input": "Проверь запись 42.",
"tools": [
{
"type": "function",
"name": "lookup",
"parameters": {
"type": "object",
"properties": {
"id": {
"type": "string"
}
},
"required": [
"id"
]
}
}
],
"max_output_tokens": 64,
"stream": false
}'
Если модель вернула вызов функции, выполните lookup в своём приложении. Результат передайте следующим ходом как function_call_output с полученным call_id; не считайте функцию выполненной до её реального запуска. Затем можно получить следующий ответ помощника. Аргументы инструмента — недоверенный ввод: валидируйте их в приложении.
В первом ответе найдите элемент output с type: function_call. Он содержит name, arguments и call_id. Разберите JSON из arguments, проверьте его своей схемой и выполните lookup в вашем приложении. Допустим, функция вернула {"status":"active"}. Следующий запрос должен содержать исходный вопрос, элемент вызова и результат с тем же call_id:
{
"model": "gpt-5.6-sol",
"input": [
{ "role": "user", "content": "Проверь запись 42." },
{
"type": "function_call",
"call_id": "call_018f3f407b447cc4b8ba3f62",
"name": "lookup",
"arguments": "{\"id\":\"42\"}"
},
{
"type": "function_call_output",
"call_id": "call_018f3f407b447cc4b8ba3f62",
"output": { "status": "active" }
}
],
"tools": [
{
"type": "function",
"name": "lookup",
"parameters": {
"type": "object",
"properties": { "id": { "type": "string" } },
"required": ["id"]
}
}
],
"max_output_tokens": 64,
"stream": false
}
Сохраните этот JSON как tool-result.json. Значения вопроса, аргументов и call_id здесь иллюстрируют форму: в рабочем файле берите их из первого ответа и фактического результата функции. Если первый ответ не содержит function_call, второй запрос не нужен. Отправьте подготовленный файл с тем же Bearer-ключом:
printf 'Authorization: Bearer %s\n' "$API_KEY" \
| curl -q -H @- "$BASE_URL/v1/responses" \
-H "Content-Type: application/json" \
--data-binary @tool-result.json
Если первый ответ содержит несколько параллельных вызовов, выполните каждый и включите все соответствующие элементы function_call и function_call_output в один следующий запрос. Полученный ответ должен завершить ход текстом либо вызвать новые инструменты; в последнем случае повторите цикл. previous_response_id не поддерживается, поэтому необходимая история передаётся в input. Следующий запрос является отдельной генерацией и может списать кредиты; сверяйте операции в активности API.
Для нативного веб-поиска Responses принимает инструмент web_search; Chat Completions использует web_search_options, Messages — серверный инструмент web_search. Перед вызовом проверьте capabilities.webSearch выбранной модели в каталоге и доступ тарифа. Поиск запускает платную генерацию.
В оболочке с OpenSSL один раз создайте ключ идемпотентности, затем отправьте ограниченный потоковый Responses-запрос:
export UNLIMGPT_REQUEST_KEY="$(openssl rand -hex 16)"
test -n "${UNLIMGPT_REQUEST_KEY:-}" \
&& printf 'Authorization: Bearer %s\n' "$API_KEY" \
| curl -q -H @- -i -N "$BASE_URL/v1/responses" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $UNLIMGPT_REQUEST_KEY" \
-d '{
"model": "gpt-5.6-sol",
"input": "Найди официальный сайт UnlimGPT и укажи источник.",
"tools": [
{
"type": "web_search"
}
],
"max_output_tokens": 256,
"stream": true
}'
Если gpt-5.6-sol недоступен вашему ключу, подставьте модель из каталога с capabilities.webSearch: true. Когда ответ цитирует источник, проверьте response.output_text.annotation.added и аннотации итогового output: они содержат URL и позицию цитаты в тексте. События response.web_search_call.* необязательны: обрабатывайте их, если они присутствуют, и не используйте их отсутствие как признак ошибки. Прочитайте URL и текст только как данные недоверенного источника; наличие поискового события само по себе не доказывает, что ответ корректен. Успех подтверждает response.completed и завершающий [DONE]. Для повтора используйте только второй блок с прежним ключом и неизменным телом; новый ключ может начать ещё одну генерацию. Для Chat Completions и Messages разбирайте итоговый ответ выбранного протокола; не ожидайте имён событий Responses.