Skip to content

AI Router ​

Агент — отдельная версионируемая AgentDefinition, исполняемая через runner-agent или внешний A2A endpoint. Ассистент — карточка Assistant (ai_chat_agents) для персонализации чата. Это разные каталоги и API.

Назначение ​

Центральный сервис работы с LLM в платформе Unishift. Маршрутизирует запросы к нескольким провайдерам (OpenAI, Anthropic, Google, Ollama и OpenAI-compatible эндпоинты вроде Yandex AI Studio), управляет чатами и knowledge base (RAG) на основе hybrid-поиска: PostgreSQL FTS + pgvector, слияние через Reciprocal Rank Fusion (RRF), опциональный LLM-rerank и переформулировка запросов.

Порты ​

  • HTTP: 8101
  • БД: ai_router_db

Ключевые возможности ​

  • Мультипровайдерность: OpenAI, Anthropic, Google, Ollama за единым API (Yandex AI Studio / Alice AI — через vendor openai + custom base_url)
  • Capabilities провайдера: chat, embed, planner, diagram, fill, decision
  • Sidecar-провайдеры planner / diagram / fill / embed — upsert при старте, только если задан URL (LLAMA_PLANNER_URL, LLAMA_DIAGRAM_URL, LLAMA_FILL_URL, LLAMA_EMBED_URL). В devops/prod эти URL пустые: стартовый стек без моделей и без провайдеров. Как поставить модели и Bosun: Локальные модели.
  • Decision-gate (опционально): decision-модель Bosun v3.1 0.6B на отдельном llama.cpp-сайдкаре (DECISION_URL, compose-профиль decision, см. devops/prod/llama-decision/README.md). Перед planner отвечает на два noul-вопроса по семействам с побочным эффектом, которые есть в каталоге. Уверенное «да» (conf ≥ 0.85) командует одиночный tool (create_drawio, create_pptx, create_file, run_command, run_flow). Для заметки, задачи и таблицы то же «да» только открывает глаголы (создать или изменить), а конкретный tool выбирает planner. Иначе семейство убирается из каталога. Если команды нет, один choice-вопрос (tool_pick) выбирает инструмент из оставшегося короткого списка, включая MCP и ask_user. Уверенный ответ (conf ≥ 0.70) оставляет в каталоге только его. Слабый ответ список не режет. Любая ошибка или отсутствие провайдера — planner работает как раньше. Клиент: pkg/decision (масочный softmax по top-k логитам с консервативным хвостом); GGUF требует патча decision-токенов (patch_gguf.py). Тот же sidecar доступен снаружи как POST /api/v1/decide (узел Flow Manager Классификатор / aiClassifyNode, модель Bosun).
  • Local planner — вход по умолчанию, если есть tools (mode=chat и mode=sub-agent): sidecar в цикле PlanTraced → exec → PlanTraced (до 4 раундов) выбирает tools, в том числе MCP (retrieve_tools → call_tool_read). Chat-LLM только синтезирует ответ, без MCP-схем. Таймаут sidecar LLAMA_PLANNER_TIMEOUT (по умолчанию 45s). Skip только: plan/obs, draft-редакторы, clarify-first, capability diagram. Fallback в chat-loop — без MCP tools. Forced tool — pin в loop при fallback.
  • Режимы чата: chat, multi-agent (оркестрация субагентов), plan (планирование задач, сценариев и презентаций в markdown), obs (observability/анализ логов и метрик через MCP), spec (постановка ТЗ и спецификаций с фиксацией в заметки/файлы). Кастомизируются карточкой режима в Настройки → AI Router → Процесс. Как менять промпты, скиллы и шаблон spec/plan: Управление ответами.
  • Multi-agent: оркестратор делегирует через spawn_agent. Несколько вызовов в одном шаге модели идут параллельно (лимит AI_SUB_AGENT_MAX_PARALLEL, по умолчанию 3). На ход не больше AI_SUB_AGENT_MAX_SPAWNS (6) и AI_SUB_AGENT_TOKEN_BUDGET токенов детей (120000). Повтор того же slug и задачи пропускается. Таймаут ребёнка AI_SUB_AGENT_TIMEOUT (3m) наследуется от контекста родительского хода. Обычный пользователь запускает только ассистентов из shared_user_ids; админ — любой активный.
  • Результат spawn_agent — JSON: status = success | failed | needs_clarification | skipped, child_chat_id, output/summary, artifacts, questions, error, error_code. needs_clarification продолжает тот же дочерний чат: ask_user, затем снова spawn_agent с child_chat_id и clarification. Длинный ответ сохраняется файлом через storage, оркестратор получает сводку и ссылку.
  • Маршрутизация модели суб-агента: provider_id+model на карточке, иначе sidecar по provider_capability (diagram, planner, fill), иначе провайдер родительского чата. Каталог для оркестратора кэшируется по пользователю и сбрасывается при изменении карточки (ai.assistant.catalog.invalidate).
  • События NATS: ai.chat.agent.started, ai.chat.agent.progress, ai.chat.agent.completed. chat_id — дочерний чат, parent_chat_id — оркестратор. В ai_audit_events у ребёнка parent_chat_id и spawn_id; у родителя child_tokens_total и child_duration_ms не складываются в его tokens_total.
  • Чаты с историей сообщений, стримингом ответа и reasoning (thinking). Продуктовое описание поверхностей: AI-чат
  • Function calling — вызов инструментов из чата (tool calls)
  • Diagram-агент: инструменты draw.io / BPMN (create_drawio, update_drawio, …)
  • RAG / Knowledge base:
    • ingest с очисткой текста, чанкованием и эмбеддингами
    • hybrid retrieval (FTS + vector) + RRF
    • score threshold, LLM-rerank, query rewriting, multi-hop
    • цитирование источников и anti-hallucination system prompt
    • space-scoped ACL: scope space-{uuid} привязан к workspace; поиск фильтруется по spaces, доступным текущему пользователю
    • автосинхронизация заметок (documents → RAG) через NATS
  • CRUD провайдеров для администраторов (модели, API-ключи, base URL, egress через proxy-manager)
  • Учёт вызовов: сохранение истории, токенов, длительности и статистики по пользователю
  • Двойная аутентификация: JWT (пользователи) и Service Token (сервисы)
  • Ролевая модель: управление провайдерами требует роль admin
  • Публикация NATS-событий: стриминг чанков, статусы обработки, tool-call'ы
  • Swagger UI, health checks

