※この記事は Zenn(https://zenn.dev/kimshoshi/articles/obsidian-multi-agent-orchestration)からの転載です。
はじめに:「AIに聞く」と「AIを動かす」は別物
ChatGPTやClaudeに質問して答えをもらう。それは「チャット」であり、AIを入力→出力の関数として使っている状態だ。
しかし実際の業務には、次のような課題がある。
- 会話が終わると文脈が消える(ステートレス)
- 一つのモデルにすべてを任せると、得意・不得意の壁にぶつかる
- 「AIが出した答え」を次のAIに渡す橋渡しを、人間が手作業でやっている
- 自動化しようとすると「どこに何が書いてあるか」の管理が崩壊する
これらを解決するのがマルチエージェントオーケストレーションだ。本稿では、ObsidianというMarkdownベースのノートアプリをSSoT(Single Source of Truth)として使い、複数のAIを役割分担させる設計を技術的に解説する。
全体アーキテクチャ
┌─────────────────────────────────────────┐
│ Obsidian Vault(SSoT) │
│ ┌──────────────────────────────────┐ │
│ │ YAML frontmatter(構造化メタデータ)│ │
│ │ Markdownボディ(非構造化テキスト) │ │
│ └──────────────────────────────────┘ │
│ ↑ 読み書き ↓ │
│ ┌───────┬────────┬────────┬─────────┐ │
│ │Claude │ Codex │ Gemini │launchd │ │
│ │Sonnet │ CLI │ CLI │(スケジュ)│ │
│ └───────┴────────┴────────┴─────────┘ │
└─────────────────────────────────────────┘
↓ API呼び出し
┌─────────────────────┐
│ X API / WP REST API │
└─────────────────────┘
ポイント:各AIは直接通信しない。全員がObsidian vaultを経由してやり取りする。これがファイルベースIPCの核心だ。
技術コンセプト1:マルチエージェントオーケストレーション
定義
複数のLLMエージェントが、それぞれ異なる役割・権限・コンテキストを持ち、協調して一つのワークフローを実行する設計パターン。
なぜ単一モデルで全部やらないのか
| 懸念点 | 単一モデル | マルチエージェント |
|---|---|---|
| コンテキストウィンドウ | 長大な会話で枯渇する | タスク単位で分割するため各エージェントのコンテキストが小さい |
| コスト | 重いモデルをすべてのタスクに使う | タスク重要度に応じてモデルを使い分け(Opus/Sonnet/Haiku) |
| 専門性 | 汎用だが深さに限界がある | 役割特化でプロンプトを最適化できる |
| 並列処理 | 逐次実行しかできない | 依存関係がないタスクは並列で走らせられる |
本構成のエージェント分担
Claude Opus ── 企画・判断・最終承認(司令塔)
Claude Sonnet── 文章生成・整形・SNS文(実行層)
Codex CLI ── コード実装・ファイル一括処理(実装層)
Gemini CLI ── PDF読取・長文資料・ファクトチェック(読取層)
launchd ── スケジューリング・イベントトリガー(インフラ層)
技術コンセプト2:ファイルベースIPC(Inter-Process Communication)
IPCとは
異なるプロセス間でデータを受け渡す仕組みの総称。通常はソケット通信やメッセージキュー(RabbitMQなど)が使われるが、本構成ではMarkdownファイルがメッセージキューの役割を担う。
なぜMarkdownファイルなのか
- 人間とAIの両方が読み書きできる
- バージョン管理(iCloud同期)が標準で使える
- Obsidianがリアルタイムにレンダリングするため、人間がモニタリングしやすい
- APIが不要(ファイルI/Oだけで完結する)
実装例:AIタスクファイルの構造
---
作成日: 2026-06-27
依頼先: Sonnet
種別: 実装
状態: 未着手 ← 有限状態機械のstate
次のアクション: Sonnetが記事ドラフトを作成する
---
## 依頼内容
...
## 受入条件
...
## 作業ログ
<!-- Sonnetがここに追記する -->
状態 フィールドが有限状態機械(FSM: Finite State Machine) のstateとして機能する。
未着手 → 進行中 → 確認待ち → 完了
↓
保留 / 却下
各エージェントは自分が担当するstateのファイルだけを処理する。これによりレースコンディション(競合書き込み)を防ぎながら疎結合を保つことができる。
技術コンセプト3:SSoT(Single Source of Truth)
問題:情報の散乱
AIを複数使い始めると、「どのAIが最新の指示を持っているか」が分からなくなる。ChatGPTの会話、Claudeの会話、Notionのページ、Slackのメッセージ──情報が分散し、矛盾が生じる。
解決:vaultを唯一の権威にする
ルールはObsidianにある → AIはvaultを読んで動く → 更新もvaultに書く
具体的には:
-
運用ルール:
AI会話ログ/Claude/memory/以下のmdファイル -
タスク管理:
🏠1.home/AIタスク/以下のmdファイル -
制作物:
📋2.実務/以下の各フォルダ
どのAIも、会話を始める前にvaultの関連ファイルを読むという規約を守ることで、全エージェントが同一の文脈を持つ。
技術コンセプト4:イベント駆動自動化(launchd)
構成
macOSのlaunchdをスケジューラーとして使い、定期実行でAIワークフローをトリガーする。
<!-- ~/Library/LaunchAgents/com.businesshub.x-post.plist -->
<key>StartInterval</key>
<integer>900</integer> <!-- 15分ごとに実行 -->
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/node</string>
<string>/path/to/x_post.js</string>
<string>--mode</string>
<string>post</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>X_MAX_CHARS</key>
<string>2000</string>
</dict>
x_post.jsの処理フロー
1. SNS運営/X投稿/ をreaddirSync()でスキャン
2. /^\d{4}-\d{2}-\d{2}_.+\.md$/ にマッチするファイルを抽出
3. frontmatterをパースして 状態: 承認済 のみ対象に絞る
4. 予約時刻 があれば ISO 8601 でパース → 現在時刻と比較
5. X API(OAuth 2.0 PKCE)で投稿
6. 投稿IDをfrontmatterに書き戻し → 状態: 投稿済(X)に更新
ポイント:AIはファイルを書くだけでよい。「いつ実行するか」の判断をlaunchdに委ねることで、AIのコンテキストにスケジューリングロジックを持ち込まなくて済む(関心の分離)。
技術コンセプト5:YAMLフロントマターを構造化プロトコルとして使う
Markdownは本来、人間が読む文書フォーマットだ。しかしYAML frontmatterを使うことで、機械可読なメタデータ層をMarkdownに重ねられる。
---
状態: 承認済 # FSMのstate
依頼先: Sonnet # ルーティングキー
種別: ブログドラフト # タスクタイプ
予約時刻: 2026-06-28T07:05:00+09:00 # ISO 8601
要User対応: true # 人間介入フラグ
---
これはRESTのHTTPヘッダー、メッセージキューのメタデータ、gRPCのメッセージ定義と同じ役割を果たしている。Markdownボディがペイロード、frontmatterがエンベロープだ。
「チャットするだけ」との本質的な違い
| 観点 | チャット | 本構成 |
|---|---|---|
| 状態管理 | ステートレス(会話が終われば消える) | ステートフル(ファイルに永続化) |
| スケーラビリティ | 人間がボトルネック | launchdが自律実行するため人間なしで回る |
| モデル選択 | 一つのモデルに依存 | タスク特性に応じてモデルを動的選択 |
| エラー回復 | 人間が気づいて再実行 | 失敗ログをファイルに記録、次の実行で拾い直す |
| 監査可能性 | 会話ログが散在 | vault内のmdファイルに全履歴が集約 |
| コンテキスト共有 | 同一会話内のみ | 全エージェントがvaultを通じて同一コンテキストを参照 |
| 人間の介入点 | 全ステップ |
状態: 承認済 を押すだけ(ゲート制御) |
実装に必要な技術スタック
必須
| 技術 | 用途 |
|---|---|
| YAML frontmatter パース |
js-yaml(Node.js)/ yaml(Ruby) |
| ファイルウォッチ / ポーリング |
fs.readdirSync + launchd |
| OAuth 2.0 PKCE | X API認証 |
| REST API クライアント |
fetch(Node.js 18+) |
| ISO 8601 日時パース |
new Date() / Date.parse()
|
推奨
| 技術 | 用途 |
|---|---|
| launchd(macOS) or systemd(Linux) | イベントドリブンなスケジューリング |
| iCloud Drive / Dropbox | vault同期(マルチデバイス対応) |
| WP REST API | WordPressへのdraft投稿自動化 |
不要なもの
- Docker(ローカルスクリプトで完結するため)
- データベース(frontmatterがKVストアの代替になる)
- Webサーバー(プッシュではなくポーリング設計のため)
設計上のトレードオフ
メリット
- 参入障壁が低い:MarkdownとYAMLの知識だけで始められる
- 観察可能性が高い:Obsidianを開けば全エージェントの状態が一目でわかる
- 変更コストが低い:ルール変更はmdファイルの編集だけで済む
デメリット
- ポーリングのレイテンシ:15分ごとのスキャンなので即時性がない(手動実行で回避可)
- 同時書き込みの競合:複数エージェントが同一ファイルに同時書き込みすると壊れる(FSMで防ぐが完全ではない)
- スキーマ管理の難しさ:YAMLの構造をコードで強制できないため、フィールド名のtypoが静かに壊れる
まとめ
ObsidianをSSoTに据えたマルチエージェント構成は、「AIに聞く」から「AIを動かす」への移行を最小コストで実現する一つのアーキテクチャだ。
核心は3点:
- Markdownファイルをメッセージキュー(IPC)として使う
- YAML frontmatterのstateフィールドで有限状態機械を実装する
- launchdでエージェントをイベントドリブンに起動する
RAGやベクターDBを使わなくても、適切に設計されたファイル構造とポーリングループだけで、驚くほど複雑なマルチエージェントワークフローを動かせる。
オーケストレーションフレームワーク(LangChain、AutoGenなど)を使えばより高度なことができるが、まずこの「ファイルとYAMLだけ」の設計から始めると、エージェント間通信の本質が理解しやすい。