Skip to main content
Glama

Kyno

マルチエージェントシステムのためのコヒーレンス制御プレーン:システムのミッションと原則(その憲法)のバージョン管理された単一の真実源を提供し、MCP経由で提供されるため、すべてのエージェントが今有効な指示に基づいて行動できます。たとえその指示が途中で変更されても。

なぜ

マルチエージェントシステムの目標が変わったとき、古い指示のコピーを保持しているエージェントは、その古い目標に向けた作業を生成し続けます。さらに悪いことに、古いコピーに対する品質チェックは、作業を逆に時代遅れの目標に向けて押し戻します。Kynoは古いコピーを排除します。指示は1つのバージョン管理されたストアに存在し、エージェントは各ステップの境界で現在のバージョンを取得し、変更があった瞬間にサブスクライバーに通知されます。

Related MCP server: Gigabrain

クイックスタート

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が行動したときの指示は何だったか」は常に回答可能です。

憲法の書き方

1行の原則はハンドルであり、ルールではありません。憲法には必要なだけの情報を、それ以上は与えないでください。以下の各項目はオプションです:

  • 宣言:ミッションが見出しとなる長文の文書。

  • 任意の原則の下にある説明:ハンドルの意味についての議論を解決する段落。

どちらも散文であり、コマンドラインフラグによる散文は苦痛です。そのため、憲法はファイルに記述されます:

# 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"

宣言はマークダウンであり、公開ページはそれをレンダリングします:見出し、リスト、強調、引用、リンク。内部の生のHTMLはエスケープされ、通過しません。また、javascript:リンクは拒否されます。ページは匿名の訪問者に提供されるため、あなた自身のテキストが実行可能なマークアップとして訪問者に届くことはありません。画像もレンダリングされません。これにより、ページは単一の自己完結型レスポンスとして保たれます。

他のすべての場所では、宣言はあなたが書いたマークダウンのままです。JSONエンドポイント、MCPツール、kyno exportはすべて、レンダリングされた文書ではなくソースを提供します。

--note、--by、--constitutionはファイルを上書きできます。これらは憲法自体ではなく、この編集に関するものだからです。フィールドフラグ(--mission、--declaration、--principle)は--fileと組み合わせることはできません。1つのフィールドに2つのソースがあることは誰も答えたくない質問だからです。ファイルが省略したフィールドは前のバージョンから引き継がれます。フィールドをクリアするには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ではベアラートークンが必要です。

すべての読み取りはデフォルトで可能な限り小さくなります。ハンドルであり、長いテキストではありません。エージェントは各ステップの前にプルするため、毎回文書全体を取得することになるからです。実際に必要な場合にのみ、より多くの情報を要求します:2つのプルでdetail="full"、get_principlesでdetail="full"、または対象を絞った読み取りのいずれか。すべての応答には、それが取得されたバージョンが含まれているため、それらを混在させるクライアントは、それらがいつ乖離したかを認識できます。

クライアントはkyno://constitution/currentリソースにサブスクライブし、バージョンが上がるたびに標準のMCP resources/updated通知を受け取ることもできます。これはコンパクトな形式を提供します。リソースはパラメータを取らず、文書全体は1つのツール呼び出しで取得できます。

複数の憲法

1つのKynoは複数の憲法を並行して保持できます。たとえば、製品ラインごとや法域ごとに1つずつです。すべての操作はオプションのconstitution名を受け取り(MCPおよびCLIで--constitution eu)、デフォルトは"default"です。そのため、単一憲法のセットアップではそれを指定する必要はありません。各名前には独自のバージョンシーケンスがあります。euをv2にバンプしても、defaultはそのままのバージョンです。まだ書き込んだことのない名前は、手つかずのストアと同じバージョン0の空の状態として読み取られます。サブスクライブ可能なリソースはデフォルトの憲法のものです。別の憲法を使用するエージェントは、get_changes_sinceで名前を指定してプルします。

アダプター(CrewAI、LangGraph)

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

