Skip to content

ИИ-агенты ​

Эндпоинты агентов (/api/agents, /api/ai, /api/repo, /api/regression, /api/sources и связанные с ними) входят в модуль agents (тариф Pro и выше); отдельные части требуют модулей eval и healing (Enterprise) — см. Модули и тарифы. Запросы, кроме GET, под /api/agents подпадают под лимит ИИ-запросов — см. Ограничения частоты запросов.

Обзор ​

GET /api/agents/overview — статус агентов, метрики и матрица трассируемости, построенная движком покрытия.

Задачи агентов ​

POST /api/agents/jobs { type, params } — запустить задачу агента (agent0_coverage, agent1_generate, agent2_codegen, agent2_verify, agent3_triage, agent4_execute, custom_agent); ответ — 202 с jobId.

  • Тот же запрос, пока его задача ещё выполняется, отвечает 200 с этой задачей (reused: true).
  • В проекте одновременно может выполняться 3 задачи: четвёртая получает 429 с Retry-After.
  • Задача, которая всё ещё выполняется через 5 минут, завершается с ошибкой, а её вызовы модели отменяются; у agent2_verify есть 40 минут, у agent4_execute — час.

Остальные эндпоинты задач:

  • GET /api/agents/jobs — недавние задачи проекта.
  • GET /jobs/:jobId — одна задача.
  • GET /jobs/:jobId/stream — следить за задачей через SSE.
  • POST /api/agents/jobs/:jobId/cancel (agents:write) — остановить ещё выполняющуюся задачу: её вызовы модели прекращаются, задача завершается как отменённая, и освобождается одно из трёх мест проекта.
  • GET /api/agents/jobs/:jobId/llm-calls (agents:write) — ответ { calls, keptDays }: все вызовы модели в задаче по порядку, с системным промптом, промптом, ответом или ошибкой, токенами и длительностью (отправленные изображения учитываются, но не хранятся). Ход беседы с инструментами (обход стенда Агентом 2) хранится как то, что появилось с последней реплики модели — ответы инструментов, — плюс текст модели и вызовы инструментов. Вызовы хранятся KVALLI_LLM_CALL_LOG_DAYS дней (7; 0 — не хранить) в таблице llm_calls и только для вызовов, сделанных задачей.

Завершённая задача несёт usage — токены, потраченные её вызовами модели (они также учитываются по проекту в agent_usage; cacheReadTokens и cacheWriteTokens говорят, сколько токенов промпта обслужил кеш промптов провайдера или сколько в него записано). Ответ модели, обрезанный по лимиту токенов, помечается как обрезанный, а не используется. Промпт длиннее контекстного окна модели завершает задачу с 413 и тем, что сказал провайдер, — или, для Ollama, которая оставляет то, что помещается в окно, и молча отбрасывает остальное, — с указанием, сколько символов было прочитано как сколько токенов; шаблон вместо ответа не подставляется.

Все агенты запускаются этим способом: синхронные формы POST /api/agents/run-agent0-coverage, run-agent1-generate, run-agent2-codegen и run-agent3-triage удалены. Остался только POST /api/agents/run-custom (agents:write) { slug, runtimeInputs? } (или agent — определение агента прямо в запросе).

Агент 4: выполнение ручного прогона ​

agent4_execute { runId, itemIds?, only? } выполняет ручной прогон на тестовом стенде проекта вместо тестировщика (Pro, модуль browser и браузерный воркер). Нужно также право runs:write (403 без него).

  • Каждый результат, который ещё untested (only: "all" выполняет заново и результаты с вердиктом; itemIds называет конкретные результаты), проходится в отдельной браузерной сессии: модель выполняет шаги в том виде, в каком их скопировал прогон, с параметрами строки, а воркер проверяет каждый ожидаемый результат.
  • Файлы кейса (до 10 файлов, 10 МБ) передаются в браузер для шага, который загружает файл; модель может менять размер окна и спрашивать, как выглядит страница (ответ даётся словами по скриншоту).
  • Шаг, отмеченный как упавший, ещё раз сверяется со скриншотом, сделанным в момент отметки; падение, которое скриншот не подтверждает, проходится заново, а не записывается.
  • На стенде, настройки которого это разрешают (prepareData, по умолчанию выключено), предусловия кейса сначала выполняются через страницы самого стенда: по рецепту, сохранённому с прошлой подготовки и проигрываемому на стенде как код, или обходом, который может следовать кейсам проекта с теми же словами в предусловии. Всё созданное называется по прогону ([A4 RUN-12] …), а комментарий результата говорит, что было подготовлено; кейс, предусловия которого не удалось выполнить, получает blocked и не проходится.
  • Статус шага и, если отличалось, наблюдаемое записываются по мере отметки шагов. Скриншот упавшего шага (или последнего шага пройденного результата) сохраняется у результата как agent4-step-<n>[-failed].png. Вердикт (passed; failed, если шаг отличался; blocked, если шаг нельзя было выполнить здесь или у кейса нет шагов) записывается от имени Agent 4 с итогом обхода в комментарии.
  • Прогон не закрывается. Одна задача выполняет не больше 50 результатов; отмена или дедлайн срабатывают между результатами, и уже записанное остаётся.

