Эталонное развертывание Managed Agent
Эталонный дистрибутив Managed Agent носит экспериментальный характер. Принятая начальная топология: одна управляющая плоскость Java и встроенный Runtime Broker на одном доверенном Linux-хосте, одна база данных MySQL и один совместимый Qwen Hosted Harness. Манифест совместимости в каждом релизе является авторитетным для этого релиза.
Проверка и распаковка
Загрузите архив, отдельный манифест и SHA256SUMS.txt из одного и того же GitHub-пререлиза. Проверьте их перед распаковкой:
sha256sum --check SHA256SUMS.txt
tar -xzf qwen-managed-agent-reference-<version>.tar.gz
cd qwen-managed-agent-reference-<version>
sha256sum --check SHA256SUMSИзучите manifest.json. Убедитесь, что source.revision — это проверенная ревизия, compatibility.qwenCodeVersion совпадает с установленной версией CLI/Harness, а compatibility.databaseSchema.latestMigrationVersion приемлема для целевой базы данных. Релиз считается недействительным, если какая-либо проверка контрольных сумм или совместимости не пройдена.
Предварительные требования
- Linux на доверенном хосте приложений.
- JDK 21 или новее.
- Node.js, соответствующая
compatibility.node, и Qwen Code, соответствующаяcompatibility.qwenCodeVersion. - MySQL 8 с пустой базой данных или базой данных, ранее управляемой более старой совместимой эталонной сборкой.
- Закрытые, постоянные каталоги для состояния Runtime и авторизованного рабочего пространства.
- Стабильные учетные данные базы данных, связка ключей учетных данных Runtime и токен Harness, хранящиеся отдельно от архива.
Java-архив не содержит npm CLI. Установите или соберите точную совместимую ревизию Qwen Code отдельно и укажите путь к dist/cli.js для воркеров Runtime.
Запуск Hosted Harness
Выберите один токен и дайджест возможностей и передайте те же значения Harness и Java-сервису:
export QWEN_MANAGED_AGENT_HARNESS_TOKEN='<private-random-token>'
export QWEN_MANAGED_AGENT_CAPABILITY_DIGEST='sha256:<64-hex-digest>'
QWEN_SERVER_TOKEN="$QWEN_MANAGED_AGENT_HARNESS_TOKEN" \
QWEN_HOSTED_HARNESS_CAPABILITY_DIGEST="$QWEN_MANAGED_AGENT_CAPABILITY_DIGEST" \
qwen serve --profile hosted-harness --port 4170 --hostname 127.0.0.1 --no-webОставьте Harness на loopback. Запишите порт, который он сообщает; --port может увеличиться, если запрошенный порт уже занят.
Запуск управляющей плоскости Java
В другом терминале настройте тот же Harness, базу данных и существующий каталог рабочего пространства:
export SPRING_DATASOURCE_URL='jdbc:mysql://127.0.0.1:3306/qwen_managed_agent'
export SPRING_DATASOURCE_USERNAME='qwen'
export SPRING_DATASOURCE_PASSWORD='<private-password>'
export QWEN_MANAGED_AGENT_HARNESS_ENABLED='true'
export QWEN_MANAGED_AGENT_HARNESS_BASE_URL='http://127.0.0.1:4170'
export QWEN_MANAGED_AGENT_HARNESS_TOKEN='<private-random-token>'
export QWEN_MANAGED_AGENT_CAPABILITY_DIGEST='sha256:<64-hex-digest>'
export QWEN_MANAGED_AGENT_WORKSPACE_CWD='/srv/qwen-workspace'
bin/qwen-managed-agent-serverПараметры, которые нельзя задать через переменные окружения, такие как связка ключей учетных данных Runtime, должны находиться в config/application.yml. Начните с встроенного шаблона и обеспечьте конфиденциальность файла:
cp config/application.example.yml config/application.yml
chmod 600 config/application.ymlОба лаунчера загружают этот файл автоматически, если он существует. Лаунчер использует серверный JAR из этого архива. Spring Flyway применяет прямые миграции базы данных перед тем, как сервис станет готов. Дождитесь:
curl --fail http://127.0.0.1:8080/actuator/healthВключённый Harness активирует Managed Session Store. Базовый URL Store по умолчанию указывает на plaintext loopback-слушатель этого сервера. ID рабочего пространства по умолчанию совпадает с тем, что Runtime Broker выводит из QWEN_MANAGED_AGENT_WORKSPACE_CWD, поэтому идентичность сохраняется при включении пути инструмента ниже. Развертывание, уже установившее QWEN_MANAGED_AGENT_WORKSPACE_ID, должно сохранить его: непривязанные сессии определяют область Store по этому ID. Устанавливайте QWEN_MANAGED_AGENT_SESSION_STORE_BASE_URL только если Harness достигает этого сервера по другому адресу или если слушатель обслуживает TLS.
Эта базовая конфигурация поддерживает текстовые Hosted-сессии. Оставьте слушатель на loopback, если не настроен подписанный или аутентифицированный вход. Полная конфигурация аутентификации, API и возможностей содержится в docs/server-reference.md.
Начальная загрузка учетных данных
bin/qwen-managed-agent-bootstrap генерирует общий токен Harness и дайджест возможностей, токен брокера и ключ учетных данных Runtime. Он записывает config/harness.env, config/server.env и config/application.yml с режимом 0600, отказывается перезаписывать существующие файлы без --force и выводит только пути:
bin/qwen-managed-agent-bootstrapТокен и дайджест записываются только в harness.env: server.env ссылается на этот файл через QWEN_MANAGED_AGENT_HARNESS_CREDENTIALS_FILE, и управляющая плоскость читает оба значения из него. Она отказывается запускаться, когда файл задан вместе с QWEN_MANAGED_AGENT_HARNESS_TOKEN или QWEN_MANAGED_AGENT_CAPABILITY_DIGEST, поэтому ротация изменяет один файл. Сгенерированные harness.env и server.env подходят для загрузки через shell и также являются валидными EnvironmentFile systemd. Передайте --directory /etc/qwen-managed-agent для раскладки systemd, заполните SPRING_DATASOURCE_PASSWORD и скорректируйте владельца для учетной записи сервиса.
Предварительная проверка
Запустите встроенный лаунчер с --check перед первым запуском и после установки каждого нового артефакта. Он привязывает ту же конфигурацию (config/application.yml плюс окружение), не запускает слушатель и выводит одну строку на каждый вход:
bin/qwen-managed-agent-server --checkОна проверяет JDK, конфигурационный файл и его права, связку ключей учетных данных, проверку свойств запуска, комбинацию аутентификации/привязки, доступность Harness, файлы рабочего пространства и перекрёстные настройки Shell (включая монтирование, требование корня создания или SSH-узла), учетные данные и каталоги брокера, cwd рабочего пространства, свободные порты и подключение к MySQL, грант performance_schema и версию Flyway против manifest.json. WARN и SKIP не являются ошибкой; любой FAIL завершает работу с кодом 1. Проверки портов привязываются к настроенным адресам, поэтому сначала остановите сервис. Команда не проверяет дайджест возможностей Harness или регистрацию нативного хранилища рабочего пространства.
systemd
Дистрибутив включает шаблоны unit-файлов и окружения systemd/ для принятой однохостовой топологии. Unit управляющей плоскости использует KillMode=process, чтобы воркеры Runtime переживали перезапуск брокера; unit Harness использует KillMode=mixed, чтобы его процессы инструментов завершались вместе с ним. Следуйте systemd/README.md для их установки.
Включение принятого пути выполнения инструментов на локальном процессе
Выполнение инструментов требует существующей настройки Runtime и рабочего пространства с fail-closed. Как минимум, настройте:
export QWEN_MANAGED_AGENT_RUNTIME_BROKER_ENABLED='true'
export QWEN_MANAGED_AGENT_RUNTIME_BROKER_TOKEN='<private-random-token>'
export QWEN_MANAGED_AGENT_RUNTIME_CREDENTIAL_KEY_ID='reference-v1'
export QWEN_MANAGED_AGENT_RUNTIME_CREDENTIAL_KEY='<base64-encoded-32-byte-key>'
export QWEN_MANAGED_AGENT_RUNTIME_STATE_DIRECTORY='/var/lib/qwen-managed-agent/runtime'
export QWEN_MANAGED_AGENT_NODE_EXECUTABLE='/usr/bin/node'
export QWEN_MANAGED_AGENT_RUNTIME_WORKER_ENTRY='/opt/qwen-code/dist/cli.js'
export QWEN_MANAGED_AGENT_RUNTIME_VERIFIED_WORKSPACE_RECOVERY_ENABLED='true'Перед допуском работы с файлами, Shell или дочерними Git-ветками, выполните регистрацию нативного хранилища и проверку идентичности монтирования, описанную в разделе «Verified physical Workspace recovery» файла docs/server-reference.md. Незарегистрированное или неоднозначное монтирование должно оставаться недоступным. Публичное выполнение Shell остаётся отключённым по умолчанию. Жизненный цикл Shell v2 анонсируется по умолчанию; явный список жизненных циклов заменяет значение по умолчанию, а пустой список отключает его. Жизненный цикл MCP по-прежнему требует явного включения. Анонсирование возможностей не устанавливает квалификацию развертывания.
Обновление
- Загрузите и проверьте новый архив, прочитайте оба манифеста. Подтвердите новые требования Qwen Code/Harness, Java, протокола и базы данных до внесения изменений в работающее развертывание.
- Остановите новый входной трафик. Дождитесь завершения допущенной работы согласно существующей процедуре дренирования развертывания.
- Сделайте резервную копию MySQL,
QWEN_MANAGED_AGENT_RUNTIME_STATE_DIRECTORY, полной связки ключей учетных данных Runtime и точного старого дистрибутива. Не ротируйте ключ учетных данных во время обновления. - Остановите Java-сервис и Hosted Harness. Сохраните рабочее пространство и долговременное состояние Runtime. Поставляемый unit управляющей плоскости использует
KillMode=process, поэтомуsystemctl stopоставляет воркеры Runtime работающими; завершите их командойsystemctl kill --kill-whom=all -s TERM qwen-managed-agent-serverперед запуском новой версии. - Установите совместимую версию Qwen Code/Harness по манифесту и запустите её с существующим токеном и дайджестом возможностей.
- Запустите новый
bin/qwen-managed-agent-serverс теми же настройками базы данных и долговременными настройками. Flyway выполнит миграцию схемы вперед. - Дождитесь здорового ответа actuator, прочитайте существующую сессию и историю, затем выполните один новый ход без инструментов перед открытием входного трафика. Повторно квалифицируйте любую дополнительную возможность инструмента перед её включением.
Понижение версии базы данных не поддерживается. Если запуск или проверка не удались до возобновления трафика, исправьте конфигурацию и повторите попытку с тем же артефактом. Чтобы вернуться к версии, манифест которой имеет более старый диапазон схем, восстановите резервную копию базы данных и состояния Runtime до обновления вместе, прежде чем принимать любую новую запись; никогда не запускайте более старый сервер против мигрированной базы данных по предположению.
Ротация ключа учетных данных Runtime
Ротируйте ключ учетных данных отдельно от обновления дистрибутива. Сделайте резервную копию базы данных и текущих ключей, затем настройте новую активную пару и сохраните старую пару в previous-credential-keys:
qwen:
managed-agent:
runtime-broker:
credential-key-id: reference-v2
credential-key: <base64-encoded-32-byte-v2-key>
previous-credential-keys:
'[reference-v1]': <base64-encoded-32-byte-v1-key>Оберните каждый ключ карты в [ ... ]. Spring relaxed binder нормализует обычные ключи — ID вида legacy/v1, legacy:v1 или legacy v1 связывается как legacyv1 независимо от того, заключен ли он в кавычки в YAML — поэтому связка ключей никогда не совпадает с сохранённым ID ключа, и строки, записанные с этим ID, остаются нечитаемыми, даже если ключ настроен. Форма в скобках сохраняет точный ID.
Перезапустите единую управляющую плоскость Java, убедитесь, что существующие привязки загружаются, и проверьте, что новые строки привязок записывают reference-v2. Новые секреты используют только активный ключ; старые строки остаются зашифрованными под их записанным ID ключа. Сервер не перешифровывает старые строки при чтении, а удаление всё ещё используемого ключа делает эти строки нечитаемыми.
Выводите reference-v1 из использования только тогда, когда ни одна сохранённая строка не ссылается на него. ma_runtime_binding.credential_key_id и ma_runtime_binding.runtime_credential_key_id — единственные сохранённые ссылки; обе хранят байты UTF-8. Выбирайте их без CONVERT, чтобы дедупликация оставалась побайтово точной, как и выбор ключа: преобразованное значение несёт стандартную колляцию набора символов и объединило бы два ID, различающихся только регистром или акцентом, скрыв ключ, на который строки всё ещё ссылаются.
SELECT DISTINCT credential_key_id AS key_id
FROM ma_runtime_binding WHERE credential_key_id IS NOT NULL
UNION
SELECT DISTINCT runtime_credential_key_id AS key_id
FROM ma_runtime_binding WHERE runtime_credential_key_id IS NOT NULL;Результат перечисляет ID ключей, которые всё ещё требуются сохранёнными строками: ожидайте только активный ID (reference-v2). Пока присутствует reference-v1, этот ключ должен оставаться настроенным.
Связка ключей — это карта, и её нельзя передать через переменную окружения QWEN_MANAGED_AGENT_*: relaxed binding молча разрешает форму переменной окружения в пустую или неправильно ключеванную связку, без ошибки запуска. Настройте previous-credential-keys в config/application.yml. Дистрибутив поставляется с config/application.example.yml, и оба лаунчера экспортируют SPRING_CONFIG_ADDITIONAL_LOCATION=file:<distribution-root>/config/application.yml, когда этот файл существует, поэтому расположение больше не зависит от рабочего каталога процесса и ни одна опция не добавляется в позиционные аргументы команды. Если переменная уже установлена, лаунчеры оставляют её в силе. Развертывание, полагающееся только на переменные окружения, запускается с пустой связкой ключей, поэтому ротация credential-key-id без настройки предыдущего ключа делает строки, записанные с его использованием, нечитаемыми. Явный аргумент командной строки --spring.config.additional-location имеет приоритет над этим умолчанием переменной окружения; когда присутствуют оба, значение командной строки побеждает, и пакетный config/application.yml не загружается.
Точка входа восстановления оператором читает ту же активную пару и карту previous-credential-keys, что и сервер. Её лаунчер загружает config/application.yml тем же способом; если файл находится в другом месте, установите SPRING_CONFIG_ADDITIONAL_LOCATION=file:<absolute-path>/application.yml. Оставьте новый ключ активным, сохраняя каждый ключ, на который всё ещё ссылается привязка. Основные приложения обслуживания CSI/миграции, включая зонд CSI Hosted, по-прежнему читают одну пару ключей учетных данных; запускайте эти точки входа с тем ключом, которым зашифрована их целевая привязка, в качестве активной пары.
После успешной настройки связки ключей сервер и точка входа восстановления логируют разрешённый активный ID и настроенные ID один раз на экземпляр протектора. Эти ID являются несекретными идентификаторами, уже хранящимися рядом с шифротекстом; диагностика экранирует управляющие и не-ASCII символы в JSON, сохраняет пробелы и регистр и никогда не включает ключевой материал, шифротекст или токены. Сравните настроенные ID с точными ID, возвращёнными запросом на вывод из использования, перед использованием ротированного развертывания. Ошибка недоступного ключа называет запрошенный, активный и настроенные ID, поэтому молча нормализованное или ошибочно введённое сопоставление может быть найдено без раскрытия секретов. Эта диагностика не доказывает, что каждая сохранённая строка может быть расшифрована.
Восстановление оператором
bin/qwen-managed-agent-operator-recovery запускает отдельно упакованную точку входа восстановления. Она отключена, если не установлено специфичное для восстановления окружение, и не запускает HTTP-сервис или воркер. Следуйте docs/hosted-workspace-recovery.md; никогда не делайте предположений о физической остановке и не удаляйте долговременные строки для обхода страховочного предела.
Границы области
Данная сборка не сертифицирует множественные управляющие плоскости Java, кросс-хостовый перехват, публичный CSI, вывод из эксплуатации Kubernetes, публичный Shell, рекламу v2 или стабильную производственную поддержку. Эти возможности требуют отдельных доказательств в релизе.