アダプターは、クルーまたはグラフを1つの名前付き憲法にバインドし、次のステップごとに現在有効なバージョンに再バインドします:

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))でバインドすると、「指示なし、作業なし」の姿勢になります。ステップは進行せずに例外を発生させます。

  • プッシュ消費 — BackgroundSubscriberはMCP resources/updated通知を名前による再プルに変換します。すでに実行中のステップが中断されることはありません。次のステップは新しい指示をバインドします。

  • リアライメントゲート — モデルフリーで、完了したタスクごとにレビューされます(CrewAIのタスク完了コールバック)。LLM呼び出しごとではなく、実際の判定者がアタッチされるとより安価でノイズが少なく、完了したタスクはすでにレビュー可能な単位です。これは、提供するVerdictSourceを呼び出し、DRIFTEDの場合に(CrewAIではtask_callbackから)例外を発生させるか、決定のために(LangGraphでは)interrupt()します。判定者が利用できない場合、作業はuncheckedとマークされて続行され、イベントはテレメトリとして出力されます。デフォルトでは、チェックをスキップして中断のない実行を優先します。代わりに停止すべきゲートにはGatePolicy(fail_closed=True)を設定します。

  • アダプターは読み取り専用 — プルとサブスクライブを行います。set_directionはKynoに対するオペレーター/CLIアクションのままであり、アダプターがクルーやグラフに代わって呼び出すことはありません。

LangGraphでは、グラフの状態スキーマにKynoStateを継承させます。LangGraphはスキーマが宣言するキーのみを運ぶため、これがないとノードがプルした指示が、それに対して判定するゲートノードに到達しません:

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


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

ストレージ

標準でSQLite。本番環境ではKYNO_DATABASE_URL経由でPostgreSQL。ストレージはプラグイン可能です。SqlConstitutionStoreに独自のSQLAlchemy Engineを渡して既存のデータベース内に配置するか、小さなストアプロトコルを実装して完全に独自の永続化を持ち込むことができます。同時書き込みは安全です。バージョンは一意のインデックスとリトライによってシリアル化され、失われたり重複したりすることはありません。

空のストアでも読み取りは決して失敗しません。指示が設定される前でも、コンシューマーはバージョン0の空の状態を取得するため、Kynoを採用する前に統合してもコストはかかりません。

憲法の公開

自分が従うと主張する原則を人々に見せたい場合、Kynoはそのページ自体を提供できます。そのため、公開されたページとエージェントが従うページは同じ記録であり、乖離する2つのコピーではありません。

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

kyno serve --transport httpが実行されている間、公開された憲法は誰でも以下のURLで読むことができます:

  • GET /constitutions/{name} — 自己完結型のHTMLページ(スクリプトなし、外部アセットなし、ライトモードとダークモード)。宣言はその本文であり、マークダウンからレンダリングされ、説明のある原則はその段落を表示します。

  • GET /constitutions/{name}.json — 同じ内容を機械可読形式で。

  • GET /constitutions/ および GET /constitutions.json — 公開したもののインデックス。

知っておくべき2つのこと:

  • 公開する名前はスラグでなければなりません — 小文字、数字、単一のハイフン(acme、acme-eu)。これはURLであり、エージェントが使用する名前でもあるため、Kynoは静かに書き換えるのではなく、それ以外のものを拒否します。公開しない名前には制限はありません。

  • 公開するまでは何も公開されません。公開は名前ごとに行われます。1つのKynoは内部の憲法と公開用の憲法を並行して保持できます。2つ目を公開しても、1つ目には何の影響もありません。

  • 公開では現在の指示のみが表示されます — ミッション、宣言、原則、バージョン、最終変更日。バージョン履歴は、--with-historyを追加しない限り非公開のままです。変更ノートはオペレーター向けに書かれており、なぜ方針を変更したかを説明するからです。公開された履歴は最新の100バージョンを表示します。これがページの契約です。完全な履歴は、MCPおよびkyno exportを介した認証済みの呼び出し元に対して引き続き利用可能です。

公開していないものは、存在しない名前と同様に404を返します。公開側には、どちらであるかを明らかにするものは何もありません。

カスタマイズ

色を変更するには、6つの環境変数。必要なものを設定し、残りはデフォルトのままにします:

変数

デフォルト

色を変更する対象

KYNO_PAGE_ACCENT

#6d6d66

リンクの下線、原則番号

KYNO_PAGE_BACKGROUND

#fbfbf9

ページ

KYNO_PAGE_TEXT

#1b1b19

本文

KYNO_PAGE_MUTED

#6d6d66

ラベル、日付、バージョンスタンプ

KYNO_PAGE_RULE

#e4e3de

項目間の細線

KYNO_PAGE_FONT

システムサンズ

ページのfont-family

設定しない場合、組み込みの外観が使用され、自動ダークモードが適用されます。いずれかの色を設定すると、Kynoはダークモード用のパレットの切り替えを停止します。選択した色を反転すると、承認していないページになるため、その時点からパレットはあなたのものになります。フォントのみを設定した場合、ダークモードの切り替えは維持されます。

適切なカスタマイズ

Kynoが提供するページはテンプレートファイルであり、実際のものを提供します:

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

編集してから、Kynoにコピーを指定します。次の2行が出力されます:

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

プレースホルダ

説明

$stylesheet

<style>ブロック全体:色変数+Kynoのページスタイル

$name

憲章の名前

$mission

ミッション(ミッションがない場合は名前)

$declaration

マークダウンからレンダリングされた宣言。<div>で囲まれている。ない場合は空

$principles

原則セクション(見出しとリスト)。ない場合は空

$version

バージョン番号(例:3)

$updated

最終更新日(例:2026-08-13)

$history

バージョン履歴ブロック。履歴を公開しない限り空

index.html

プレースホルダ

説明

$stylesheet

上記と同じ

$items

公開された憲章のリスト、または「まだ何も公開されていません」という行

$count

公開されている数

各ブロックプレースホルダはそれ自身のラッパーを持ち、何もないときは完全に消えるため、テンプレートは「宣言がない場合はどうするか」を問う必要がありません。これは意図的です。これらはプレースホルダであり、テンプレート言語ではありません — ループも条件も式もなく、デフォルトも同じ制限に従うため、あなたがエクスポートしたのと同じファイルなのです。

これがもたらす安全性:Kynoはあなたのミッション、原則、変更ノートをファイルに届く前にエスケープし、宣言のマークダウンをHTML無効でレンダリングするため、誰かが憲章に入力したテキストが実行可能なマークアップになることはありません。スペルミスのあるプレースホルダはページを壊すことなくそのまま残され、リクエストが来たときにファイルが見つからないか読み取れない場合、Kynoは自身のページを提供して警告をログに記録します — 悪いテンプレートがあなたの公開ページをダウンさせることは決してありません。

認証

  • stdio: オープン。サーバーを起動できるプロセスは、その下にあるデータベースファイルをすでに所有しています。そこにトークンがあっても、儀式に過ぎず、境界にはなりません。

  • HTTP: 共有ベアラートークン(KYNO_TOKEN)がMCPエンドポイント(/mcp)へのすべてのリクエストをゲートします。サーバーは、明示的にオプトインしない限り(KYNO_ALLOW_INSECURE_HTTP、ローカル実験のみ — 警告が出ます)、HTTPでトークンなしでの起動を拒否します。また、設定されていても空のKYNO_TOKENは、無言で認証なしになるのではなく、設定エラーとして扱われます。コードでアプリを組み込む開発者も同様にオプトインします:build_http_app(..., allow_insecure=True)。上記の公開された憲章ページは、意図的にそのゲートの外側にあります — それらはあなたが公開することを選んだ表面です。

書き込みトークンは方向制御です:それを保持する者は、このKynoにバインドされたすべてのエージェントの指示を操作できます。システムプロンプトの資格情報として扱ってください — /mcpをTLS経由で提供し、トークンをログやチェックポイントから遠ざけてください(Kyno自身のreprは決してそれを出力しません)。関連して、注入されたブロックの[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リクエストボディは5MBに制限されています。

  • 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を参照してください。

Maintenance

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP+HTTP control plane for routing work to multiple coding-agent CLIs through a normalized contract, enabling multi-agent coding pipelines with planning, implementation, review, and revision.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A durable MCP control plane for starting, observing, steering, continuing, cancelling, and handing off long-running coding agents, with bounded MCP calls and persistent worktrees.
    5 npm
    MIT