Результат задачи: { runId, executed, passed, failed, blocked, left, items: [{ itemId, name, caseRef?, status, steps: [{ index, outcome, note? }], rounds?, reason? }], stopped? }. Закрытый прогон или прогон, импортированный из CI, отклоняется.

Агент 2: проверка в CI ​

agent2_verify { artifactId, sourceId?, workflowFile? } запускает автотест Агента 2 в собственном CI проекта, на ветке его открытого merge request. Нужно также право pipelines:trigger (403 без него).

  • Merge request должен быть в репозитории Агента 2; на GitHub воркфлоу (параметр или первый файл из ciWorkflowFiles источника) должен быть в этой ветке, иначе задача предложит влить в неё ветку по умолчанию.
  • Пайплайн записывается в GET /api/pipelines с trigger: "agent2_verify".
  • Падение читается из загруженного результата самого теста, если CI отправляет результаты в Kvalli, иначе — из конца логов упавших джобов (не больше трёх, джобы, которым разрешено падать, не учитываются).
  • Модель, читая это вместе с шагами и ожидаемым результатом тест-кейса, решает, что упало:
    • test_code — тест неверен или делает не то, что говорит кейс; он исправляется, коммитится в ту же ветку как test(codegen): fix <case> after CI run <PIP> [Kvalli Agent 2] после обычной проверки кода и запускается снова — не больше двух раз;
    • product — тест верен; он не меняется;
    • environment — пайплайн не дошёл до теста;
    • unrelated — упали другие тесты.

Артефакт сохраняет итог как ciVerification: { status: "running" | "passed" | "failed" | "inconclusive", verdict?, reason?, attempts: [{ pipelineId, url, status, failureSource?, verdict?, reason?, fixCommitted? }], checkedAt } и ciStatus. passed — только зелёный пайплайн или собственный пройденный результат теста; environment и unrelated дают inconclusive.

Агент 1: генерация кейсов ​

agent1_generate принимает sourceRef (jira:KVQA-2, youtrack:SHOP-12 или confluence:98307) и sourceVersion (когда задача последний раз менялась, номер версии страницы), если текст получен из этого источника. Каждый черновик кейса несёт их, и утверждённый кейс сохраняет их для отслеживания изменившихся требований. Каждый черновик также говорит, кто его написал, — draftOrigin: { provider, model } (provider: "parser" для кейса, выведенного парсером спецификаций), а кейс парсера, проверяющий то же, что уже проверяет один из кейсов модели, не включается.

Агент 3: разбор падений ​

agent3_triage с runId и itemId упавшего результата сообщает модели, как тот же тест проходил в пяти импортированных прогонах до этого на той же ветке («прошёл в 4 из последних 5») или что истории у него нет.

  • Он также читает, что оставило падение: страницу, которую Playwright сохранил в месте падения (самое новое вложение результата error-context.md, 8000 символов), вывод теста (output — конец stdout/stderr или system-out/system-err упавшего результата в том виде, в каком их нёс отчёт), и конец логов упавших джобов CI, если к прогону привязан пайплайн, известный Kvalli.
  • Для ручного результата падением считается его комментарий.
  • Скриншоты, видео и трассы не читаются: подключения к моделям передают только текст.
  • Модели также сообщается, где ещё встречается то же падение: другие упавшие результаты прогона, сообщение которых совпадает, если отбросить время, id, числа (HTTP-статусы сохраняются) и пути URL, а также импортированные прогоны проекта за предыдущие 14 дней. Тогда разбор несёт sharedFailure{ signature, inRun, earlierRuns, earlierTests }; если падение есть только у этого теста, поля нет. Экран прогона группирует упавшие результаты по той же сигнатуре.

