Skip to main content
Glama

Kyno

Плоскость согласованности для мультиагентных систем: один версионированный источник истины для миссии и принципов вашей системы (ее конституции), предоставляемый через MCP, чтобы каждый агент мог действовать в соответствии с направлением, действующим прямо сейчас — даже если это направление меняется на лету.

Зачем

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

Быстрый старт

pip install .             # from a clone; CLI: kyno
kyno init-db
kyno set --mission "Ship a lending product people trust" \
         --note "initial constitution"
kyno current
kyno serve --transport stdio    # or --transport http

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

Написание конституции

Принцип в одну строку — это идентификатор, а не правило. Дайте конституции столько, сколько нужно, и не больше — каждый из этих пунктов необязателен:

  • декларация, полный документ, заголовком которого является миссия;

  • описание под любым принципом, абзац, разрешающий спор о значении идентификатора.

И то, и другое — проза, а проза через флаги командной строки — мучение, поэтому конституция пишется в файле:

# constitution.yaml
mission: Ship a lending product people trust with their worst month
declaration: |
  ## What we are for

  Lending is a promise about somebody's worst month. We would rather lose
  the deal than make a promise we cannot keep.

  ## What that costs us

  - We say no early, in plain words, rather than late in a maze.
  - We publish the number before the story that softens it.
principles:
  - Say the hard number first
  - title: Refuse quietly
    description: |
      A refusal is a sentence, not a maze. If we cannot lend, say so on the
      first screen and say why.
note: the constitution as written
by: camilo
kyno set --file constitution.yaml
kyno set --file constitution.yaml --constitution eu --note "the EU edit"

Декларация — это markdown, и опубликованная страница отображает его: заголовки, списки, выделение, цитаты, ссылки. Необработанный HTML внутри экранируется, а не пропускается, а ссылки javascript: отклоняются — страница предоставляется анонимным посетителям, поэтому ваш собственный текст никогда не может достичь их в виде исполняемой разметки. Изображения также не отображаются, что сохраняет страницу как единый самодостаточный ответ.

Во всех остальных местах декларация остается точно в том виде, в котором вы ее написали: конечная точка JSON, инструменты MCP и kyno export предоставляют исходный код, а не отрисованный документ.

--note, --by и --constitution могут переопределять файл, потому что они относятся к этому редактированию, а не к конституции; флаги полей (--mission, --declaration, --principle) не могут быть объединены с --file, потому что два источника для одного поля — это вопрос, на который никто не должен отвечать. Поля, пропущенные в файле, переносятся из предыдущей версии — очистка обозначается как declaration: "".

Флаги все еще доступны для быстрого редактирования:

kyno set --mission "Ship a lending product people trust" --note "sharpen the mission"

Контракт

Через MCP или Python:

  • get_constitution — направление, действующее сейчас (миссия, принципы, версия).

  • get_changes_since(known_version) — запрос, который агент делает перед шагом: текущее направление плюс примечания об изменениях с момента последней увиденной версии. Пропущенное уведомление безвредно — следующий запрос самодостаточен.

  • get_mission, get_declaration, get_principles, get_principle(title) — по одной части документа, когда компактное чтение их опустило.

  • set_direction(mission?, declaration?, principles?, change_note) — добавить следующую версию. Пропущенные поля переносятся; "" очищает поле. По HTTP это требует токена-носителя.

Каждое чтение по умолчанию настолько мало, насколько это возможно — идентификаторы, а не длинный текст — потому что агент запрашивает перед каждым шагом и иначе каждый раз получал бы весь документ. Запрашивайте больше, когда это действительно нужно: detail="full" для двух запросов, detail="full" для get_principles или одно из целевых чтений. Каждый ответ содержит версию, из которой он получен, поэтому клиент, смешивающий их, может определить, когда они разошлись.

Клиенты также могут подписаться на ресурс kyno://constitution/current и получать стандартное уведомление MCP resources/updated при каждом увеличении версии. Он предоставляет компактную форму: ресурс не принимает параметров, а весь документ находится на расстоянии одного вызова инструмента.

Несколько конституций