Платформа агентов ​

AI Router хранит определения, неизменяемые версии и durable runs. Сам agent loop выполняется DB-free бинарником runner-agent; AI Router выдаёт короткоживущий job token и остаётся policy proxy для LLM, tools, scopes и финализации артефактов. Inline fallback отсутствует: без подключённого runner с требуемыми capabilities агент помечается недоступным.

APIНазначение
GET/POST /api/v1/agentsкаталог и создание определения
POST /api/v1/agents/:slug/versionsпубликация immutable version
POST /api/v1/agents/:slug/runsdurable запуск
GET /api/v1/agents/runs/:runIdстатус и progress
POST /api/v1/agents/runs/:runId/cancelотмена
POST /api/v1/agents/importимпорт .usagent; неизвестная подпись → quarantine
POST /api/v1/agents/import/cursorбезопасный импорт Cursor ZIP как inert draft
POST /api/v1/agents/admin/endpointsрегистрация и pin A2A Agent Card

Встроенные версии artifact-pptx, artifact-drawio и artifact-bpmn возвращают typed IR. После проверки схемы AI Router вызывает детерминированный finalizer (create_pptx, create_drawio, create_bpmn). Legacy chat modes chat, multi-agent, plan, obs, spec продолжают работать независимо.

Формат пакета и trust model: Агенты платформы. Публичный каталог пакетов: unishift.ru/agents. Установка раннера: Agent Runner.

Провайдеры ​

Админский CRUD — /api/v1/providers (роль admin). Полный список методов — в Swagger.

