Реестр артефактов (Artifact Registry)
#1. Цель
Ввести артефакт как first-class ресурс Temporality: ссылочный документ (регламент о качестве кодирования, утверждённая инструкция, чек-лист безопасности, список одобренных библиотек), который навыки указывают в манифесте, но который никогда не попадает в промпт неявно — агент загружает его по требованию, когда задача совпала с условием применимости.
Ключевой принцип документа: содержимое артефакта раскрывается
постепенно. Навык в системном промпте — это digest ≤1500 символов;
SKILL.md целиком — по skill_inspect; связанный регламент целиком — по
artifact_read. Третий уровень раскрытия закрывает класс задач «навык
знает, что существует регламент, но не тащит его в каждый ран».
Второй принцип: реестр — это указатель + права, а не обязательно хранилище тела. Для builtin-провайдера документ лежит в Postgres, для внешних (СЭД, Confluence, S3) — у нас только ссылка и контракт доступа. Выбор бэкенда — конфигурация инсталляции, не код (тот же вывод, что у секретов, docs/secrets-management.md §10).
#2. Проблематика текущего состояния
- SKILL.md — процедура, а не библиотека. Регламент на 40 страниц не влезает ни в digest, ни в разумный SKILL.md; попытка вместить убивает бюджет промпта для всех ранов, включая те, где регламент не нужен.
- Копии расползаются. Один «Регламент качества» нужен пяти навыкам; вставка текста в каждый SKILL.md создаёт пять независимо стареющих копий.
- Нет аудита чтений. Для утверждённых инструкций обычно главный вопрос комплаенса — «кто, когда и какую версию документа читал». Сегодня он неотвечаем.
- Нет управления доступом. Документ может относиться к подразделению; URL в тексте навыка виден всем, кто видит навык.
- Ссылки гниют. URL в Confluence/СЭД переезжают при реорганизации портала — навык молча теряет опору.
- Внешние хранилища недоступны агенту. Корпоративный документ живёт в СЭД за SSO; песочница агента без сети и без креденшелов человека.
#3. Основные понятия
#3.1. Artifact (артефакт)
Org-scoped ресурс (как секреты, навыки и агенты):
workspace_artifact
id TEXT PRIMARY KEY
title TEXT -- человекочитаемое имя
description TEXT -- КОГДА читать этот документ (условие применимости)
provider TEXT -- builtin | url (будущее: s3, sed)
external_ref TEXT -- ссылка во внешней системе (для не-builtin)
content TEXT -- тело документа (builtin)
content_hash TEXT -- sha256 тела, пересчитывается на записи
size_bytes BIGINT
mime_type TEXT -- text/markdown по умолчанию
org_unit_id TEXT NULL REFERENCES org_unit(id) -- NULL = вся инсталляция
created_at / updated_at
description — важнейшее поле модели. Это не аннотация содержания, а
условие применимости («читай перед ревью PR, если затронута
криптография»). Именно по нему агент решает, грузить документ или нет;
болванка «см. документ» здесь бесполезна так же, как бесполезный заголовок
группы в прайминге.
#3.2. Artifact Reference (ссылка из навыка)
Поле манифеста skill.yaml:
artifacts:
- id: coding-standard
note: применимо к любому коду на Go в этом репозитории
Ссылка версионируется вместе с навыком (манифест иммутабен в рамках
версии), а тело документа живёт своей жизнью: регламент обновляется
независимо от процедуры. Воспроизводимость («на какой версии регламента
основано решение») восстанавливается по content_hash в событиях чтения,
а не хранением снапшотов в каждом навыке.
#3.3. Artifact Provider (провайдер хранилища)
builtin— тело в Postgres (лимит 2 МиБ на документ). Не добавляет точек отказа: та же БД, что реестр навыков.url— только ссылка; тело в корпоративной системе.artifact_readотдаёт метаданные +external_ref; загрузка тела — через web_fetch, если он разрешён агенту, или через прокси ядра (фаза 3).- Будущее:
s3(объект в корпоративном бакете, читает ядро),sed/ ECM (адаптер к СЭД с авторизацией ядра). Все они переиспользуютexternal_refи не меняют модель ссылок.
#3.4. Прогрессивное раскрытие
digest навыка "Artifacts: 2 reference docs (skill_inspect)" — ~50 симв.
↓ skill_inspect
список артефактов title + description (когда читать) + note — ~200 симв./шт.
↓ artifact_read
тело документа чанками по 32 КиБ + checksum — по требованию
#4. Принципы
- Неявного попадания в промпт нет. digest навыка упоминает только
количество артефактов; тела грузятся исключительным явным вызовом
artifact_read. - Реестр — указатель + права. Хранение тела — деталь провайдера.
- Ссылка стабильна, тело живо. Навык указывает на id, а не на слепок
версии; аудит чтений фиксирует
content_hash. - Чтение по совпадению, не превентивно. Системный промпт фиксирует
контракт: грузи артефакт, когда задача совпала с
description, а не «на всякий случай». - Аудит не блокирует чтение. Событие
artifact.readпишется best-effort: сбой журнала не должен лишать агента документа (мутации, напротив, аудируются в той же транзакции, где это критично).
#5. Модель доступа
- Видимость по оргдереву — тем же правилом, что остальные ресурсы:
org_unit_id IS NULLилиorg_unit_id IN path(U). - RBAC API: reader — чтение; writer — создание и изменение; operator — удаление.
- Org-привязка не меняется при редактировании — только через администраторский binding-endpoint (тот же контракт, что агенты, секреты и MCP-серверы).
- Удаление занятого артефакта запрещено: если на id ссылается хотя бы один манифест навыка, DELETE отвечает 409 со списком навыков. Сначала убери ссылку (новой версией навыка), потом удаляй документ.
- Путь агента идёт через ядро с сервисным токеном kernel-internal; в фазе 1 видимость на этом пути инсталляционная (как у skills сегодня), org-фильтрация работает на API для людей. Уточнение агентской execution-identity — вместе с общей работой по агентским правам.
#6. Инструменты агента
artifact_search(query?)— поиск по реестру: id, title, description, provider, size. Ключевые слова матчатся по любому вхождению (как skill_search), детерминированный порядок.artifact_read(artifact_id, offset?)— тело документа чанком 32 КиБ:{content, offset, next_offset, truncated, checksum, size_bytes}. UTF-8-safe граница чанка. Дляprovider=urlядро само забирает тело (egress только у ядра — как у секретов), кэширует его в памяти с TTL 15 минут и раздаёт тем же конвертом; при недоступности внешней системы — тег «внешний документ недоступен» с указанием артефакта и причины.
skill_inspect показывает разрешённый список артефактов навыка (title,
description, note) — без отдельного вызова на каждый id.
#7. Аудит
artifact.read— событие journal:(run_id, artifact_id, checksum, offset, bytes). Попадает в трейс рана с локализованной подписью, агрегируется в таймлайне, экспортируется как остальные события.- Мутации — access audit:
artifact.created/artifact.updated/artifact.deleted(кто менял метаданные и тело).
Разделение то же, что у секретов: чтение — поток наблюдаемости, мутации — журнал доступа.
#8. API
GET /v1/workspace/artifacts— список без тел (org-visible).POST /v1/workspace/artifacts— создание (writer). builtin требует content ≤ 2 МиБ; url требует валидный http(s) external_ref.GET /v1/workspace/artifacts/{id}?offset=&limit=— метаданные + чанк тела (limit=0 — целиком). Ядро читает чанками, UI — целиком.PUT /v1/workspace/artifacts/{id}— обновление; hash пересчитывается.DELETE /v1/workspace/artifacts/{id}— operator; 409 если занят манифестами.GET /v1/workspace/artifacts/references— картаartifact_id → [skill_id]по видимым навыкам (для индикатора «занят N навыками» в UI).
#9. UI (фаза 2)
- Раздел «Артефакты»: список с фильтрами по оргединице и провайдеру, редактор тела (markdown), индикатор «занят N навыками».
- В редакторе навыка — привязка артефактов к манифесту выбором из реестра.
- В трейсе рана —
artifact.readкомпактной строкой («Артефакт прочитан · coding-standard · 12.4 KiB»).
#10. Фазы реализации
#Фаза 1 — реестр builtin + тулы (закрывает основную боль)
Таблица + миграция; CRUD API с org-видимостью и RBAC; artifacts в
манифесте навыка + строка в digest; разрешение ссылок в
GET /skills/{id}; тулы artifact_search / artifact_read с чанками;
событие artifact.read + подпись в трейсе; guard на удаление занятого.
Управление — через API. Внешних зависимостей нет.
#Фаза 2 — UI и url-провайдер
Раздел UI и привязка в редакторе навыка; честный url-провайдер: прокси чтения через ядро (egress только у ядра, как у секретов), кэш с TTL, тегging «внешний документ недоступен».
#Фаза 3 — корпоративные хранилища и зрелость
Адаптеры S3 и СЭД/ECM (авторизация ядра, маппинг метаданных, выгрузка тела в builtin-кэш по требованию); версионирование содержимого (история tел + снапшоты для комплаенса); полнотекстовый/семантический поиск по содержимому. Предложения артефактов от агентов с человеческим apply и жизненный цикл (draft → review → approved) выделены в отдельный документ: docs/artifact-lifecycle.md.
#11. Критерии готовности
#Фаза 1
- Навык с артефактом в манифесте: digest упоминает только количество;
skill_inspectпоказывает описания;artifact_readотдаёт тело чанками с корректнымnext_offsetна границе UTF-8. - Чтение артефакта эмитит
artifact.readс checksum; в трейсе — локализованная строка. - Артефакт с
org_unit_idне виден читателям чужого поддерева через API. - DELETE занятого манифестом артефакта отвечает 409 со списком навыков.
- Обновление тела меняет
content_hashиsize_bytes.
#Фаза 2
- Весь сценарий создания навыка с артефактом проходится из UI без curl.
- url-артефакт читается агентом без прямого egress песочницы.
#Фаза 3
- Инсталляция с СЭД и с builtin проходит один сценарий без изменений в навыках.
- История тел восстанавливает содержимое на любую дату.
#12. Открытые вопросы
- Версионирование тел: события с checksum против полноценных снапшотов — решить при первом комплаенс-требовании.
- Полнотекстовый поиск по содержимому (сейчас — только метаданные); tsvector против внешнего индекса.
- Лимиты (2 МиБ на документ, 32 КиБ чанк) — тюнить по метрикам использования, а не заранее.
- Нужна ли агентская execution-identity фильтрация артефактов на пути ядра (сейчас инсталляционная видимость, как у skills).
#13. Архитектурные ограничения
- Артефакты не привязываются к проектам: сквозной ресурс оргструктуры (тот же принцип, что агенты, навыки, секреты и MCP-серверы).
- Тело builtin-артефакта не шифруется: это не секрет. Конфиденциальные
материалы не загружаются в артефакты без org-привязки; доступ к
системам — только через
secret://. - Реестр не становится зависимостью ранов без артефактов: недоступность внешнего провайдера касается только тех, кто явно читает его документы.
- Единственный клиент внешних хранилищ — ядро. Песочница не получает ни креденшелов СЭД, ни сетевого egress под загрузку документов.