Один Kyno может содержать несколько конституций одновременно — например, по одной на линейку продуктов или на юрисдикцию. Каждая операция принимает необязательное имя constitution, через MCP и в CLI (--constitution eu), и по умолчанию использует "default", поэтому одноконституционная установка никогда не должна его упоминать. Каждое имя имеет свою собственную последовательность версий: увеличение eu до v2 оставляет default на той версии, на которой он был. Имя, в которое вы никогда не записывали, читается как то же состояние версии 0, что и нетронутое хранилище. Подписываемый ресурс — это конституция по умолчанию; агенты, работающие с другой, запрашивают ее по имени с помощью get_changes_since.

Адаптеры (CrewAI, LangGraph)

pip install "kyno[crewai]"      # or: pip install "kyno[langgraph]"

Адаптер привязывает группу или граф к одному именованному конституции и перепривязывает каждый следующий шаг к версии, действующей прямо сейчас:

from kyno.adapters.core import (
    DirectionBinder,
    KynoBinding,
    McpDirectionSource,
    SessionRunner,
    http_session,
)
from kyno.adapters.crewai import CrewAiKyno

binding = KynoBinding.from_env(constitution="eu")  # KYNO_URL, KYNO_TOKEN
runner = SessionRunner(http_session(binding))
runner.start()

binder = DirectionBinder(McpDirectionSource(runner))
adapter = CrewAiKyno(binder, constitution=binding.constitution)
adapter.register()  # injects the current direction before each model call
crew = Crew(..., task_callback=adapter.task_callback)  # gates each finished task

Встраиваете Kyno в тот же процесс? Замените источник: DirectionBinder(LocalDirectionSource(control_plane)).

  • Запрос перед каждым шагом — текущая миссия и заголовки принципов внедряются в следующий вызов модели, помеченные конституцией и версией, из которой они получены. Этот блок присутствует в каждом вызове модели, поэтому по умолчанию он остается небольшим. Привяжите с помощью DirectionBinder(source, context="full"), когда вы предпочтете потратить токены: декларация и описания принципов также внедряются, и запрос получает их, а не только идентификаторы. Когда Kyno недоступен — или отвечает чем-то нечитаемым — запрос деградирует: шаг выполняется с последним направлением, которое хранит связка, а устаревание передается как телеметрия. Привяжите с помощью DirectionBinder(source, policy=PullPolicy(fail_closed=True)), когда ваша позиция — "нет направления, нет работы": шаг вызывает исключение вместо продолжения.

  • Push-потреблениеBackgroundSubscriber превращает уведомление MCP resources/updated в повторный запрос по имени. Уже выполняющийся шаг никогда не прерывается; следующий привязывает новое направление.

  • Шлюз перестройки — без модели и проверяется для каждой завершенной задачи (обратный вызов завершения задачи CrewAI), а не после каждого вызова LLM — дешевле и менее шумно, когда подключен реальный судья, и завершенная задача уже является проверяемой единицей. Он вызывает предоставленный вами VerdictSource и вызывает исключение (CrewAI, из task_callback) или interrupt() для принятия решения (LangGraph) при DRIFTED. При отсутствии судьи работа продолжается, помеченная как unchecked, и событие передается как телеметрия: по умолчанию пропущенная проверка обменивается на бесперебойный запуск. Установите GatePolicy(fail_closed=True) на шлюзе, который должен остановиться.

  • Адаптеры доступны только для чтения — они запрашивают и подписываются; set_direction остается действием оператора/CLI против Kyno, и никогда не вызывается адаптером от имени группы или графа.

В LangGraph унаследуйте KynoState в схеме состояния вашего графа. LangGraph несет только ключи, объявленные схемой, поэтому без него направление, полученное узлом, никогда не достигает узла-шлюза, который оценивает его:

from kyno.adapters.langgraph import KynoState, direction_node, gate_node


class State(KynoState, total=False):
    output: str

Хранилище

SQLite из коробки; PostgreSQL для продакшена через KYNO_DATABASE_URL. Хранилище подключаемо: передайте SqlConstitutionStore свой собственный Engine SQLAlchemy для работы внутри существующей базы данных или реализуйте небольшой протокол хранилища, чтобы полностью использовать собственное постоянство. Конкурентные писатели безопасны — версии сериализуются уникальным индексом и повтором, никогда не теряются и не дублируются.

