Интеграция с Agentfy
Принятое направление · API слит · приложение реализовано · локальная проверка в браузере пройдена · 13 октября 2026 · общий контракт интеграции записан, Shiffty приведён к нему (восьмое поле, переключатель чата, обновление профиля на месте) 15 октября 2026 · проверено на локальной заглушке и локальном Agentfy, ничего не развёрнуто · с 14 октября 2026 чат в приложении был скрыт, а локальная замена Agentfy удалена в тот же день (её таблицы удалены 16 октября 2026) · чат снова показывается там, где API говорит, что ассистент доступен, а агента магазина подключают с его страницы — создано 19 октября 2026, проверено с локальным Agentfy, не развёрнуто · ассистент владельца — один агент на компанию, решено и создано 20 октября 2026, проверено с локальным Agentfy, не развёрнуто · ассистент компании подключается первым, при одобрении компании администратором платформы, решено и создано 23 октября 2026, не развёрнуто · ассистент владельца создаёт магазин, создано 23 октября 2026, проверено на Agentfy в памяти, не развёрнуто · новый профиль сам доходит до агентов каждой компании, решено и создано 23 октября 2026, проверено с локальным Agentfy, не развёрнуто · почему ассистент компании не настроился, видит администратор, с «Retry», а владелец — короткий текст без кодов, решено и создано 28 октября 2026, проверено с Agentfy в памяти, не развёрнуто · чат читает новые названия событий ответа Agentfy (AGNT2-596), создано 28 октября 2026, проверено на Agentfy в памяти и с локальным Agentfy, не развёрнуто · неделя, которую меняет карточка графика, рядом с чатом, создана 4 ноября 2026, проверена с Agentfy в памяти, не развёрнуто · описания спрашиваются до того, как строится неделя, в обоих ассистентах, создано 5 ноября 2026, проверено с Agentfy в памяти, с живым агентом не проверено, не развёрнуто
Каждый магазин получил бы собственного агента на платформе агентов Agentfy; управляющий и сотрудники этого магазина говорили бы с ним внутри приложения Shiffty, каждый от своего имени, и никогда не видели бы Agentfy. С 20 октября 2026 у владельца компании есть ещё один, собственный агент — сразу для всех магазинов.
Agentfy ведёт разговор; Shiffty хранит факты, проверяет каждое разрешение и рисует чат.
Как Shiffty ложится на Agentfy
В Agentfy три уровня, а не два:
Organization — сам Shiffty как партнёр: пространство имён, учётные данные
└─ Team — одна компания Shiffty
└─ Agent × N — по одному на магазин
└─ Agent — агент владельца, один на компанию (с 20 октября 2026)
ExternalIdentity — сотрудник или управляющий (externalUserId = идентификатор занятости в Shiffty)
или владелец (externalUserId = идентификатор пользователя владельца)
Conversation — один на пару (агент, человек)- Одна компания — одна команда; один магазин — один агент.
- Управляющий магазина и его сотрудники говорят с одним и тем же агентом, каждый со своей личностью. У сотрудника или управляющего доступ ровно к одному агенту, потому что каждый человек относится ровно к одному магазину (11 октября 2026; до этого управляющий должен был вести несколько). Владелец говорит с собственным агентом: см. ассистент владельца.
- Агента для магазина создавал бы сам Shiffty, когда создаётся магазин, через интерфейс провижининга Agentfy. Это зависит от оператора Agentfy; см. что должно быть верно сначала. В созданном (19 октября 2026) владелец или управляющие магазина также могут запустить или повторить это кнопкой «Connect assistant» на странице магазина (Экраны). В созданном API создание активного магазина уже пробует настроить его агента, когда Shiffty подключён к Agentfy; если попытка не удалась, больше ничего не ломается, а страница магазина показывает агента неготовым, с «Retry».
Как это записано на стороне Shiffty — на странице Структура данных.
Ассистент владельца
Решено владельцем 20 октября 2026; создано в тот же день, проверено на Agentfy в памяти и один раз сверено с локальным Agentfy, не развёрнуто. Это заменяет «нет ассистента для владельца» от 19 октября 2026.
- Один агент на компанию, а не на магазин. Он находится в команде компании в Agentfy рядом с агентами магазинов. Его внешний id — id компании (команды); у него собственный профиль со своей ревизией, поэтому изменение профиля агентов магазинов его никогда не затрагивает, и наоборот.
- Он создаёт команду компании в Agentfy (решение владельца проекта от 23 октября 2026; до этого он входил в команду, которую создал агент первого магазина, а подключить его раньше любого магазина было нельзя). Agentfy создаёт команду компании вместе с первым агентом, о котором его просят. Теперь ассистент компании подключается, когда администратор платформы одобряет компанию, поэтому первым агентом становится он, а агент каждого магазина, созданного позже, входит в его команду; ни один магазин не должен быть первым. Одобрение никогда долго не ждёт Agentfy и не срывается из-за него: если Shiffty не подключён к Agentfy или настройка не удалась, владелец видит в Stores Not connected или Failed с Retry. Компания, чью команду раньше создал агент магазина, сохраняет эту команду: сначала подключается тот магазин, а ассистент компании входит в его команду. Проверено с Agentfy в памяти, в том числе с падающим и медленным; не развёрнуто.
- Почему он не настроился, говорится (решение владельца проекта от 28 октября 2026; создано в тот же день, проверено только с Agentfy в памяти, не развёрнуто). Неудачная настройка сохраняет, что ответил Agentfy, — его код и HTTP-статус, никогда не его текст — как короткую причину, которая говорит, что делать, например «Agentfy rejected Shiffty's key for this organization (CREDENTIAL_REJECTED, 401)» или что Agentfy не ответил вовремя, и API пишет об этом одну строку в журнал. Администратор платформы видит её сразу после «Approve» и на карточке компании в «Requests», с «Retry», который продолжает ту же настройку и никогда не создаёт второго агента; компания, чей ассистент так и не был создан, показана как не настроенная, с «Retry». Владелец вместо неё видит короткий текст — «The company assistant could not be set up. We have been notified; press Retry later.» — без кодов и без того, что может сделать только администратор, в «Stores» и на своей вкладке Assistant, тоже с «Retry»; полная причина остаётся сохранённой для администратора. До этого причина была общей («could not be confirmed»), а администратор видел только «approved».
- Владелец говорит с ним от своего имени, со своей личностью — id пользователя владельца — и ролью, которую Agentfy называет owner. Shiffty никогда не сообщает Agentfy, что владелец ушёл: тогда Agentfy навсегда отнял бы владение командой. Доступ бывшего владельца просто истекает в течение минут, и Shiffty его отклоняет.
- С правами владельца, на все магазины. Каждый инструмент магазина принимает магазин, с которым работает; владелец называет любой магазин компании, а на неуказанный магазин отвечают списком магазинов. Права по-прежнему берутся из разрешения разговора, никогда не от модели; магазин вне компании не находится. Каждое изменение — карточка, которую владелец подтверждает в приложении, и подтверждение снова проверяет правила. Публикация недели есть только здесь, как карточка (инструменты).
- Подключается как ассистент магазина. Владелец подключает его вверху «Stores» (Company assistant: Not connected, Setting up, Ready или Failed, с «Connect assistant» или «Retry»), а локальный запуск подключает его первым (до 23 октября 2026 — после магазинов). Когда сброшенная база потеряла его ключ доступа, он так и говорит, и «Retry» выдаёт тому же агенту новый ключ, как для магазина. Владелец также может вывести его из работы; агенты магазинов остаются.
- Каждый агент видит только свои инструменты. Агент магазина по-прежнему обнаруживает ровно те инструменты и аргументы, что у него были; агент владельца обнаруживает инструменты владельца.
- Он может создать магазин (23 октября 2026, создано и проверено на Agentfy в памяти, с локальным Agentfy не сверено, не развёрнуто). Подтверждение карточки создаёт магазин и затем подключает ассистента магазина, как при создании в приложении; ассистент магазина подключается только после сохранения магазина, потому что Agentfy проверяет его инструменты ключом, который Shiffty для него сохранил. Оба профиля в тот день получили новую ревизию (владельца — 5, магазинов — 9): новые инструменты, продукт называется Shiffty, и простой ответ с местом в Shiffty, когда ни один инструмент не делает того, о чём просят. Сброс локальной базы после этого изменения отклоняет агентов, созданных до него, как описано ниже.
- Оба ассистента спрашивают недостающие описания, прежде чем строить неделю (просьба владельца от 5 ноября 2026; создано в тот же день, проверено с Agentfy в памяти, с живым агентом не проверено, не развёрнуто). Если у магазина, должности или человека, которого неделя запланировала бы, нет описания, инструмент солвера ничего не планирует и говорит, чего не хватает; ассистент сообщает это человеку, спрашивает то, что нужно неделе, записывает ответ в описания карточкой и строит неделю, когда её подтвердят, — или, только когда человек говорит строить без этого, строит и говорит, чего не было. У ассистента владельца есть карточка и для описания должности. Оба профиля получили новую ревизию (магазинов 15, владельца 11). Как это работает — на странице Инструменты агента.
Проверено 20 октября 2026 в рабочей копии с локальным Agentfy, от имени владельца демо-компании: на «чего не хватает на следующей неделе по магазинам?» ответ пришёл из обзора компании; просьба спланировать черновую неделю Harbor Street дала карточку солвера, которая спланировала и смены управляющего магазина, и, подтверждённая через маршрут приложения, записала 11 смен и убрала 6 в черновике, не опубликовав его; изменение должности и часов по договору управляющего и описание управляющего стали карточками, подтверждёнными. Найден и в тот же день исправлен один недостаток: инструмент магазина, вызванный без своего магазина, ронял весь ход; теперь он отвечает списком магазинов. Карточки подтверждались через маршрут подтверждения, а не нажатием в браузере. Затем копия вывела из работы своих пятерых агентов.
Два пути и почему виджет не подходит
| Путь | Что агент знает о человеке | Инструменты | Вывод |
|---|---|---|---|
| Встраиваемый виджет — готовый чат Agentfy, размещённый на странице | Ничего: посетитель для агента анонимен | Нет | Не используется |
| Партнёрский серверный чат — API Shiffty говорит с Agentfy от имени человека | Постоянная личность у каждого человека | Доверенный сервер инструментов, который запускает Shiffty, получает контекст человека при каждом вызове | Выбран |
Ассистент, который не отличает Анну от Бена, не может посмотреть смены Анны или отправить её запрос, поэтому виджет не подходит.
С партнёрским серверным чатом разговор рисует приложение Shiffty, а с Agentfy говорит API Shiffty. По порядку: сообщить Agentfy, что человек входит в команду компании → открыть разговор с агентом магазина → прикрепить к нему контекст человека → отправить сообщение → читать ответ по мере его появления.
Как разрешается вызов инструмента
Агенту никогда не верили бы на слово, от чьего имени он действует.
- Открывая разговор, Shiffty выписывает грант: какая занятость, какой магазин, какая роль и до какого времени. Он привязывает грант к этому разговору.
- Agentfy возвращает грант при каждом вызове инструмента — в заголовке
X-SD-Context, вместе с идентификаторами агента, разговора и хода. - Сервер инструментов Shiffty проверяет три вещи, прежде чем что-либо делать: грант ещё действует, магазин в нём совпадает с агентом, который вызывает, и роль в нём разрешает этот инструмент.
Один агент на магазин обслуживает обе роли. Какие инструменты разрешены, решает грант, а не агент: разговор сотрудника не может дотянуться до инструмента управляющего.
Сервер инструментов — это MCP-сервер; MCP — открытый стандарт подключения агентов к внешним системам. Это закрывает вопрос на странице Агент и солвер: инструменты доходят до агента через один MCP-сервер, который запускает Shiffty, а солвер остаётся обычным сервисом за ним.
Инструменты, которые получит агент
| Инструмент | Для кого | Что он будет делать |
|---|---|---|
| Прочитать мои смены | Сотрудник, управляющий | Смены человека в опубликованном графике |
| Проверить изменение | Сотрудник, управляющий | Нарушает ли конкретный обмен или выходной какое-то правило |
| Найти замену | Сотрудник, управляющий | Кто может взять смену, не нарушая правил, и чего это будет стоить |
| Объяснить отказ | Сотрудник, управляющий | Почему что-то невозможно и что это исправит |
| Подать запрос на изменение | Сотрудник | Передать подготовленное изменение коллеге, а затем управляющему |
Создано в API, не развёрнуто, как семь инструментов: my_shifts, check_change, find_cover, explain_refusal, submit_change_request и request_status для управляющих и сотрудников и team_week — неделя магазина — только для управляющих. submit_change_request — единственный, который ведёт к изменению, и изменение становится запросом, только когда человек подтверждает его карточку в чате; по запросу всё равно нужно решение. Ни один из них не составляет и не меняет график. С 19 октября 2026 года они — часть одного каталога вместе с девятью новыми инструментами чтения — день с покрытием, месяц, часы без дежурного управляющего, неделя одного человека, магазин, его люди, запросы на решение, один запрос, «Ждёт вас» — и плана, по которому ассистент шаг за шагом сможет делать то, что человек может в приложении, кроме решения по запросам и публикации недель: см. Инструменты агента.
«Построить график» — кнопка в приложении, а не инструмент агента. У вызова инструмента в Agentfy короткий предел времени (ниже), и построение графика для настоящего магазина может в него не уложиться. Распределение прав между ролями в таблице — предложение. Что делает солвер за этими инструментами — на странице Агент и солвер.
Чего Agentfy сегодня не делает и что поэтому остаётся за Shiffty
Ограничения ниже прочитаны в репозитории Agentfy 5 октября 2026. Контракт встроенного профиля повторно проверен 13 октября (AGNT2-476). В тот день SHIF-19 проверил локальную цепочку провижининг → ready → чат → вызов MCP-инструмента → done; размещённые и production-окружения не проверялись. См. слитую реализацию API.
| Ограничения Agentfy (5 октября; профиль и локальная проверка обновлены 13 октября 2026) | Что из этого следует для Shiffty |
|---|---|
| Партнёрский серверный чат завершил разговор с вызовом инструмента на локальном Agentfy 13 октября. | API слит. Чат приложения реализован в ветке SHIF-20, был скрыт с 14 октября 2026 и снова показывается с 19 октября 2026 (ниже). Работа с размещёнными и production-окружениями ещё не проверена. |
| Провижининг для организации включается только в базе данных Agentfy, его оператором. | Оператор должен включить его для организации Shiffty, прежде чем магазин сможет автоматически получить агента. |
| Agentfy принимает профиль агента прямо в запросе в рамках политики организации, одобренной оператором (AGNT2-476); шаблонов агентов больше нет. | Shiffty версионирует имя, инструкции, skill и обязательные инструменты в коде как profileRevision и передаёт их в agent.profile. Политика ограничивает модели, MCP-хосты, доверенный контекст, worker-инструменты и исходящие соединения. |
| Агент не может начать сообщение первым: исходящих уведомлений нет. | Сообщать человеку, что его что-то ждёт, — дело Shiffty: список «Ждёт вас» на странице Экраны. |
| У вызова инструмента 15 секунд. | Инструменты должны отвечать быстро; построение графика остаётся кнопкой в приложении. |
| За один ход — не больше 3 вызовов инструментов, меняющих данные. | Одна просьба сотрудника должна уложиться в несколько шагов; инструменты Shiffty делаются под это. |
| Ровно один доверенный MCP-сервер на разговор. | Все инструменты Shiffty стоят за одним сервером. |
| В партнёрских ходах нет памяти о человеке между разговорами. | Состояние хранит Shiffty и каждый раз передаёт агенту факты. |
| Оплата использования за счёт организации не готова к эксплуатации. | Как Shiffty платил бы за разговоры своих магазинов, не определено. |
Чат в приложении
Снова показывается с 19 октября 2026 (решение владельца, насовсем), когда API говорит, что он доступен; создано, проверено только с локальным Agentfy, не развёрнуто. Приложение спрашивает API при входе и при открытии вкладки: GET /v1/me отвечает assistant с available, причиной словами (reason) и кодом (code) — not_connected (у Shiffty нет подключения к Agentfy в «Settings» приложения администратора), chat_off (нет ключа серверного чата), agent_not_ready (агент этого магазина не готов) или, с 20 октября 2026, owner_agent_not_ready (собственный агент владельца не подключён или не готов; до этого код owner говорил, что у владельца его нет), и без кода, когда он доступен. Если доступен, вкладка Assistant каждой роли — чат ниже, и ссылки «Ask the assistant» в других местах показаны. Если недоступен, вкладка говорит обычными словами почему и кто может это исправить — администратор платформы в «Settings» или управляющий магазина либо владелец на странице магазина, — а ссылки скрыты. Когда ассистент владельца не готов, вкладка владельца так и говорит и с 28 октября 2026 показывает самого ассистента компании — его состояние, почему настройка не удалась, и «Connect assistant» или «Retry» (выше); до этого она вела на «Stores». Агент магазина показывается и подключается на странице магазина: GET /v1/stores/:id/agent даёт Not connected, Setting up, Ready или Failed с безопасной причиной и profileUpdateError, когда агент ещё работает на старом профиле; «Connect assistant» или «Retry» вызывает POST /v1/stores/:id/agent (владелец и управляющие этого магазина). Настройка продвигается только с POST, поэтому, пока она идёт, страница отправляет его снова каждые 3 секунды, не больше 20 раз. С 19 октября 2026 агент считается готовым, только пока Shiffty хранит ключ доступа, который выдал этому агенту: после сброса локальной базы (те же id магазинов, агент в Agentfy жив) магазин показывает Failed с этой причиной вместо Ready, а «Connect assistant» или «Retry» выдаёт тому же агенту новый ключ; проверено только с локальным Agentfy. Тоже с 19 октября 2026 после локального пересева нажимать ничего не нужно: как только локальный API отвечает, запуск у разработчика входит как владелец демо-компании, так же подключает каждый активный магазин, всегда в одном порядке, и печатает по строке на магазин — Ready или Failed с причиной; проверено только с локальным Agentfy. Чего это пока не умеет: если профиль агента изменился между его созданием и сбросом, Agentfy отказывает в новом запросе (он хранит исходный и не даёт найти агента по id Shiffty), такой магазин показывает Failed с этой причиной, и агента приходится вывести из работы в Agentfy, потеряв его разговоры, прежде чем подключить снова. См. Экраны.
С 14 по 19 октября 2026 вкладка Assistant каждой роли говорила «Assistant · In development» и что, пока он не готов, всё делается вручную на других вкладках, — за константой в приложении; ссылки, которые открыли бы ассистента, были скрыты. Этой константы больше нет. Демо по сценарию (11 октября 2026), которое отвечало на несколько фиксированных вопросов заготовленными ответами, удалено из кода, и запасного варианта по сценарию нет: когда API отвечает, что Agentfy не настроен, приложение снова спрашивает GET /v1/me и показывает панель.
В тот же день из API убрана локальная замена Agentfy — режим (AGENTFY_INTEGRATION_MODE=fake), в котором API сам играл Agentfy, с коротким сценарием вместо модели, и хранил свои разговоры в пяти собственных таблицах; миграция 20261016T1038_drop_fake_agentfy (Prisma 8, 16 октября 2026) удаляет эти таблицы. Локальные запуски теперь идут с выключенной интеграцией. Оставшийся fake — в переменных окружения или в сохранённой строке Settings — считается выключенным, с причиной в Settings и предупреждением в журнале API, и Settings его больше не принимают. Настоящий режим организации, MCP-сервер с его семью инструментами, разрешения, журнал аудита и карточки подтверждения не изменились. Автотесты API проверяют их в режиме организации с заменой Agentfy в памяти, которая живёт только в тестах: модель играет сам тест, вызывая MCP-сервер с разрешением, которое Shiffty привязал к разговору.
Ниже описан чат, каким он был реализован в ветке SHIF-20 и проверен в браузере с локальным Agentfy 13 октября 2026, и проверен снова в браузере с локальным Agentfy 19 октября 2026. Управляющий и сотрудники видят агента магазина, когда API сообщает о его доступности; с 20 октября 2026 владелец так же видит собственного агента.
Разговор загружается из сохранённой истории. Приложение показывает полученный текст и состояния инструментов без выдуманного прогресса. При разрыве соединения ответ остаётся неподтверждённым; его можно восстановить с тем же сообщением. Графики и запросы остаются доступны.
26 октября 2026 Agentfy переименовал события ответа (AGNT2-596): текст теперь приходит кусками под новыми названиями, начало и конец работы инструмента называются иначе, а последнего сообщения с полным текстом больше нет. Shiffty новых названий не знал, поэтому с того дня каждый ответ заканчивался словами «The run could not be confirmed», хотя Agentfy его завершил. С 28 октября 2026 API читает и старые, и новые названия, собирает полный текст из кусков, пропускает незнакомое событие вместо ошибки и пишет в журнал одну строку, без содержания разговора, когда поток ответа обрывается. Создано, проверено на Agentfy в памяти, говорящем на обоих вариантах, и с локальным Agentfy 28 октября 2026 (ответ сотруднику и карточка магазина у владельца); не развёрнуто. Названия — в api/AGENTFY.md.
Проверенное изменение появляется карточкой с описанием от сервера. Send request отправляет запрос коллеге и принимающему решение, но не меняет график. Карточки сохраняются после перезагрузки; повтор подтверждения восстанавливает тот же запрос. No сохраняет отказ для этой карточки. С 4 ноября 2026 у карточки, меняющей неделю (create_week, change_week, solve_week), есть Show week: неделя открывается рядом с чатом с изменениями карточки — их пробуют со всеми правилами и отбрасывают, поэтому это то, что запишет подтверждение, — а после подтверждения неделя показана сохранённой (экран 13).
Настройки оператора
Сделано в ветке SHIF-23, 14 октября 2026; восьмое поле добавлено 15 октября 2026; проверено на локальной заглушке, не на размещённом Agentfy и не развёрнуто. Подключение больше не живёт в переменных окружения, а в одной строке Setting (agent/agentfy), которую администратор платформы правит в разделе Settings админ-приложения — отдельного приложения рядом с API и приложением с 18 октября 2026 (SHIF-36), созданного и не развёрнутого; до того Settings были разделом приложения. Поля в порядке, общем для всех проектов с Agentfy: режим (off, fake, organization), URL API, идентификатор организации, окружение (test или production), ключ provisioning, ключ server chat, URL MCP, модель. Точные имена, типы и переменные окружения — в контракте ниже. Оба ключа хранятся запечатанными (AES-256-GCM под ключом вне базы) и больше не показываются — чтение сообщает лишь, задан ли ключ, а пустое поле при сохранении его сохраняет. Сохранение атомарно и отклоняется, если кто-то сохранил раньше; смена организации, окружения, origin или режима требует явного переподключения, которое отбрасывает агентов, команды и разговоры прежнего подключения, чтобы их идентификаторы не использовались повторно. «Test connection» проверяет API, оба права и URL MCP по отдельности и не выдаёт это за сквозной сценарий — его доказывает только подготовленный магазин. Кто какие поля менял, записывается по именам, никогда по значениям. Каждый работающий API подхватывает изменение не позднее чем за 15 секунд. Импорт старых переменных окружения — явное действие. Механизм описан в api/AGENTFY.md в репозитории.
Контракт интеграции с Agentfy
Четыре продукта подключаются к Agentfy одинаково — Bonsite, Securify, Shiffty и Store Deputy, — и Shiffty является эталоном, к которому приводятся остальные три. Этот раздел — общий контракт, записанный так, чтобы на него мог ссылаться тикет любого из четырёх. Где этот текст и код Shiffty расходятся, прав текст, а Shiffty исправляется (SHIF-24 сделал это 15 октября 2026); остальные следуют в своих тикетах той же серии.
Одна группа настроек с одними восемью полями, один движок настроек, один способ читать соединение, один каркас MCP, один формат профиля. Продукт может отличаться только инструментами, текстом своего агента и собственными экранами провижининга и чата.
Восемь полей agent/agentfy
Ровно эти, в этом порядке, с этими именами, типами и переменными окружения. Формат определения — как в api/src/slices/setup/agentfy/setting/agentfySetting.ts Shiffty: у поля есть name, label, type (string, url, enum или secret), options, default, required, placeholder, help, env; у группы — title, description, fields, reconnectFields (mode, apiUrl, organizationId, environment), validate(data, {production}), возвращающая {field: problem}, и fromEnv(env).
| # | Поле | Тип | По умолчанию | Переменная окружения | Правило |
|---|---|---|---|---|---|
| 1 | mode | enum off · organization | off | AGENTFY_INTEGRATION_MODE | Shiffty: оставшийся fake выключен и не сохраняется (с 14 октября 2026) |
| 2 | apiUrl | url | — | AGENTFY_URL | только origin — без пути, query, fragment и учётных данных; HTTPS, простой HTTP только для loopback вне production |
| 3 | organizationId | string | — | AGENTFY_ORG_ID | A-Za-z0-9._:-, от 1 до 128 символов |
| 4 | environment | enum test · production | test | AGENTFY_ORG_ENVIRONMENT | должно совпадать с окружением ключей |
| 5 | provisioningKey | secret | — | AGENTFY_ORG_KEY | orgk_… |
| 6 | serverChatKey | secret | — | AGENTFY_CHAT_KEY | orgk_…, отличается от provisioningKey; задан — чат включён, пуст — чат выключен; в organization не обязателен |
| 7 | mcpUrl | url | — | MCP_PUBLIC_URL | точный публичный адрес POST /mcp этого API; обязателен в organization |
| 8 | modelId | string | пусто | AGENTFY_MODEL_ID | пусто — первая модель, разрешённая политикой организации; передаётся в profile.modelId при провижининге |
validate везде одна: в organization обязательны apiUrl, mcpUrl, organizationId, environment и provisioningKey, serverChatKey опционален, но если задан — orgk_… и не равен provisioningKey; apiUrl без пути, query, fragment и учётных данных. Старые имена — AGENTFY_MODE, AGENTFY_API_URL, AGENTFY_ENVIRONMENT, AGENTFY_PROVISIONING_KEY, AGENTFY_SERVER_CHAT_KEY, AGENTFY_MCP_URL, AGENTFY_CHAT_ENABLED, AGENTFY_TEMPLATE_* и режимы legacy/live — не читаются нигде, и .env.example и документация больше не упоминают их как действующие. До 14 октября 2026 в контракте был и режим fake (замена Agentfy внутри API для разработки, запрещённая в production, которой нужен был только mcpUrl); Shiffty убрал его по решению владельца, а уберут ли его три других продукта — решают их собственные тикеты.
Движок настроек
Один слайс, setup/setting, как в Shiffty, который ничего не знает про Agentfy. Строка Setting хранит scope, scopeKey, group, code, version, data, source (database или env), enabled, lastCheck, lastCheckAt, updatedAt, updatedBy. Секреты запечатаны под SETTINGS_KEY (secret box; перезапечатываются при старте после ротации с SETTINGS_KEY_PREVIOUS), сохранения атомарны под optimistic version, каждое изменение записывается в аудит по актору, действию и именам полей, а API читает типизированный снимок. Определения групп подключаются через SettingModule.forRoot([...]).
Одно место, где читают соединение
setup/agentfy/connection.ts экспортирует тип IAgentfyConnection — mode, source (database, env или none), reason, refused, apiUrl, organizationId, environment, provisioningKey, serverChatKey, mcpUrl, modelId — и функцию currentConnection(). Больше никто не читает process.env.AGENTFY_* и не держит свою копию: ни обёрток на хранилище запроса, ни внедрённых снимков, ни settingValue(). Всё через currentConnection().
REST для администраторов
Для администратора платформы, не владельца команды; generic по group и code:
| Маршрут | Что делает |
|---|---|
GET /settings | все группы с полями (секрет показывает только hasValue), source, version, enabled, state, lastCheck, importable |
GET /settings/:group/:code | одна группа в той же форме |
PUT /settings/:group/:code | тело {version, data: {field: string | {op: 'keep' | 'replace' | 'clear', value?}}, source?, enabled?, reconnect?}; 400 с fields при отказе, 409 SETTING_VERSION_CONFLICT или SETTING_RECONNECT_REQUIRED, 503 SETTINGS_KEY_MISSING |
POST /settings/:group/:code/import | тело {version}: импорт переменных окружения, значения не возвращаются |
POST /settings/:group/:code/test | результат проверки ниже; агентов не создаёт и модель не запускает, если на то нет отдельной явной кнопки |
POST /settings/:group/:code/reconnect | {removed, setting} |
GET /settings/:group/:code/audit | кто какие поля менял, никогда значения |
POST /settings/rotate | необязателен, единственный маршрут вне group/code: перезапечатать все секреты текущим SETTINGS_KEY после ротации; если у продукта он есть — именно такой |
Типы ответов — admin/slices/setting/domain/setting.types.ts Shiffty: ISetting, ISettingField, ISettingCheck, ISaveSetting и SecretOperation с ключом op.
Форма результата проверки
{
"at": "2026-10-15T09:00:00.000Z",
"mode": "organization",
"ok": true,
"checks": {
"api": { "status": "ok", "detail": "…" },
"provisioning": { "status": "ok", "detail": "…" },
"chat": { "status": "skipped", "detail": "…" },
"mcp": { "status": "ok", "detail": "…" },
"mcpEndToEnd": { "status": "skipped", "detail": "…" }
},
"note": "…"
}Каждая проверка — ok, failed или skipped с понятным человеку detail. Пять аспектов различаются и никогда не выдают сетевой ответ за весь сценарий: MCP end to end доказывает только подготовленный магазин.
Административный интерфейс
Один слайс setting: store с fetchSettings, saveSetting, importSetting, testSetting, reconnectSetting, fetchAudit; одна generic-карточка группы, рендерящая поля из реестра (admin/slices/setting/components/setting/group/Card.vue Shiffty); CHECK_LABELS для пяти аспектов. Никаких захардкоженных путей на одну группу и никакого собственного логина в store.
Один каркас MCP
POST /mcp, Streamable HTTP, stateless. Bearer — credential агента; грант беседы приходит в заголовке X-SD-Context. Без учётных данных или с неверными: 401 с WWW-Authenticate: Bearer. Любой другой метод: 405. JSON-RPC batch: 400. Слайсы — mcp/server, mcp/policy, mcp/grant и mcp/credential. Между продуктами отличаются только таблица инструментов и политика вызова. Режим fake живёт в setup/agentfy/fake и ходит в тот же /mcp.
Профиль агента
Один тип, IAgentfyProfile: {name, instructions, skill: {name, description, body}, modelId?, mcp: {url, requiredTools, trustedContext: true}}, в файле agent/<product>Provision/domain/<product>Profile.ts рядом с PROFILE_REVISION и REQUIRED_TOOLS (в Shiffty: agent/orgProvision/domain/storeAgentProfile.ts). Провижининг замораживает профиль в intent. Когда PROFILE_REVISION повышают, профиль обновляется на месте через PUT /v1/orgs/{org}/operations/{operationId}/profile {expectedVersion, profile} Agentfy (AGNT2-477), без пересоздания агента; profileRevision хранится в intent, а неудавшееся обновление GET /stores/:id/agent показывает как profileUpdateError, пока агент продолжает работать на прежнем профиле. modelId берётся из настройки.
Агенты каждой компании, а не только демо (решение владельца, 23 октября 2026). До этого агент получал новый профиль только тогда, когда кто-то запускал его провижининг, и компания, которую никто не трогал, оставалась на старом (23 октября 2026 ассистент реальной компании остался на ревизии владельца 4 после выхода ревизии 5 и продолжал говорить, что не может создать магазин). Теперь API Shiffty раскатывает профиль сам: примерно через 10 секунд после старта и затем раз в час он находит каждого готового агента со старой ревизией — в одобренной и активной компании и в активном магазине — и обновляет его на месте, по одному, под той же арендой компании, что и кнопка подключения у человека. Он никогда не создаёт, не подхватывает и не выводит агентов из работы. Отклонённое обновление записывается в profileUpdateError и повторяется при следующем запуске; агент продолжает работать на старом профиле. В админке у одобренной компании в разделе Requests видны её ассистенты с ревизией профиля относительно текущей, последняя ошибка и кнопка Update now. Локальная рабочая копия делает это только с AGENTS_CONNECT=1, как и подключение агентов демо. Проверено на Agentfy в памяти и один раз с локальным; не развёрнуто.
Что может отличаться между продуктами
Только это: набор MCP-инструментов и политика их вызова; текст профиля агента (name, instructions, skill); провижининг и чат как продуктовые слайсы. Всё остальное выше одинаково.
Что значит «готово»
Тикет этой серии готов, когда: реестр содержит восемь полей с именами и переменными окружения из таблицы, буквально; поиск по старым именам ничего не находит; GET /settings отдаёт agent/agentfy в описанной форме; админ-форма сохраняет, импортирует и проверяет через generic-маршруты; POST /mcp отвечает как описано; провижининг и чат проходят end-to-end локально в режиме fake; а в режиме organization против локального Agentfy провижининг доходит до ready и ассистент отвечает в чате. Отчёт открывается объяснением для того, кто не открывал репозиторий, перечисляет выполненные проверки с результатами и говорит, что не проверено.
Не решено
- Какую языковую модель использовать в production. Настройка
modelId(по умолчанию пустая) называет одну в рамках одобренной политики; пустая оставляет выбор первой разрешённой модели Agentfy. Shiffty оставляет её пустой. - Что агенту сообщается о магазине в начале разговора, а что он обязан каждый раз запрашивать.
- Использует ли Agentfy демо, запланированное на 18 октября. Эта страница не меняет план.
Что читать дальше
- Инструменты агента: каталог, его уровни и план.
- Агент и солвер: что считает график за инструментами.
- Структура данных: где записаны агент, разговоры и гранты.
- Экраны: два экрана ассистента, 13 и 16, и что вкладка Assistant показывает сегодня.
- Открытые вопросы: что решено, а что нет.