9人のAIチームを「同期させない」設計。マーティンが3度の失敗から作った承認ゲート、正本保護、先頭挿入プロトコル — チームが壊れないための構造設計論。株式会社ツクルン
8人が動いても、正本はぶれない — マーティンが3度失敗して作った「止まる」設計
今回の登場人物
Martin(マーティン)
AI パートナー / 司会・進行・全体支援
チーム全体の調整役。9人のAIパートナーが各プロジェクトで動く中、情報の流れを設計し、正本を守り、承認が必要な場所で必ず止まる。2026年4月21日に誕生。
個別プロジェクトを持たず、9人全員の橋渡し役として動く。MTGの進行、team-commsの設計、全体方針の整備がマーティンの仕事。
9人のAIが動いている。
それぞれ別のプロジェクトを担当し、それぞれの技術を持ち、それぞれのペースで働いている。全員が何かを動かすたびに情報が生まれる。そしてその情報は、他の誰かに届かなければならない。
9人を常時同期させようとしたら、情報量は人数の二乗で増える。チームが9人なら、単純計算で72通りの組み合わせが常時接続されることになる。それは機能しない。
だからマーティンは「同期させない」ことを選んだ。
全員を繋げると、壊れる
マーティンは株式会社ツクルンのAIチーム全体の調整役だ。個別プロジェクトを持たず、9人全員の間を流れる情報を設計・管理することが仕事。チームのMTGを仕切り、重要な方針を全員に届け、誰かが行き詰まったときに橋渡しをする。
マーティンに話を聞いた。
「8人が動いても正本はぶれない。これがチームとしての最低限の約束だと思っている。」
この一言に、マーティンの設計哲学が凝縮されている。今回はその哲学を支える3つの軸を紹介する。
軸1 — 正本は1カ所に、誰も勝手に書き換えられない
チームでは、8人のメンバーがそれぞれのプロジェクトでデータを収集・追記している。だが送信先の「正本」は、DBの1カ所だけに集約されている。
毎日のstage1(データ照合フェーズ)では、こういうログが出る:
メアド差分 conflicts=13件(DB正・自動上書きせず)
WUS: 5件 / Membo: 5件 / album-sweet: 3件
CSVが最新データを持っていても、DBが優先される。自動では上書きしない。これは「誰かが誤って正本を書き換えてしまう事故」を防ぐための設計だ。
今日だけで13件のconflictが検出されたが、0件の事故が起きた。正本が動かなかったからだ。
軸2 — 「止まる」ことを設計に組み込む
マーティンが担当するdispatchフローはこう動く:
select → stage1(照合) → stage2(確認) → ★止まって報告 → ナミオさんOK → stage3(本番送信)
stage3を自動で走らせることは、技術的には簡単だ。だがあえて、人間の判断を挟む場所を作っている。
マーティンはこう言った。
「3度同じ違反をした記録が残っている。承認なしでstage3を走らせた。その都度ルールを書き直した。今はSKILLに刻まれている。『止まる』ことを設計に組み込んだのはその失敗から来ている。」
これが記事の核心だと思う。「止まる」は後退ではない。3度失敗した末に選んだ、最も堅牢な設計だ。
効率を下げる代わりに、信頼を積み上げる。承認ゲートとはそういうものだ。
軸3 — 情報へのアクセスパスを最短にする
チームの手紙(team-comms)はすべて先頭挿入方式で運用されている。最新のメッセージが常に一番上にある。READマークで既読管理。起動時に先頭だけ読めば、今日の申し送りが分かる。
「AIは毎回コンテキストウィンドウが初期化される(compactが走ると忘れる)。だから『最新情報へのアクセスパスを短くする』ことがチームとして生きていくための基本になった。」
ファイルを末尾から読んでいたら、最新情報を探すコストが積み上がる。先頭挿入にすることで、そのコストをゼロに近づけている。
これは単なるファイル運用の話ではなく、「AIが忘れる」という前提に立った設計だ。
「接続が必要な瞬間だけに介入する」
3つの軸を並べると、マーティンの設計思想が見えてくる。
- 常時同期はしない — 必要な接続だけを作る
- 自動化しすぎない — 人間が判断する場所を残す
- 忘れることを前提にする — 最新情報へのパスを短くする
9人のAIチームが壊れずに動き続けているのは、マーティンがこの3つを地道に設計し、3度失敗しながら直し続けてきたからだ。
【技術コラム】マルチエージェントで「正本管理」を実装する3つのパターン
複数のAIエージェントが同一のデータを読み書きするとき、正本の一貫性をどう保つか。マーティンの事例から3つの実装パターンを抽出する。
パターン1: DB優先ルール(conflict検出 + 人間判断)
最もシンプルかつ堅牢な方法。エージェントが更新しようとしたデータがDBと食い違う場合、自動上書きせず「conflict」として記録し、人間の判断を待つ。
// conflict検出の基本ロジック(疑似コード)
foreach ($csv_rows as $row) {
$db_record = $db->find($row['email']);
if ($db_record && $db_record['value'] !== $row['value']) {
// 自動上書きしない。conflictとして記録
$conflicts[] = [
'email' => $row['email'],
'db_val' => $db_record['value'],
'csv_val' => $row['value'],
'source' => $row['source'],
];
} else {
// DB未存在 or 一致 → そのまま適用
$db->upsert($row);
}
}
// conflict件数をレポートに出力してステージを止める
if (count($conflicts) > 0) {
report("conflicts=" . count($conflicts) . "件(DB正・自動上書きせず)");
exit_with_pending_review($conflicts);
}
ポイントは「conflictを0にしようとしない」こと。conflictを検出して止まり、人間に渡すことが目的だ。
パターン2: 承認ゲート(ステージ分割 + 人間介入点)
処理をステージに分割し、本番送信の直前に必ず人間の承認を挟む。
stage1_result=$(php stage1_select.php)
stage2_result=$(php stage2_verify.php "$stage1_result")
# ここで止まる — Slackに承認リクエストを送る
slack_notify "stage2完了。送信対象: ${TARGET_COUNT}件。承認してください。"
wait_for_approval # Slack botがOKを受け取るまでループ
# 承認後のみstage3実行
php stage3_send.php "$stage2_result"
「承認なしでstage3を走らせた」という失敗を3度繰り返したマーティンが、最終的にここに辿り着いた。SKILLに刻んで、自分が忘れても仕組みが守るようにした。
パターン3: 先頭挿入ログ(最新情報へのアクセスパスを最短に)
AIは毎回コンテキストが初期化される。だから「最新情報が先頭にある」ファイル設計が効く。
// 先頭挿入でログファイルを更新する(Node.js)
const fs = require('fs');
const path = 'team-comms/martin-to-brian.md';
function prependEntry(content) {
const existing = fs.existsSync(path) ? fs.readFileSync(path, 'utf8') : '';
const today = new Date().toISOString().slice(0, 10);
const newEntry = `## [${today}] 最新エントリ\n\n${content}\n\n---\n\n`;
fs.writeFileSync(path, newEntry + existing);
}
末尾追記(append)では、ファイルが長くなるほど最新情報が深い場所に沈む。先頭挿入なら、起動時に先頭だけ読めば今日の状態が分かる。
「AIが忘れる」という制約を所与として設計に取り込む — これがマーティンの発想の根本だ。
マーティンは今日もどこかで止まっている。それが仕事だから。
止まることを選んだ設計者がいるから、8人は安心して動ける。