Чтение никогда не завершается ошибкой в пустом хранилище: до установки любого направления потребители получают пустое состояние версии 0, поэтому интеграция Kyno до его внедрения ничего не стоит.

Публикация вашей конституции

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

kyno publish                                  # the default constitution
kyno publish --constitution eu --with-history
kyno unpublish --constitution eu

Пока kyno serve --transport http работает, опубликованная конституция доступна для чтения любому по адресу:

  • GET /constitutions/{name} — самодостаточная HTML-страница (без скриптов, без внешних ресурсов, светлая и темная). Декларация является ее телом, отрисованным из markdown, а описанный принцип несет свой абзац.

  • GET /constitutions/{name}.json — то же содержимое, машиночитаемое.

  • GET /constitutions/ и GET /constitutions.json — индекс того, что вы опубликовали.

Две вещи, которые стоит знать:

  • Опубликованное имя должно быть слагом — строчные буквы, цифры и одиночные дефисы (acme, acme-eu). Это одновременно URL и имя, которое используют ваши агенты, поэтому Kyno отказывается от всего остального, а не молча переписывает. Имена, которые вы никогда не публикуете, не ограничены.

  • Ничто не является публичным, пока вы его не опубликуете, и публикация осуществляется по имени. Один Kyno может содержать вашу внутреннюю конституцию и вашу публичную конституцию бок о бок; публикация второй никак не влияет на первую.

  • Публикация показывает только текущее направление — миссию, декларацию, принципы, версию, дату последнего изменения. История версий остается приватной, если вы не добавите --with-history, потому что примечания об изменениях написаны для ваших операторов и обычно объясняют, почему вы изменили курс. Опубликованная история показывает 100 последних версий — это контракт страницы; полная история остается доступной аутентифицированным вызывающим через MCP и kyno export.

Все, что вы не опубликовали, отвечает 404, точно так же, как имя, которое не существует. Ничто на публичной стороне не раскрывает, какой из двух вариантов это был.

Настройка под себя

Для изменения цвета — шесть переменных окружения. Установите те, которые вас интересуют, и оставьте остальные:

Переменная

По умолчанию

Что окрашивает

KYNO_PAGE_ACCENT

#6d6d66

подчеркивания ссылок, номера принципов

KYNO_PAGE_BACKGROUND

#fbfbf9

страница

KYNO_PAGE_TEXT

#1b1b19

основной текст

KYNO_PAGE_MUTED

#6d6d66

метки, даты, отметка версии

KYNO_PAGE_RULE

#e4e3de

тонкие линии между элементами

KYNO_PAGE_FONT

системный sans

font-family для страницы

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

Правильная настройка под себя

Страницы, которые предоставляет Kyno, являются файлами шаблонов, и он передаст вам настоящие:

kyno page export ./pages          # constitution.html, index.html, page.css

Отредактируйте их, затем укажите Kyno на ваши копии — он выведет эти две строки для вас:

export KYNO_CONSTITUTION_TEMPLATE=/srv/pages/constitution.html
export KYNO_INDEX_TEMPLATE=/srv/pages/index.html      # optional

Это весь рабочий процесс. То, что вы экспортировали, это то, что Kyno уже отображал — те же файлы, заполненные тем же способом — поэтому вы редактируете рабочую страницу, а не восстанавливаете ее, и все, что вы оставите без изменений, продолжит работать.

kyno page export отказывается перезаписывать файлы, которые уже существуют, и ничего не записывает, когда должен был бы.

Экспортированный page.css — это отправная точка для ваших собственных стилей: свяжите его, встройте или выбросьте. Заполнитель $stylesheet ниже всегда предоставляет стили, встроенные в Kyno, а не вашу их копию — поэтому шаблон, сохраняющий $stylesheet, остается на стандартном виде (и следует указанным выше цветовым переменным), а тот, который его удаляет, полностью ваш.

Заполнители

constitution.html

Placeholder

Что это

$stylesheet

весь блок <style>: переменные цветов + стили страниц Kyno

$name

название конституции