Полезность агентов ​

GET /api/agents/usefulness?days=90 (1–365) — что стало с черновиками агентов: byModel (key: "provider / model") и bySkill, каждая строка с proposed, accepted, edited, discarded и процентами.

  • Агент 1: кейс утверждён в виде черновика, утверждён после правки на ревью или отброшен из очереди (acceptedPct, editedPct, discardedPct от решённых).
  • Агент 2: автотест, сгенерированный моделью, — proposed, и accepted, когда открыт его первый merge request (acceptedPct от предложенных).

Записывается по каждому черновику в agent_outcomes; кейсы парсера спецификаций считаются как parser / spec-parser. Строка bySkill несёт revisions (те же счётчики по каждой ревизии, v<version>-<hash> текста навыка, сначала старые), если черновики писались по двум или более ревизиям навыка, — так правку навыка можно оценить по тому, что она изменила. corrections (Агент 1) считает editedFields — поля, которые ревьюеры изменили перед принятием, по сравнению с кейсом в том виде, в каком его написал агент, — и discardReasons с discardedWithoutReason; каждое «до» и «после» правки и каждая причина хранятся в agent_outcomes.details.

Навыки ​

  • GET /api/agents/skills — встроенные навыки, поставляемые с Kvalli (только для чтения, isBuiltIn), и собственные навыки проекта, хранящиеся в базе данных. Навык проекта с id встроенного навыка заменяет его (overridesBuiltIn).
  • POST /api/agents/skills сохраняет навык проекта: с id правит этот навык, без id создаёт новый и отвечает 409, если ключ (filename или slug от name на любом алфавите) занят.
  • DELETE /api/agents/skills/:filename удаляет навык (409 для встроенного).
  • POST /api/agents/skills/bootstrap { appliesTo? } предлагает до трёх навыков на основе кейсов проекта и ничего не сохраняет: отвечает drafts, которые нужно просмотреть и сохранить; без модели — 502.
  • POST /api/agents/skills/eval-test, POST /api/agents/eval/run (agents:write), GET /api/agents/eval/report — оценка на заложенных дефектах; /api/agents/eval требует модуль eval (Enterprise).

Очередь ревью Агента 1 ​

  • GET /api/agents/agent1/drafts — очередь черновиков.
  • PUT /api/agents/agent1/drafts/:id — изменить черновик (с version).
  • POST /api/agents/agent1/drafts/approve и POST /api/agents/agent1/drafts/discard (cases:write) — решить по нескольким сразу: принимают id и отвечают, что принято и что отклонено. Отбрасывание может указать причину, reason: duplicate, not_in_requirement, wrong, too_vague или other (любое другое значение — 400).
  • DELETE /api/agents/agent1/drafts/:id — удалить черновик.
  • DELETE /api/agents/agent1/drafts — очистить очередь.

Первая правка черновика на ревью сохраняет кейс в том виде, в каком его написал агент, — с ним сравнивается утверждение. Каждое решение записывается к черновику в agent_outcomes, откуда берутся цифры полезности выше; очистка очереди выбрасывает это измерение, а не считает черновики отброшенными.

Свои агенты ​

Свои агенты хранятся в каждом проекте:

  • GET|POST /api/agents/custom, GET|DELETE /api/agents/custom/:slug;
  • POST /api/agents/custom/import (Markdown);
  • GET /api/agents/custom/:slug/export;
  • POST /api/agents/custom/:slug/verify — пробный запуск, который агент должен пройти.

