SparkUAPIЭкспериментальноllms.txtEnglish

Разделы · 8/11

Вопросы человеку

POST …/dialogs и sparku ask — варианты, подтверждение, таймаут, вложение; как агент спрашивает разрешения.

Markdown ↗

Как это работает#

POST /v1/integrations/{slug}/dialogs показывает вопрос на островке и держит соединение открытым, пока человек не ответит (или вопрос не снят). Ответ приходит в теле того же HTTP-ответа — ждать нужно curl или HTTP-клиенту, который умеет не закрывать соединение по таймауту раньше срока timeout из тела запроса.

У интеграции — не больше одного вопроса без ответа одновременно: второй dialogs раньше ответа на первый получает 409 dialog_pending. Диалоги должны быть отдельно включены в настройках интеграции.

Тело запроса#

Вопрос с вариантами — есть options или custom:

{
  "message": "Выкатить в прод?",
  "title": "Деплой",
  "options": ["yes", {"id": "no", "label": "Отмена", "detail": "ничего не делать"}],
  "multiple": false,
  "custom": false,
  "timeout": "10m"
}

Подтверждение — без options и custom:

{"message": "Удалить ветку feature/x?", "accept": "Удалить", "decline": "Оставить", "comment": true}
Поле Тип По умолчанию Правило
message строка — обязательное, до 600 символов
title строка адрес интеграции до 60 символов
options массив строк или {id, label, detail?} — до 9 вариантов; строка — сама себе и id, и label
multiple bool false выбор нескольких — нужно ≥ 2 вариантов
custom bool false добавляет поле свободного ответа
accept / decline строка «Да» / «Нет» подписи кнопок подтверждения, до 30 символов
comment bool false у отказа можно оставить комментарий
timeout число секунд или "90s" / "10m" / "2h" 600 (10 мин) от 5 секунд до суток
attachment абсолютный путь — файл, который человек может открыть из вопроса; должен существовать

С options или custom — вопрос с вариантами; иначе — подтверждение двумя кнопками. Указать одновременно options/custom и accept/decline нельзя — accept/decline относятся только к подтверждению.

Ответ#

Всегда 200 OK, форма тела зависит от исхода:

Ситуация Тело
выбрал вариант(ы) {"answer": "chose", "options": ["yes"]}
свой ответ (custom) {"answer": "custom", "text": "…"}
подтвердил {"answer": "accepted"}
отказал {"answer": "declined"} или {"answer": "declined", "comment": "…"}
истёк timeout {"answer": "expired"}
вопрос снят {"answer": "withdrawn"}

withdrawn приходит, если: клиент отключился до ответа (тогда, впрочем, отвечать уже некому — вопрос просто снимается с островка), SparkU закрывается, API выключили или интеграцию выключили/удалили, пока вопрос ждал ответа.

Спрятать вопрос кнопкой «Скрыть» можно только у интеграции с карточкой — вернуть его на экран можно кнопкой «Ответить» в карточке; до этого он остаётся без ответа на сервере.

Пример: curl#

curl --unix-socket ~/.sparku/run/api.sock \
  -H "Authorization: Bearer $SPARKU_TOKEN_DEPLOY" \
  -d '{"message": "Выкатить в прод?", "accept": "Да", "decline": "Нет"}' \
  http://sparku/v1/integrations/deploy/dialogs
{"answer": "accepted"}

sparku ask#

sparku ask <slug> "вопрос" [-o id:подпись …] [--multi] [--custom]
           [--accept Да --decline Нет --comment] [--title …] [--timeout 10m] [--attach файл]
sparku ask deploy "Деплоить в прод?" -o yes:Да -o no:Нет
sparku ask deploy "Куда катить?" -o prod:Прод -o stage:Стейджинг --custom
sparku ask deploy "Удалить ветку?" --accept Удалить --decline Оставить --comment

Выбранные варианты печатаются в stdout по одному на строку (id, не подпись), свой ответ (custom) — текстом, комментарий отказа — тоже в stdout.

Коды выхода ask#

Отдельные от <sysexits.h>, которыми пользуются push/end/doctor — чтобы в shell работало if sparku ask deploy "Деплоить?"; then …:

Код Значение
0 ответ получен (выбор или свой текст — в stdout)
1 отказ (declined)
2 время вышло, вопрос снят или «Скрыть», SparkU закрылся

Ошибки транспорта (нет сокета, неверный токен, 409 dialog_pending) возвращают обычные коды sparku — 69, 77, 69 соответственно, см. CLI sparku.

if sparku ask deploy "Выкатить в прод?"; then
  ./deploy.sh
else
  echo "деплой отменён"
fi

Для ИИ-агентов#

Агент вроде Claude Code или Codex, который выполняет команды в shell, может спросить подтверждения у человека тем же путём, каким это делает CI-скрипт: через sparku ask в интеграцию, которую человек завёл заранее (например, «Агент» с адресом agent; если у неё есть карточка, вопрос можно спрятать и вернуться к нему). Это не отдельный протокол — агент такой же клиент API, как любой другой процесс.

if sparku ask agent "Удалить ветку feature/old и её PR на GitHub?" \
     --accept Удалить --decline "Не трогать" --timeout 90s; then
  git push origin --delete feature/old
  gh pr close 42
else
  echo "отменено человеком" >&2
  exit 1
fi

Пока вопрос висит на островке, агент блокируется на вызове sparku ask — это ожидаемо: решение принимает человек, и до его ответа выполнять опасный шаг нельзя. Если человек не отвечает --timeout, по умолчанию 10 минут, ask вернёт 2, и агент должен трактовать это как отказ, а не как разрешение продолжать.

TIP

У инструмента, которым агент запускает команды, обычно свой таймаут (у Claude Code — 2 минуты по умолчанию). Ставьте --timeout меньше него, иначе агент прервёт ожидание раньше, чем человек успеет ответить, а вопрос снимется с островка.

Строку-инструкцию для агента (в CLAUDE.md, AGENTS.md и т. п.) можно написать так:

Перед необратимыми действиями (удаление, force-push, деплой, миграции) спроси
человека: sparku ask agent "<что и зачем>" --accept Да --decline Нет --timeout 90s
Код 0 — можно, 1 — отказ, 2 — ответа нет: считай отказом.