hubris

1С:Предприятие

Подключение Hubris к 1С:Предприятие 8.3 — вызов моделей из встроенного языка через HTTPСоединение, ЗаписьJSON и ЧтениеJSON.

1С:Предприятие умеет обращаться к сторонним HTTP-сервисам прямо из встроенного языка — этого достаточно, чтобы конфигурация работала с моделями Hubris: разбирала письма клиентов, готовила описания номенклатуры, отвечала на вопросы по документам. Отдельной обработки не требуется, весь обмен — три объекта платформы: HTTPСоединение, ЗаписьJSON и ЧтениеJSON.

Требования

  • 1С:Предприятие 8.3
  • Аккаунт на hubris.pw и API-ключ
  • Исходящий доступ к api.hubris.pw по 443 порту с той машины, где выполняется код: при серверном вызове это сервер 1С, а не рабочее место пользователя

Подключение

Функцию удобно положить в общий модуль с признаком «Сервер». Ключ в коде не хранят: в типовых конфигурациях на БСП его кладут в безопасное хранилище данных (ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище и ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища), в простых — в отдельную константу с ограниченными правами. Переменных окружения платформа 1С:Предприятие читать не умеет, этот путь отпадает.

// Возвращает текст ответа модели.
Функция ОтветМодели(Ключ, ИдентификаторМодели, ТекстВопроса)

	// 1. Тело запроса
	Сообщение = Новый Структура("role, content", "user", ТекстВопроса);
	Сообщения = Новый Массив;
	Сообщения.Добавить(Сообщение);

	ПараметрыЗапроса = Новый Структура;
	ПараметрыЗапроса.Вставить("model", ИдентификаторМодели);
	ПараметрыЗапроса.Вставить("messages", Сообщения);
	ПараметрыЗапроса.Вставить("max_tokens", 500);

	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет));
	ЗаписатьJSON(ЗаписьJSON, ПараметрыЗапроса);
	ТелоЗапроса = ЗаписьJSON.Закрыть();

	// 2. Соединение: HTTPS, таймаут 120 секунд
	Соединение = Новый HTTPСоединение(
		"api.hubris.pw",
		443,
		,
		,
		,
		120,
		Новый ЗащищенноеСоединениеOpenSSL);

	Запрос = Новый HTTPЗапрос("/v1/chat/completions");
	Запрос.Заголовки.Вставить("Authorization", "Bearer " + Ключ);
	Запрос.Заголовки.Вставить("Content-Type", "application/json");
	Запрос.Заголовки.Вставить("X-Title", "1C");
	Запрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8);

	// 3. Отправка
	Попытка
		Ответ = Соединение.ОтправитьДляОбработки(Запрос);
	Исключение
		ВызватьИсключение "Не удалось обратиться к Hubris: " + ОписаниеОшибки();
	КонецПопытки;

	ТелоОтвета = Ответ.ПолучитьТелоКакСтроку("UTF-8");
	Если Ответ.КодСостояния <> 200 Тогда
		ВызватьИсключение "Hubris вернул код " + Ответ.КодСостояния + ": " + ТелоОтвета;
	КонецЕсли;

	// 4. Разбор ответа
	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(ТелоОтвета);
	Результат = ПрочитатьJSON(ЧтениеJSON);
	ЧтениеJSON.Закрыть();

	Возврат Результат["choices"][0]["message"]["content"];

КонецФункции

Вызов:

Сообщить(ОтветМодели(Ключ, "anthropic/claude-haiku-4.5", "Одним предложением: что такое счёт-фактура?"));

Адрес — именно api.hubris.pw, с api. в начале и /v1 в пути запроса. Домен hubris.pw — это сайт и личный кабинет: запросы к API он не обслуживает. Имя сервера в HTTPСоединение пишется без протокола, а https включается седьмым параметром — объектом ЗащищенноеСоединениеOpenSSL.

Сертификаты и HTTPS — первое, обо что спотыкаются

api.hubris.pw работает по обычному публичному сертификату. Российские корневые сертификаты — НУЦ Минцифры, «Russian Trusted Root CA» — для обращения к нам не нужны: они требуются другим сервисам, а не нашему API. Ставить что-либо в хранилище сертификатов не надо.

Что действительно нужно — не забыть сам объект защищённого соединения:

  • Без седьмого параметра Новый ЗащищенноеСоединениеOpenSSL платформа пойдёт на 443 порт открытым протоколом и вернёт ошибку соединения. Это и есть самая частая причина «не соединяется».
  • Конструктор без параметров даёт шифрование, но не проверяет сертификат сервера — источник корневых сертификатов не указан, проверять не с чем. Для большинства задач этого достаточно.
  • Нужна полноценная проверка — передайте источник корневых сертификатов вторым параметром: Новый ЗащищенноеСоединениеOpenSSL(, Новый СертификатыУдостоверяющихЦентровОС) (хранилище сертификатов операционной системы; на сервере доступно в сборках 8.3.8 и новее) либо Новый СертификатыУдостоверяющихЦентровФайл("cacert.pem") с явным файлом. Наш сертификат выпущен публичным удостоверяющим центром, поэтому обычное хранилище ОС его знает — доустанавливать корни не требуется.