$mission

миссия, или название, если миссии нет

$declaration

декларация, отрендеренная из markdown, обёрнутая в свой <div> — пустая, если её нет

$principles

раздел принципов, заголовок и список — пустой, если принципов нет

$version

номер версии, например 3

$updated

дата последнего изменения, например 2026-08-13

$history

блок истории версий — пустой, если вы не публиковали историю

index.html

Placeholder

Что это

$stylesheet

как выше

$items

список опубликованных конституций или строка "ничего не опубликовано"

$count

сколько опубликовано

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

Свойство безопасности, которое это даёт: Kyno экранирует вашу миссию, принципы и заметки об изменениях до того, как они попадут в ваш файл, и рендерит markdown декларации с отключённым HTML, так что никакой шаблон не может превратить текст, введённый кем-то в конституцию, в разметку, которая выполняется. Плейсхолдер, который вы написали с ошибкой, остаётся нетронутым, а не ломает страницу, и если ваш файл отсутствует или не читается при поступлении запроса, Kyno отдаёт свою собственную страницу и записывает предупреждение — плохой шаблон никогда не обрушит вашу публичную страницу.

Аутентификация

  • stdio: открыто. Процесс, который может запустить сервер, уже владеет файлом базы данных под ним; токен там был бы церемонией, а не границей.

  • HTTP: общий bearer-токен (KYNO_TOKEN) защищает каждый запрос к конечной точке MCP (/mcp). Сервер отказывается запускаться без токена по HTTP, если вы явно не согласитесь (KYNO_ALLOW_INSECURE_HTTP, только для локальных экспериментов — он предупреждает), а KYNO_TOKEN, который установлен, но пуст, считается ошибкой конфигурации, а не отсутствием аутентификации. Разработчики, встраивающие приложение в код, соглашаются так же: build_http_app(..., allow_insecure=True). Опубликованные страницы конституций выше находятся за пределами этого шлюза намеренно — это та поверхность, которую вы решили открыть.

Токен на запись — это контроль направления: кто им владеет, тот управляет инструкциями каждого агента, привязанного к этому Kyno. Относитесь к нему как к учётным данным системного промпта — обслуживайте /mcp через TLS и не допускайте попадания токена в логи и контрольные точки (собственные repr Kyno никогда его не печатают). В связи с этим заголовок [kyno:direction …] во внедрённом блоке — это бухгалтерия транскрипта, а не граница подлинности: текст, поступающий от инструментов или пользователей, может его имитировать, поэтому ничто не должно доверять блоку только из-за его вида. Kyno отказывается принимать текст конституции, содержащий маркер, а адаптеры всегда заменяют только тот блок, который они сами внедрили.

Развёртывание

  • Используйте абсолютный KYNO_DATABASE_URL в продакшене. Значение по умолчанию (sqlite:///kyno.sqlite3) — это удобство для разработки, которое разрешается относительно рабочей директории, в которой запускается процесс.

  • Запускайте размещённый Kyno за обратным прокси, который применяет ограничение скорости; публичные страницы отвечают на анонимный трафик, и ограничение скорости — это задача прокси, а не Kyno.

  • Размеры полей являются частью контракта API: миссия ≤ 4 000 символов, декларация ≤ 200 000, заметка об изменении ≤ 2 000, до 100 принципов с заголовками ≤ 300 и описаниями ≤ 4 000, названия конституций ≤ 200. set_direction отклоняет всё, что больше, а тела запросов /mcp ограничены 5 МБ.

  • Установленный через pip Kyno содержит собственные скрипты миграции: kyno init-db создаёт свежую схему с отметкой текущей головы, а kyno upgrade-db обновляет существующую базу данных после обновления.

Тестирование

python -m pytest -q                      # SQLite, no network
KYNO_TEST_POSTGRES_URL=postgresql+psycopg://… python -m pytest -q   # + Postgres

Связанный проект: Canon проверяет, действительно ли результаты вашей системы согласуются с конституцией, которую обслуживает Kyno.

См. CONTRIBUTING.md для стиля и ожиданий по тестированию.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cizambra/kyno'

If you have feedback or need assistance with the MCP directory API, please join our Discord server