Запросы провайдера с use_proxy: true уходят через proxy-manager: клиент вызывает GET /api/v1/proxies/next по каждому тегу из proxy_tags и берёт первый здоровый адрес. SOCKS4 для этих вызовов не используется. Пустой proxy_tags при включённом прокси — ошибка валидации.

ПолеОписание
use_proxyВключить egress через пул. По умолчанию false
proxy_tagsТеги пула. Обязателен, если use_proxy
proxy_on_unavailabledirect (по умолчанию) — запрос напрямую, если прокси нет; fail — ошибка

Адрес сервиса: PROXY_MANAGER_SERVICE_URL (по умолчанию http://localhost:8114).

Проверка соединения до сохранения: POST /api/v1/providers/connection/test (admin). Тело то же, что у POST /providers/models/preview: vendor, api_key, base_url; если ключ и URL пустые, а задан provider_id — берётся сохранённый провайдер. Таймаут 30 с. HTTP 200 и при неудаче: { "ok": false, "models": [], "message": "…" }. message: models_endpoint_missing — у вендора нет /models, соединение при этом не считается успешным.

RAG / Knowledge base ​

Пайплайн ​

Ingest                         Retrieval                         Generation
───────                        ─────────                         ──────────
clean text ──► chunk ──►       rewrite query ──►                 system prompt
embed ──► store                FTS + vector ──► RRF ──►          (anti-hallucination
(pgvector + tsvector)          [rerank] ──► [multi-hop]          + cite sources)
  1. Ingest — документ чистится (HTML/шум), режется на чанки с overlap, для каждого чанка считаются эмбеддинги и заполняется content_tsv (FTS).
  2. Retrieval — сырой вопрос опционально переписывается LLM; параллельно ищутся кандидаты по FTS и по cosine similarity; списки сливаются RRF; при включённом rerank LLM оставляет top-N; при слабом recall — второй hop.
  3. Generation — в чат с привязанными scopes подмешивается жёсткий system prompt («отвечай только по документам», «цитируй Source»), tool search_knowledge_base возвращает чанки в формате с заголовком источника.

Ingest ​

POST /api/v1/rag/documents

ПолеТипОбязательноеОписание
scopestringдаОбласть знаний (space-{uuid} или legacy id)
titlestringдаЗаголовок документа (попадает в метаданные чанков)
contentstringдаТекст / markdown / HTML
content_typestringнетtext (default), markdown, html, json, yaml, config, code
source_idstringнетВнешний id (UUID заметки) — upsert по (scope, source_id)
space_iduuidнетWorkspace id (должен совпадать с space-* scope)
metadataobjectнетДоп. поля чанков: category, author, date, …

При ingest:

  • upsert: если задан source_id — по (scope, source_id); иначе по (scope, title) (legacy). В ответе updated: true при обновлении. document_count увеличивается только при создании.
  • для space-* scopes требуется доступ пользователя к соответствующему space (через spaces API + SERVICE_TOKEN)
  • для text / markdown HTML и script/style вырезаются, пробелы нормализуются
  • json, yaml, config, code сохраняют отступы и переносы как в исходнике
  • markdown режется по заголовкам #; html парсится в markdown-ish (заголовки/списки) и тоже режется по заголовкам; text — по абзацам; json / yaml / config / code идут одним куском. Крупные секции дополнительно режутся по RAG_CHUNK_MAX_SIZE с overlap.
  • в metadata чанка всегда пишутся title, content_type, scope, ingested_at
  • FTS-индекс (content_tsv) обновляется триггером БД
  • векторы пишутся в document_chunk_embeddings_{dim} (не в колонку чанка), dim берётся из embed-провайдера, привязанного к scope

Embeddings (multi-dim + per-scope) ​

Разные модели эмбеддингов несовместимы. Поддерживаемые размерности: 256 / 768 / 1536 — отдельные таблицы document_chunk_embeddings_{256|768|1536} + HNSW.

СущностьПоля
Embed-провайдер (type=embed)embedding_dim, default_model (doc), query_model (search), is_default (пресет для новых scopes)
Scopeembedding_provider_id, embedding_dim (immutable после create)

Правила:

  • при создании scope выбирается embed (или берётся is_default);
  • embedding_dim копируется с провайдера и не меняется;
  • сменить провайдера на scope можно только с той же dim → авто-reindex;
  • ingest использует default_model; search — query_model || default_model;
  • поиск по нескольким scopes группирует их по провайдеру и сливает через RRF с FTS.

POST /rag/scopes/:scope/reindex — пересчитать векторы текущим провайдером scope.

Yandex embeddings ​

Отдельного vendor нет: vendor=openai. base_url можно оставить OpenAI-совместимым (https://ai.api.cloud.yandex.net/v1) — для эмбеддингов ai-router всё равно ходит в нативный https://llm.api.cloud.yandex.net/foundationModels/v1/textEmbedding (modelUri + text, заголовок Api-Key для ключей AQVN…).

ПолеЗначение
embedding_dim256
default_modelemb://<folder_id>/text-search-doc/latest
query_modelemb://<folder_id>/text-search-query/latest

Preview /models у Yandex часто отдаёт 404 — UI позволяет ввести URI вручную. Без query_model поиск деградирует (query и documents в разных пространствах Yandex).

Проверьте, что скоуп (например tt) привязан именно к этому embed-провайдеру, а не к чатовому. Ingest берёт провайдера из настроек скоупа.

Space scopes и ACL ​

Конвенция имени: space-{spaceUUID}.

  • GET /rag/scopes возвращает:
    • все space-* для spaces, доступных пользователю (owner или shared);
    • админам — все существующие scopes (общие и space);
    • общие (не space-*) scopes, пошаренные пользователю (shared_user_ids);
    • legacy scopes, в которых у пользователя есть собственные документы.
  • Space scopes auto-provision при list (alias = имя space).
  • Общую базу можно открыть выбранным пользователям через shared_user_ids на PUT /rag/scopes/:scope. Доступ к space-базам по-прежнему через ACL пространства.
  • SearchKnowledgeBase / tool search_knowledge_base принимают user_id на бэкенде и отбрасывают недоступные space scopes. Пошаренные общие scopes ищутся целиком (без фильтра owner_id). Legacy scopes без шаринга — только среди документов с owner_id = user.
  • AI-чат в Notes подставляет defaultScopes = ["space-{currentSpaceId}"].

Синхронизация заметок ​

Сервис documents публикует NATS-события:

SubjectКогда
documents.createdсоздание / duplicate
documents.updatedpatch
documents.deletedsoft/hard delete

ai-router подписан и делает trusted ingest / delete по (scope=space-{spaceID}, source_id=documentID).

Retrieval ​

Поиск вызывается tool'ом search_knowledge_base (чат с scopes) или через usecase SearchKnowledgeBase(userID, …).

ШагОписаниеКонфиг
ACL filterпересечение запрошенных scopes с доступными spaces / шарингом / admin—
Query rewriteLLM исправляет опечатки / раскрывает аббревиатурыRAG_QUERY_REWRITE_ENABLED
FTSwebsearch_to_tsquery('simple') + ts_rank_cd—
Vectorcosine distance (<=>), отсев по similarityRAG_VECTOR_MIN_SCORE
RRFscore = Σ 1/(k + rank)RAG_RRF_CONSTANT, RAG_CANDIDATE_LIMIT
RerankLLM listwise ranking top-кандидатов → top-NRAG_RERANK_ENABLED
Multi-hopповторный поиск с другим rewrite при слабом recallRAG_MULTI_HOP_ENABLED

Формат результата для LLM:

Source: «FAQ» [category=support, author=team]
текст чанка…

Scopes ​

МетодПутьОписание
GET/rag/scopesСписок scopes, доступных текущему пользователю (админ — все)
GET/rag/scopes/:scopeНастройки одного scope (403 без доступа)
PUT/rag/scopes/:scopeUpsert alias / description / system_prompt / default_origin / embedding_provider_id / shared_user_ids
POST/rag/scopes/:scope/reindexПересчитать embeddings scope
DELETE/rag/scopes/:scopeУдалить документы и чанки scope
DELETE/rag/scopes/:scope/settingsУдалить только настройки scope

system_prompt scope дополняет дефолтный anti-hallucination prompt, а не заменяет его.

Конфигурация ​

ПеременнаяПо умолчаниюОписание
PORT8101Порт HTTP-сервера
DB_*—PostgreSQL (DB_NAME=ai_router_db)
JWT_SECRET—Валидация JWT
SERVICE_TOKEN—Межсервисный токен (ACL через spaces, sync)
AGENT_PACKS_DIRpacks/usagent вверх по дереву от cwdКаталог исходников .usagent. ai-router загружает их при старте
AI_DEFAULT_PROVIDERopenaiПровайдер по умолчанию
AI_REQUEST_TIMEOUT120sTimeout запросов к LLM
AI_MAX_RETRIES3Число повторов при ошибке
RAG_CANDIDATE_LIMIT20Сколько кандидатов брать из FTS и из vector до RRF
RAG_DEFAULT_LIMIT5Лимит результатов по умолчанию
RAG_VECTOR_MIN_SCORE0.2Мин. cosine similarity (0 = без порога)
RAG_RRF_CONSTANT60Константа k в формуле RRF
RAG_RERANK_ENABLEDtrueLLM-rerank кандидатов после RRF
RAG_QUERY_REWRITE_ENABLEDtrueПереформулировка запроса перед поиском
RAG_MULTI_HOP_ENABLEDtrueПовторный поиск при слабом recall
RAG_CHUNK_MAX_SIZE2000Размер чанка при ingest (символы)
RAG_CHUNK_OVERLAP200Overlap чанков (символы)
MESSAGING_URLnats://localhost:4222NATS URL
PROXY_MANAGER_SERVICE_URLhttp://localhost:8114Базовый URL proxy-manager для egress провайдеров
SERVER_WRITE_TIMEOUT300sWrite timeout (длинный под стриминг)

Для снижения latency на retrieval можно отключить тяжёлые шаги:

bash
RAG_RERANK_ENABLED=false
RAG_QUERY_REWRITE_ENABLED=false
RAG_MULTI_HOP_ENABLED=false

Квоты и маршрутизация моделей ​

  • Лимиты: месячные потолки токенов на пользователя (quota_user_monthly_tokens) и на пространство (quota_space_monthly_tokens), порог предупреждения (quota_warn_percent, по умолчанию 80%). Значение 0 выключает проверку по оси. Персональный потолок (ai_user_settings.monthly_token_quota) при > 0 подменяет глобальный пользовательский лимит.
  • Двухэтапный контроль:
    • Перед ходом пользователя в SendMessage (при превышении — HTTP 402 quota_exceeded, сообщение не сохраняется, текст в композере остаётся).
    • Перед каждым шагом вызова модели в цикле инструментов (при превышении — цикл прерывается с уведомлением).
  • Слоты маршрутизации:
    • strong (route_strong_provider_id, route_strong_model) — сильная модель исключительно для режимов spec и plan.
    • cheap (route_chat_provider_id, route_chat_model) — дешёвая модель для обычного чата, выполнения шагов плана и obs.
  • API: GET/PUT /api/v1/settings/quotas, GET/PUT /api/v1/settings/users/:userId/quota (роль admin).
  • Отчёт: «Мониторинг → Токены» (/monitoring/tokens) с фильтром по диапазону дат, группировкой по пространствам и выгрузкой CSV для финансового учёта.

API (кратко) ​

Assistants (каталог карточек) ​

Каталог кастомных ассистентов (Assistant, таблица ai_chat_agents):

  • GET /api/v1/assistants — список (доступ зависит от shared_user_ids)
  • GET /api/v1/assistants/:id — карточка ассистента

Примечание: после установки каталог пуст; карточки pptx/drawio/bpmn/doc-generator/code-* миграциями не создаются.

RAG (/api/v1/rag) ​

МетодПутьОписание
POST/rag/documentsIngest документа
GET/rag/scopesСписок scopes
GET/rag/scopes/:scopeНастройки scope
PUT/rag/scopes/:scopeUpsert настроек scope
POST/rag/scopes/:scope/reindexReindex embeddings scope
DELETE/rag/scopes/:scopeУдалить документы scope
DELETE/rag/scopes/:scope/settingsУдалить настройки scope

Decision (/api/v1/decide) ​

POST /decide — классификатор (capability=decision, типично Bosun). Тело: { state, questions[] } с типами choice / score / noul. Ответ: { answers[{question,chosen,confidence,slots_found}], provider, model }. Используется узлом Flow Manager Классификатор (aiClassifyNode). Без активного decision-провайдера — 404.

Полный список эндпоинтов (провайдеры, чаты, completions) — в Swagger UI: http://localhost:8101/swagger/index.html.

Prompt traces (debug) ​

Глобальный сбор трейса хода чата. По умолчанию выключен.

  • Вкл: Settings → AI Router → Tools → Collect prompt traces (PUT /api/v1/settings/prompt-trace, роль admin).
  • Хранение: таблица ai_turn_traces (JSONB payload, FK на messages), флаг messages.has_trace.
  • Просмотр: Monitoring → Chats → кнопка Trace у ответа ассистента → модалка. API: GET /admin/chats/:chatId/messages/:messageId/trace (секция monitoring_chats).
  • В payload: runtime (mode/model/tools/skills), фрагменты system prompt по источнику, метод выбора skills, tool defs, шаги LLM (role + provider/model: planner, chat, planner_synth, diagram_synth, plan_synth, obs_synth, evidence_synth; messages in / response out), финальный ответ.
  • Содержит пользовательский и системный текст — не держать включённым в проде без нужды. Старые трейсы остаются после выключения сбора.
  • Логи PROMPT_TRACE=true не связаны с этим UI.

Журнал ИБ (AI Audit Journal) ​

Отдельный неизменяемый (append-only) журнал для информационной безопасности. В отличие от Prompt Traces, журнал всегда включён и регистрирует каждый ход AI без сохранения текста запроса или ответа.

  • Что пишется:
    • Субъект и контекст: user_id, chat_id, message_id, origin, mode, карточка ассистента (agent_id, agent_slug).
    • Пространства и права: space_ids (извлечённые из space-{uuid}), полный список выданных scopes.
    • Модели: реально задействованные модели с ролями (chat, planner, diagram, synth и др.) и вендорами.
    • Инструменты: выданные имена tools и вызванные tools со статусом (ok, denied, error). Аргументы и результаты вызовов не пишутся.
    • RAG-источники: идентификаторы документов (document_id, source_id, title, scope), попавших в контекст. Текст чанков не пишется.
    • Метрики: токены (prompt, completion, total), длительность, статус (completed, failed), код ошибки.
    • Хеши: content_fingerprint (SHA-256 текста пользователя для линковки с DLP Guard) и детерминированный row_hash (SHA-256) записи.
  • Неизменяемость: таблица ai_audit_events защищена триггером PostgreSQL (BEFORE UPDATE блокирует любые изменения; BEFORE DELETE блокирует удаление без флага сессии ai_router.audit_purge = 'on').
  • Срок хранения (retention): параметр audit_retention_days (по умолчанию 365 дней, 0 — бессрочно). Фоновый воркер раз в сутки очищает устаревшие записи и сохраняет квитанцию с типом retention_purge (с указанием диапазона seq и количества удалённых строк).
  • Экспорт в SIEM:
    • Pull: GET /api/v1/admin/audit/turns?cursor= (NDJSON, доступ по секции monitoring_security).
    • Push: фоновый воркер отправляет пачки NDJSON на AUDIT_SIEM_URL (с токеном AUDIT_SIEM_TOKEN) и автоматически продвигает курсор audit_siem_cursor.
  • UI: доступен в Мониторинг → Журнал AI (/monitoring/ai-audit, секция monitoring_security). На этой же странице настраивается срок хранения и доступен ручной запуск purge.

Function calling / Tools ​

Инструменты регистрируются в internal/infrastructure/tools и подключаются через ToolRegistry в container. Клиент передаёт имена в tools[] на send message; при наличии scopes автоматически добавляется search_knowledge_base.

ToolSide effectsНазначение
run_commandcommand-manager: create jobЗапуск команды по имени/UUID
search_commandsread-onlyПоиск команд перед запуском
get_job_status / get_job_logs / stop_jobread / command-managerСтатус, логи, стоп job
run_flowflow-manager: test pipelineЗапуск/тест процесса
write_starlark_code / test_starlark_codenone / TryCodeNodeScaffold и прогон Starlark
create_task / update_task / search_tasks / get_task / change_task_statustask-trackerЗадачи в space
create_note / update_note / search_notes / get_notedocumentsЗаметки
create_drawio / update_drawio / read_drawiodocuments (draw.io)Диаграммы; capability diagram
create_bpmn / update_bpmn / read_bpmndocuments (BPMN)Процессные схемы
create_pptx / update_pptx / read_pptxdocuments / storageПрезентации; рендер из slideLayouts шаблона (pptx_template), вписывание текста по метрикам шрифта
search_media / get_media_filespark-gridМедиатека пространства
search_tables / get_table / create_table / *_table_rowsdata-tablesТаблицы в space
search_env / create_env / update_envenv-managerСекреты и конфиги
web_search / fetch_urlSearXNG / HTTPПоиск в вебе и загрузка URL
update_command_draft / update_note_draft / update_flow_draft / update_skill_draftnone (UI patch)Черновики в открытый редактор
search_knowledge_baseRAG readПоиск по scopes (авто при scopes)
ask_userUI clarifyУточняющий вопрос пользователю

UI-patch tools (update_*_draft) возвращают JSON; фронт слушает NATS ai.chat.tool.call / ai.chat.tool.result и применяет поля в открытый редактор.

PPTX-рендер и шаблоны ​

create_pptx принимает компактный IR (theme + slides, без координат). Рендер:

  • Шаблон — .pptx с настоящими slideLayout и placeholder (p:ph). Built-in: 4 темы (corporate|dark|minimal|pitch), генерируются кодом (BuildTemplate, 10 layout'ов). Загруженный через Settings → AI Router → Templates файл становится pptx_template (base64-пакет в ai_asset_catalog.body, ≤10MB, meta хранит маппинг canonical layout → layout шаблона). Рендер по slug: theme = <slug>. Тег default у шаблона делает его рендером дек без явной темы.
  • Сборка — слайд ссылается на layout шаблона и содержит только заполненные placeholder-шейпы: геометрия/стили наследуются от layout и master. Пустые слоты не эмитятся; карточки/колонки без контента дропаются.
  • Вписывание текста — advance-таблицы Calibri (regular/bold, латиница + кириллица + CJK-эвристика) → симуляция переноса → подбор размера из лестницы (−10% шаг до 12pt), затем normAutofit fontScale. vertOverflow clip больше не используется — текст уменьшается, а не обрезается.
  • Выбор темы — explicit slug → keywords каталога → FNV-ротация по тексту запроса (деки не «слипаются» в одной теме). Промпт архитектора предписывает выбирать тему по тону, enum в schema отсортирован.

Пакет деки дублируется в ppt/unishift/deck.json — веб-превью читает его напрямую из zip.

Режимы AI-чата (Chat Modes & Pipelines) ​

AI Router поддерживает 6 пайплайнов выполнения чата (mode), которые определяют доступность инструментов, глубину планирования, лимит шагов (MaxSteps) и встроенные системные промпты. Выполнение каждого режима настраивается карточкой в Настройки → AI Router → Процесс (/settings/ai-router/pipeline, таблица ai_pipeline_graphs): скиллы режима, MaxSteps, промпт цикла.

Режим (mode)Ключевое назначениеPlanner / RouterMaxStepsИтоговые артефакты / Поведение
chatОбычный диалог, Q&A и быстрая работа с контекстомМаленький planner (если есть tools)~3–6Прямой ответ, короткие вызовы read-only инструментов
multi-agentКомплексные и разветвлённые задачи с декомпозициейMulti-agent orchestrator (spawn_agent)~12Автоматический спавн изолированных дочерних субагентов и сборка их результатов
planПроектирование архитектуры, планов реализации и презентацийПропускает planner (LLM пишет plan.md)~10Создание/обновление файлов plan.md, интерактивное уточнение (clarify-first), слайды PowerPoint (create_pptx)
obsДиагностика инфраструктуры, логов, метрик и трейсовПропускает planner, использует Obs MCP~10Сбор метрик и логов через MCP Gateway / Grafana / Prometheus without destructive mutations
specФормирование спецификаций, ТЗ и описаний сервисовПропускает planner, подключает RAG/код~10Автоматическое сохранение итоговой спецификации в заметку (create_note) или файл (create_file)
sub-agentВыбранный Assistant или дочерний spawnНаследует agent loop~10Tools/skills/MCP только из этого ассистента (mcp_slugs). Пикер с agent_id идёт сюда, не в оркестратор. Spawn от multi-agent — тот же runtime, чат read-only.

Детальное описание режимов ​

1. Режим Chat (mode=chat) ​

  • Назначение: Быстрые ответы на вопросы, генерация текста, простые разовые команды.
  • Особенности: Использует короткий цикл диалога. Если к чату подключены инструменты, входным узлом становится локальный Planner, который определяет необходимые вызовы перед генерацией ответа.

2. Режим Multi-Agent (mode=multi-agent) ​

  • Назначение: Решение крупных составных задач, требующих параллельной или последовательной работы узкоспециализированных агентов.
  • Особенности: Оркестратор анализирует запрос и каталог доступных ассистентов. Через инструмент spawn_agent он создает изолированные дочерние чаты (mode=sub-agent), передает им контекст, дожидается выполнения и синтезирует финальный ответ. Выбор конкретного ассистента в пикере (agent_id) не включает оркестратор: ход идёт как sub-agent с MCP из mcp_slugs этого Assistant, без полного реестра gateway.

3. Режим Plan (mode=plan) ​

  • Назначение: Разработка планов интеграций, декомпозиция релизов, создание структуры презентаций.
  • Особенности:
    • Clarify-first: если запрос неоднозначен, сначала задаются уточняющие вопросы через ask_user.
    • Pinned plan.md: итоговый план сохраняется как закрепеленный документ; повторные правки перезаписывают его без мусора в истории.
    • PPTX Generation: если в плане описываются слайды, активируется рендер презентаций через create_pptx.

4. Режим Observability (mode=obs) ​

  • Назначение: Мониторинг, анализ сбоев, просмотр метрик и логов в реальном времени.
  • Где доступен: только в общем чате (без space scope); внутри пространства режим недоступен. MCP-серверы — все включённые в MCP Gateway, а не привязанные к пространству.
  • Особенности: Подключает MCP-инструменты наблюдаемости (Grafana, Prometheus, Sentry, Jaeger). Исключает мутирующие инструменты, отдавая приоритет безопасному сбору фактов и визуализации состояния.

5. Режим Spec (mode=spec) ​

  • Назначение: Составление регламентов, архитектурных спецификаций и технических заданий.
  • Особенности: Активно задействует RAG и поиск по исходному коду. После согласования текста автоматически создает заметку в пространстве (create_note) или сохраняет файл.
  • Шаблон: markdown kind: unishift-spec в prompt Chat Loop. Скиллы — graph.skill_slugs пайплайна spec; после установки список пустой. Правка — Управление ответами. create_task выключен.

Sidecar GGUF через ush platform enable llama-planner больше не ставится. Planner, diagram, fill, embed и Bosun подключаются вручную. Подробнее: Локальные модели.

Starlark ​

См. starlark-api.md — модуль up.ai_router (провайдеры, чаты, ingest_document с metadata, scopes).