Сигнатура объектов защищённого соединения и набор типов сертификатов различаются между сборками платформы. Если конфигуратор ругается на несоответствие типов, сверьтесь с синтакс-помощником (Shift+F1) своей версии.

Подводные камни

В заголовках — только латиница. Значение X-Title вида с русской «С» платформа не отправит: HTTP-заголовки принимают только ASCII, запрос падает с ошибкой «Request headers must contain only ASCII characters». Пишите 1C латиницей — этого достаточно, чтобы вызовы были подписаны в логах.

Кодировку указывайте явно с обеих сторон. В теле запроса — УстановитьТелоИзСтроки(Тело, КодировкаТекста.UTF8). При чтении ответа — ПолучитьТелоКакСтроку("UTF-8"): мы отдаём заголовок Content-Type: application/json без указания кодировки, и полагаться на угадывание не стоит. Само тело безопасно при любых настройках: ЗаписатьJSON по умолчанию экранирует символы вне ASCII, кириллица уходит служебными последовательностями и доезжает без искажений.

Таймаут ставьте большим. Шестой параметр HTTPСоединение — таймаут в секундах. С коротким таймаутом длинный ответ модели не дождётся: платформа выбросит исключение, а запрос на нашей стороне всё равно выполнится и будет оплачен. 120 секунд — разумный минимум, для длинных ответов ставьте больше.

Длинные вызовы — в фоновое задание. Ответ занимает секунды, иногда десятки секунд. Вызывать модель прямо в обработчике формы не стоит: интерфейс замирает, а серверный вызов может упереться в таймаут веб-сервера. Запускайте ФоновоеЗадание и забирайте результат по готовности.

У моделей с размышлением закладывайте запас токенов. При max_tokens: 32 весь бюджет уходит в размышление, и в content приходит пустая строка с finish_reason: length. Ставьте 300–500 и больше, а размышление, если оно не нужно, отключайте параметром "reasoning_effort": "none".

Прокси, если сервер 1С выходит в интернет через него. Пятый параметр HTTPСоединение — объект ИнтернетПрокси:

Прокси = Новый ИнтернетПрокси(Ложь);
Прокси.Установить("https", "proxy.local", 3128);

Выбор моделей

IDКогда подходит
anthropic/claude-haiku-4.5быстрые ответы, аккуратный русский в документах
google/gemini-3.7-flashдешёвые массовые операции по строкам справочников
deepseek/deepseek-v4-flashсамая низкая цена на простых задачах
anthropic/claude-sonnet-5разбор длинных договоров и сложные формулировки

ID берите из каталога целиком, вместе с вендором перед косой чертой. Каталог открыт без ключа — его читает тот же код, только методом Получить:

Запрос = Новый HTTPЗапрос("/v1/models");
Ответ = Соединение.Получить(Запрос);

Расходы

  • Заведите под конфигурацию отдельный ключ с дневным лимитом — ошибка в цикле обработки не съест весь баланс.
  • Заголовок X-Title подписывает вызовы в логах: расход по каждой конфигурации виден отдельно.
  • В ответе приходит блок usage с числом токенов — его удобно писать в регистр сведений рядом с документом, для которого делался запрос.

Решение проблем

Соединение не устанавливается

Забыт седьмой параметр Новый ЗащищенноеСоединениеOpenSSL либо сервер 1С не выпущен в интернет по 443 порту. Проверьте доступность api.hubris.pw именно с той машины, где выполняется код: при серверном вызове это сервер, а не рабочее место.

Ошибка «Request headers must contain only ASCII characters»

В значении заголовка кириллица. Чаще всего это X-Title с русской «С» — замените на латиницу.

Ответ приходит пустым

Модель потратила лимит на размышление. Поднимите max_tokens или добавьте "reasoning_effort": "none".

Вместо русского текста — нечитаемые символы

Не указана кодировка при чтении: нужно Ответ.ПолучитьТелоКакСтроку("UTF-8"). То же с телом запроса — УстановитьТелоИзСтроки(Тело, КодировкаТекста.UTF8).

Код 401, «Неверный API-ключ»

Ключ неверный или отозван. Он начинается на sk-gw-, без пробелов по краям; целиком виден только при создании. Новый — в разделе «Ключи».

Код 404, «Модель не найдена»

ID должен совпадать с каталожным символ в символ, вместе с вендором перед косой чертой. Короткие имена без вендора и имена с датой на конце мы не принимаем.

Код 402, недостаточно средств

Пополните баланс в кабинете — от 300 ₽, через СБП, банковской картой или по счёту для юридических лиц.

Проверено прогоном на OneScript 2.2.0 — свободной реализации языка 1С, 11 сентября 2026: запрос ушёл, ответ разобран, вызов виден в логах под именем 1C. Конструкции, которых в OneScript нет (ЗащищенноеСоединениеOpenSSL), выверены по документации платформы.

Что дальше

Обновлено: