Cairn を導入前に読む: 事実と意図のグラフで解く汎用探索エンジン
A AI general-purpose state-space search engine, validated first on autonomous penetration testing.
ひと目でわかる
- これは何?
- Cairn は origin と goal だけを与えて未知の状態空間を探索させるエンジンで、ペネトレーションテストを最初の検証領域に据えている。Blackboard 型の Fact / Intent / Hint という3つのプリミティブと、役割を持たない Worker の OODA ループが設計の中心にある。
- 誰に向いている?
- Cairn が向くのは、起点と成功条件は言語化できるが経路が未知で、しかも探索の途中経過を人間が読み返して Hint を差し込める種類の作業だ。ペネトレーションテストや CTF のように、Fact が積み上がる形で進む問題と相性がよい。
- 商用利用できる?
- 厳しい条件付きでできます。AGPL-3.0 はネットワーク型コピーレフトのライセンスで、改変版をホスティングサービスなどとしてネットワーク越しに利用させる場合、その利用者にソースコードを同じライセンスで提供する必要があります。
- 今もメンテナンスされている?
- されています。最後のコミットは 8 日前です。
- 何の言語で書かれている?
- 主に Python です(GitHub の言語統計による)。
回答はプロジェクトの GitHub データ(最終同期:2026年9月15日)と当サイトの分析に基づくもので、法的助言ではありません。
オープンソース詳細解説
Cairn が解こうとしている問題の形
README はペネトレーションテストを「近無限の状態空間における有向探索」と定義している。起点は既知 (対象 IP、対象システム)、ゴールは定義済み (シェル取得、フラグ奪取)、そして経路が未知である。Cairn の主張は、この形がペネトレーションテスト固有のものではないという点にある。脆弱性調査、数学的証明、CTF も、起点と成功条件が明確で経路が未知という同じ構造を持つ。
つまり Cairn は「ペネトレーションテスト用ツール」として設計されていない。役割もワークフローも定義しない、というのが README の言い方だ。与えられた origin から goal へ至る経路を未知の状態空間の中で探す、という一段抽象度の高い道具として提示されている。ペネトレーションテストは、その最初の検証済みドメインという位置づけになる。
読者にとって重要なのはここだ。特定の攻撃手順を自動化するツールを探しているなら、Cairn の抽象度は高すぎる。逆に、ドメインごとにエージェントの役割やワークフローを書き分けるのに疲れているなら、Cairn が削ろうとしているのはまさにその部分である。
Fact・Intent・Hint という3つのプリミティブ
Cairn のデータモデルは Blackboard アーキテクチャに基づく。共有盤面に書き込まれる要素は3種類しかない。Fact は確認済みの客観的な発見であり、盤面に書き込まれる。Intent はまだ実行されていない探索の方向宣言である。Hint は任意のタイミングで人間が注入する判断で、エージェントが次に盤面を読むときに吸収される。
グラフは origin から goal に向かって成長する。新しい Fact は飛び石であり、Intent は未知への一歩という比喩が README で使われている。重要なのは、Intent が「やることリスト」ではなく「探索方向の宣言」だという点だ。誰がそれを実行するかは書かれていない。実行主体はグラフの状態から実行時に決まる。
Hint の設計は地味だが効く。人間が途中で「この認証方式はもう試した」「このホストは対象外」と差し込むと、次に盤面を読んだエージェントがそれを取り込む。エージェントを止めてプロンプトを書き換えるのではなく、盤面に1行足すだけで介入できる。この非対称性が、長時間走らせる探索での人間の関与をかなり軽くする。
役割を持たない Worker と OODA ループ
Agent Worker は OODA ループを回す。盤面全体を Observe し、現在の状態に Orient し、次の Intent を Decide し、探索を Act して、結果を新しい Fact として書き戻す。README は Worker に固定の役割がないと明記している。タスクは事前定義された職務記述からではなく、グラフの現在の状態から実行時に生成される。
エージェント間の調整は共有盤面のみを通じて行われる (Stigmergy)。直接通信はなく、情報サイロもない、というのが README の説明だ。これは実装上の制約として読むべきで、エージェント同士が相談して方針を決めることはできない。すべての文脈は盤面に書かれていなければ存在しない。
タスクは3種類あり、いずれも同じ Worker が実行する。Bootstrap はプロジェクト開始時に問題を直接解こうとし、Fact と場合によっては Complete を出力する。Reason は盤面全体を読み、ゴールに到達したか、次に何を探索すべきかを判断して、Complete か新しい Intent か no-op を返す。Explore は Intent を1つ引き受けて実行し、Fact を1つ報告する。
この3種類しかないという点は、拡張性の制約でもある。ドメイン固有のタスク種別を足す仕組みは README には書かれていない。探索の質を上げたいなら、タスクを増やすのではなく Hint と初期 Fact の質で調整することになる。
Server と Dispatcher の責務分離
構成は3層に分かれている。Cairn Server はグラフの整合性のみを維持する。Cairn Dispatcher はグラフを読み、タスクをスケジュールし、Worker コンテナの起動と破棄を行い、プロトコルへの唯一の書き手となる。Agent Worker はプロンプトを受け取り構造化された出力を返すだけだ。
Dispatcher がプロトコルへの単一の書き手である点は、デバッグの入口として覚えておく価値がある。盤面の状態がおかしいとき、疑うべきは Worker ではなく Dispatcher の書き込み経路になる。Worker 側はコンテナ内で完結し、盤面に直接触れない。
プロジェクトごとに Worker Container が1つ割り当てられ、その中で複数の Agent Worker が並行して動く。プロジェクト A と B が別コンテナに分かれるため、探索対象の分離はコンテナ境界で行われる。逆に言えば、同一プロジェクト内の Worker は同じコンテナを共有するので、Worker 間のファイルシステム分離はない。
Worker はディスパッチャのホスト上で直接動かすこともできる。これが local mode で、Docker を必要としない。README はこのモードを別セクションとして用意している。
導入手順と設定ファイル
前提は macOS または Linux、Python 3.12 以上、そしてコンテナ実行を使う場合のみ Docker だ。local mode では Docker は不要と明記されている。
まず Worker コンテナイメージを取得する。Docker Compose 方式でも local mode でも共通で必要になる。
docker pull --platform=linux/amd64 ghcr.io/oritera/cairn-worker-container:latest
次にディスパッチャの設定を用意する。dispatch.example.yaml をコピーして、LLM のエンドポイントと API キーを埋める。
cp dispatch.example.yaml dispatch.yaml
Docker Compose 方式では、Cairn のビルドに使うベースイメージも先に取得する。
docker pull ghcr.io/astral-sh/uv:python3.13-trixie
docker compose up --build
これで cairn-server がポート 8000 で起動し、サーバのヘルスチェックが通った時点で cairn-dispatcher が起動する。Dispatcher はプロジェクトルートの dispatch.yaml をマウントして接続する、と README は説明している。
対応する Worker バックエンドは Claude Code、Codex、Pi の3つ。どのバックエンドを選ぶかは dispatch.yaml 側の設定になる。README の抜粋には各バックエンドの具体的なキー名までは含まれていないので、そこは dispatch.example.yaml を開いて確認する必要がある。
README が示す競技結果と、そこから言えないこと
README には Tencent Cloud Hackathon の AI Penetration Testing Challenge 第2回での結果が載っている。610チーム、1,345名、中国の主要大学とセキュリティ企業が参加した。Cairn 側の記載では、54問中54問を解き、AK (全問正解) を達成した唯一のチームであり、最終順位は3位だったとされている。
注目すべきは付随する注記のほうだ。システムは競技前にテストされたことがなく、フルパイプラインが初めてオンラインになったのは当日の午前4時だったという。訓練もチューニングもドメイン固有ツールもなく、MCP ツール、RAG、事前定義されたエージェント役割はいずれもゼロだと書かれている。
ここから言えるのは、この構成が少なくとも1つの競技環境で機能したという事実までだ。ベンチマーク数値や再現手順は README には示されていない。54/54 という数字がどのような問題セットで、どの程度の時間制約のもとで出たのかは、この資料からは分からない。汎用の状態空間探索エンジンとしての性能をこの結果から外挿するのは無理がある。競技はペネトレーションテストという1ドメインに閉じている。
向かない場面と、代わりの選択肢
Cairn が明確に向かないのは、探索の余地がほとんどない作業だ。手順が既知で、分岐が少なく、成功条件が単一のコマンド実行で判定できるなら、Fact と Intent のグラフを維持するコストは回収できない。Dispatcher がコンテナを起動し、Worker が盤面を読み、Reason タスクが no-op を返す、という一連の流れは、定型的な処理には重すぎる。
もうひとつの失敗モードは、Hint を差し込む人間がいない長時間運用だ。Cairn の設計は盤面への介入を前提にしている。探索が誤った方向に伸びたとき、それを止める仕組みは README には書かれていない。Intent を無効化する操作があるかどうかも、この資料からは確認できない。無人で回しっぱなしにする使い方は、設計の想定から外れている可能性がある。
代わりの選択肢として挙げられるのは、LangGraph のような明示的なグラフ定義型のエージェントフレームワークだ。アプローチの違いははっきりしている。LangGraph ではノードとエッジ、つまり状態遷移の構造を人間が事前に書く。Cairn は逆で、役割もワークフローも定義せず、Fact と Intent のグラフを実行時に成長させる。
この違いは、ドメイン知識をどこに置くかという違いでもある。LangGraph ではドメイン知識はグラフ定義に埋め込まれ、Cairn では Hint と初期 Fact として盤面に注入される。問題の構造が事前に分かっているなら LangGraph のほうが予測可能で、デバッグもしやすい。構造が分からないからこそ探索させたいなら、事前定義を要求しない Cairn の側に利がある。どちらが優れているという話ではなく、ドメイン知識を書けるかどうかの話だ。
ライセンスと保守の見取り図
ライセンスは AGPL-3.0。ネットワーク越しにサービスとして提供する場合、改変版のソース開示が及ぶ可能性がある点は、社内ツールとして組み込む前に確認しておくべき論点だ。ここでは法的助言はできないので、実際の適用範囲は自組織の法務に確認してほしい。
リリースは v0.1.0 が 2026-05-03、v0.2.0 が 2026-05-05、v0.2.1 が 2026-05-10 と、短期間にまとまっている。最新の push は 2026-09-07 で、アーカイブはされていない。バージョン番号が 0.x の段階であり、API や設定キーが今後変わる前提で読むのが妥当だ。dispatch.yaml のスキーマもその対象になりうる。
Worker コンテナイメージは ghcr.io から latest タグで取得する手順になっている。latest は固定タグではないので、再現性が必要な運用では digest を記録しておく必要がある。これは Cairn 固有の話ではなく、latest を引く手順一般に言えることだが、dispatch.yaml と Worker イメージの組み合わせが噛み合わなくなると、症状は盤面に Fact が増えないという形で現れる。原因が設定なのかイメージなのか切り分けにくいので、導入時に両方のバージョンを控えておく価値はある。
編集部の結論
Cairn が向くのは、起点と成功条件は言語化できるが経路が未知で、しかも探索の途中経過を人間が読み返して Hint を差し込める種類の作業だ。ペネトレーションテストや CTF のように、Fact が積み上がる形で進む問題と相性がよい。逆に、探索の余地がほとんどない定型処理や、途中の判断を人間が一切見ないで回したいバッチ処理には、Fact / Intent のグラフは単なるオーバーヘッドになる。導入前に確認すべきは、dispatch.yaml に書く LLM エンドポイントと API キーが Worker 側のコンテナから到達できるか、そして Worker コンテナ内で動かすバックエンド (Claude Code / Codex / Pi) の認証がそのコンテナに渡っているかだ。この2点が通らなければ、Bootstrap タスクは最初の Fact を書けないまま止まる。
コミュニティノート