Источники требований для Агента 1 ​

  • POST /api/sources/requirements-bundle{ openapi?, issues?, confluencePages? } (не больше 20 задач и 20 страниц).
  • POST /api/sources/swagger/fetch ({ url } требует cases:write; доверенные хосты применяются только к источнику, зарегистрированному в проекте).
  • POST /api/sources/confluence/fetch, POST /api/sources/task-manager/fetch.
  • POST /api/sources/task-manager/issues (cases:read) — задачи трекера, чтобы выбрать одну из списка, а не по ключу.
  • GET|POST /api/sources — реестр источников проекта (запись требует cases:write).
  • PUT /api/sources/:id — один источник, создаётся (201) или заменяется (200); название, которое уже есть у другого источника, — 409.
  • DELETE /api/sources/:id — удалить источник. Источники-репозитории по-прежнему добавляет, меняет и удаляет только администратор.
  • GET /api/contracts — спецификации из реестра.

Каждый маршрут этой группы доступен по двум путям. Маршруты получения и сборки работают и без префикса /sources (POST /api/swagger/fetch, /api/confluence/fetch, /api/task-manager/fetch, /api/task-manager/issues, /api/requirements-bundle), а реестр и контракты — наоборот: GET|POST /api/sources/list — тот же обработчик, что GET|POST /api/sources, а GET /api/sources/contracts — то же, что GET /api/contracts. Это псевдонимы, а не отдельные эндпоинты: используйте любой и ожидайте любой в старых клиентах.

Результаты агентов ​

  • GET /api/agents/requirements, GET /api/agents/traceability — граф требований и матрица, построенные последним прогоном покрытия.
  • GET /api/agents/last-result/:agent (cases:read) — последний результат названного агента в этом проекте в сохранённом виде, чтобы панель могла показать предыдущий ответ, не запуская задачу.

Код автотестов и репозиторий ​

Артефакты кода ​

GET /api/agents/code-artifacts — сгенерированные артефакты кода этого проекта. Агент 2 проверяет код, прежде чем сохранить его:

  • TypeScript и JavaScript — компилятором TypeScript по спеке и её page object вместе (синтаксис, неопределённые имена, собственные типы файлов; типы тестового фреймворка не установлены, поэтому его импорты считаются нетипизированными);
  • Python — парсером интерпретатора, если он установлен.

Код, который не компилируется, возвращается модели с сообщениями компилятора, не больше двух раз. Артефакт несёт результат как codeCheck: { status: "passed" | "failed" | "unchecked", checker, issues: [{ file, line, column, message }], note, fixAttempts }; Java и Go — unchecked, никогда не passed. Код, который всё равно не проходит проверку, сохраняется как артефакт, но не записывается в кейс.

Merge request ​

POST /api/repo/merge-request проверяет файлы, которые собирается отправить, включая правки, тем же способом: код, который не компилируется, получает 409 с codeCheck, если не передано force: true. Ответ в любом случае несёт codeCheck.

  • Отправка идёт только в ветку под autotest/, не больше 20 файлов по 512 КБ, и только тестовые файлы: пути под тестовыми globs репозитория или там, куда пишет Агент 2 (tests/**, e2e/**, **/*.spec.*, …).
  • Скрытые пути (.github/, .gitlab-ci.yml), конфигурация сборки и запуска (package.json, playwright.config.ts, conftest.py, Dockerfile, shell-скрипты …) и scripts/, ci/, bin/ верхнего уровня отклоняются с 400.

Вылеченный тест (purpose: "healing", один файл) получает один merge request на файл. Его ветка — autotest/heal-<file path as a slug>-<8 hex of the path's hash> (или переданный branchName, под autotest/). Пока в том же репозитории открыт запрос из этой ветки (или из неё с суффиксом, который получает занятое имя) в ту же целевую ветку, у провайдера запрашивается этот запрос, и вылеченные строки идут туда, а не в новый: они вносятся в копию файла в этой ветке, так что отправленное ранее исправление остаётся, а ответ содержит updated: true, и ещё unchanged: true, если в ветке они уже были (тогда ничего не коммитится). Иначе открывается новый запрос (updated: false). В запросы из форков ничего не пишется. Поиск одинаков для любого провайдера (merge requests GitLab, pull requests GitHub); без токена ничего не ищется, а запрос симулируется.

Репозиторий ​

Остальные эндпоинты /api/repo:

  • GET /api/repo/status (settings:read) — настроен ли репозиторий и какая его часть проиндексирована.
  • POST /api/repo/sync (agents:write) — см. ниже.
  • Три эндпоинта, которые читают или используют сохранённые учётные данные и поэтому требуют settings:write и администратора установки: POST /api/repo/test, GET /api/repo/projects (репозитории, которые видит токен, — для выбора в настройках) и GET /api/repo/branches (?project= — ветки одного из них).

Весь префикс ограничен 60 запросами в минуту и требует модуля agents.

POST /api/repo/sync { force? } индексирует головной коммит ветки: маршруты, которые объявляет каждый исходный файл, и тесты в каждом тестовом файле, — это то, что читают Агент 0 и свои агенты с входом repo. Коммит скачивается один раз как архив (по файлам через API, если провайдер не отдаёт архивы), а файл, git blob id которого не изменился с прошлой индексации, повторно не анализируется; коммит, уже проиндексированный с теми же globs, отвечает unchanged: true и ничего не скачивает. Статус говорит, сколько файлов, подходящих под globs, проиндексировано (filesScanned из filesMatched), с truncated и notes, если лимит (50 000 файлов, 1 МБ на файл) что-то отбросил. Агенты обновляют индекс до головы ветки, прежде чем его читать.

Подбор кейсов для регрессии ​

POST /api/regression/suggest{ planKey?, folder?, focus?, issueKey?, limit? (30), windowDays? (30) } — какие кейсы выполнить сейчас и почему каждый. Оценка строится по истории проекта в окне и никогда — моделью. Причины:

  • упал или заблокирован в последнем прогоне (и заведён дефект);
  • часто падает;
  • переключается между прохождением и падением на одном окружении;
  • нет вердикта в окне или нет его 14 дней;
  • изменён после последнего прогона;
  • покрывает требование, кейсы которого падают, или единственный покрывает требование;
  • слова изменения (focus или название и описание задачи трекера issueKey) найдены в его названии, папке, тегах, эндпоинте или шагах.

Критический и высокий приоритет добавляют очки, но сами по себе не причина; заглушённый кейс теряет очки; устаревшие кейсы не учитываются. Ответ: picks (сначала с наибольшей оценкой, каждый с reasons: [{ kind, points, text }]), nextBest ниже отсечки, leftOut, considered, quiet (нет причины запускать), счётчики byReason и basis — использованные результаты и прогоны. Одна и та же история всегда даёт один и тот же ответ.

Эндпоинты /api/ai ​

  • GET /api/ai/providers (cases:read) — провайдеры и модели, которые может использовать установка, для выбора в интерфейсе. Ключей в ответе нет.
  • POST /api/ai/smart-search (cases:read) — старый адрес POST /api/testcases/best-match, отвечает так же; модель не используется. Работает только там, где лицензирован модуль агентов: на Starter используйте новый адрес.
  • POST /api/ai/generate-cases (cases:write, models:use) — сгенерировать кейсы и вернуть их в том же запросе, а не запускать задачу. Для небольшой немедленной генерации; всё более долгое — через POST /api/agents/jobs, за которым можно следить и который можно отменить. POST /api/ai/generate-testcases — тот же маршрут под старым названием.
  • POST /api/ai/analyze-failure, POST /api/ai/generate-report (runs:read, models:use) — разбор падения и сводка по прогону. Отчёт принимает { runId } и сам читает прогон; модели передаются его счётчики и первые 50 падений с сообщениями, но не загруженный отчёт, стеки и пройденные тесты (целый { run } от старого клиента сводится так же). Текст падения обрезается до 20 000 символов — его начало и конец. Без настроенной модели падение читается по трассе, а отчёт — это собственные цифры прогона; ни то ни другое не выдумывает классификацию, уверенность или рекомендацию по релизу.

Эндпоинты /api/ai/test-llm и /api/ai/ollama-models описаны в разделе Конфигурация и система.

Починка локаторов ​

POST /api/healing/heal (healing:write; модуль healing, Enterprise) восстанавливает сломанный локатор по снимку DOM и возвращает исправленный код с оценёнными кандидатами. POST /api/healing/apply (те же требования) возвращает этот код: в репозиторий здесь ничего не пишется. Предложить его как merge request — POST /api/repo/merge-request с purpose: "healing" (один запрос на файл, переиспользуется, пока открыт; см. Merge request).

Документация описывает последний выпуск Kvalli.