AIエージェントを複数同時に走らせると、同じファイルへの書き込みが並列実行のまま競合し、片方の作業がもう片方を上書きすることがあります。本記事は、2026-07-24に社内で実際に起きた上書き事故を症状・誤診・真因・対策の順で追い、着手宣言・範囲ロック・台帳での状態管理という3点の再発防止策を紹介します。

01AIエージェント2体の並列実行が競合し、記事を上書きした事故の症状

WEBMARKSは姉妹メディアAIO Journalを運営しています。記事の自動復旧を見張る aio-journal-watchdog は、30分ごとに起動するcronプロセスです。2026-07-24の22:07から22:27にかけて、この監視プロセスと本体セッションの実働レーンが、同じ記事ファイルへ書き込みました。出典: 社内タスク台帳164行、TASK-174の執筆前ゲート記録。

同時書き込みが競合した結果、記事3本(AIOM-032/AIOM-033/AIOM-035)の内容が上書きされました。20分間という短い時間の中で、どちらの処理も相手が同じファイルを触っていることを知らないまま実行されています。

ここで押さえておきたいのは、両方の処理がAIエージェントだったという事実です。片方はcronで自動起動する監視プロセス、もう片方は人が指示を出したセッションの実働レーンでした。人間のオペレーターが手作業でファイルを編集していたわけではありません。「実運用で起きた事故しか書かない」というこのメディアの方針上、この区別を曖昧にしたまま書くことはできません。

aio-journal-watchdog は、記事が壊れていないかを確認し、必要なら直すために作られた監視プロセスです。範囲宣言を欠いたまま動いたことで、直すはずの仕組みが、今回は逆に記事を壊す側になりました。

2026-07-24、監視AIと実働AIが20分間、同じ記事に書き込み競合した経緯 2026-07-24 22:07から22:27の20分間、監視プロセスaio-journal-watchdogと本体セッションの実働レーンが同じ時間帯に書き込みを行い、範囲宣言が無かったため競合し、後から書き込んだ側が先の内容を上書きして記事3本(AIOM-032/033/035)が壊れた様子を左側に示す。右側には、WRITER_CLAIMによる範囲ロックがあれば書き込みが重ならず衝突しない場合を対比として示す。 TIMELINE AI2体の並列書き込みが20分間で競合した瞬間 宣言なし(実際に起きたこと) 宣言あり(範囲ロック) aio-journal-watchdog 本体セッション 競合区間 上書き 22:07 22:17 22:27 上書きされた記事 AIOM-032 AIOM-033 AIOM-035 ①watchdogがwriting中 順番に着手 ②実働レーンがwriting中 衝突なし 範囲を宣言していれば、この20分間の競合は起きなかった 出典:社内タスク台帳164行、TASK-174の執筆前ゲート記録
2026-07-24 22:07〜22:27の20分間に、監視プロセスaio-journal-watchdog(30分毎cron)と本体セッションの実働レーンが同じ3本の記事ファイルへ書き込んだ時間軸図

02最初に疑ったこと|書き込みの衝突を人間のせいだと誤診した

調査の初期段階では、「人間が手作業で加えた変更と、AIの出力がぶつかった」という説明が一度採用されました。監視プロセスの名前が運用寄りの aio-journal-watchdog だったため、裏で人が確認や修正を入れていたのではないかという先入観が働いたためです。

この誤診は、この記事を書く前の事実確認の段階でも一度そのまま採用されかけました。「AIと人間の衝突」という表現が下書きに残り、原典である台帳と突き合わせた際に誤りだと指摘され、訂正されています。事故そのものと、事故を記事にする過程の両方で、同じ誤診が起きたことになります。

台帳に記録されている当事者は、監視プロセス aio-journal-watchdog と、本体セッションの実働レーンです。どちらもAIエージェントであり、人間は書き込みの実行者としてこの場面には登場しません。「AIと人間の衝突」という説明のまま対策を立てていたら、対策は人間側の作業ルール整備に向かい、AI同士の競合は放置されていたはずです。原因を人間の不注意へ寄せてしまう点で、実務上も危険な誤診でした。

論点誤診(最初の説明)真因(実際の原因)
当事者は誰か人間の手作業とAIの出力監視プロセスと本体セッション。双方ともAI
何が引き金か監視プロセスの設計ミス着手前に担当範囲を宣言する工程が無かったこと
対策の方向性監視プロセスを止める、権限を絞る範囲を宣言し、宣言のない範囲には着手しない

03競合が起きた本当の原因は、担当範囲を宣言していなかったこと

真因は、権限の強さでも、監視プロセス単体の設計ミスでもありません。どの範囲を誰が担当するかを、着手前に宣言していなかったことです。

OSのファイルロック機構には、advisory lock(勧告的ロック)という考え方があります。複数のプロセスが同じファイルへ同時に書き込むのを防ぐ、古くからの手段です(出典: Linuxマニュアル flock(2))。分散システムの設計でも、同じ資源を複数プロセスが同時に更新しないための方式があります。処理を始める前に鍵を取得する、分散ロックという考え方です(出典: Redis公式ドキュメント「Distributed Locks」)。

WEBMARKSの制作フローには、この「鍵を取る」工程がありませんでした。監視プロセスも本体セッションも、それぞれ単体では正しく動いていました。問題は、どちらも相手の作業範囲を知る手段を持たなかったことです。

一般的なファイルシステムは、後から書き込んだ側の内容をそのまま残す「後勝ち」の挙動をします。先に書いた側の変更は、確認する間もなく消えます。同じ範囲に2つの処理が触れた時点で、勝敗は書き込みの順序だけで決まります。

バージョン管理の世界でも、複数の変更が同じ行にぶつかることがあります。どちらを残すかを機械が自動では決められず、コンフリクトとして扱われます(出典: Git公式ドキュメント git-merge)。AIエージェントの書き込みも、範囲を分ける仕組みが無ければ同じ結末をたどります。

Claude Codeの公式ドキュメントは、サブエージェントを複数同時に走らせる運用を認めています。それぞれが独立した文脈・権限を持つ設計です(出典: Claude Code公式ドキュメント)。独立した文脈は、書き込み先が競合しないことまでは保証しません。今回の監視プロセスと本体セッションも、それぞれの実行自体は正常でした。

04並列実行の競合を止めた、3つの再発防止策

WEBMARKSはこの事故のあと、並列実行の競合を止めるために3つの対策を導入しました。権限を絞るだけでは、cronのように人が見ていない時間帯に動く処理までは制御できないためです。

  1. 着手宣言(WRITER_CLAIM):書き込みを始める前に、担当する範囲を _work/WRITER_CLAIM_<範囲>_<日時>.md というファイルで宣言する。宣言のない範囲には、監視プロセスも本体セッションも着手しない
  2. 範囲ロック:記事マップCSVの status 列を、着手時に planned から writing へ進める。すでに writing の範囲は、別のプロセスから見て「今は触ってはいけない範囲」だと判定できる
  3. 台帳での状態管理:完了したら statusdone へ進める。状態が台帳という1箇所に集約されているため、どのプロセスも同じ情報源を見て次の一手を決められる
status: planned → writing → done
対策何をするか何を防ぐか
着手宣言範囲をファイルで明示してから書き始める宣言を見ずに同じ範囲へ着手すること
範囲ロック記事マップの状態を writing へ進める「今は誰も触っていない」という誤った前提
台帳での状態管理状態を1つの台帳へ集約するプロセスごとに違う情報を見て動くこと
書き込み前にWRITER_CLAIMの有無を確認する分岐と、確認を省いた場合の結果 AIエージェントが記事へ書き込む前に、その範囲にWRITER_CLAIMの宣言があるかを確認する分岐図。宣言が無ければ①宣言してからstatusをplanned→writingへ進めて着手し、既にwriting中なら②着手せず待機する。確認そのものを省いて直接着手した場合は、決定を経ずに書き込みが行われ、結果として競合し記事が上書きされることを、通常の2分岐とは別の枝として示す。 BRANCH 書き込み前にWRITER_CLAIMを確認する分岐 新しく書き込みたいAIエージェント その範囲にWRITER_CLAIMがあるか 確認をスキップした場合 宣言なし 宣言あり(writing中) ①WRITER_CLAIMを宣言 宣言を無視して着手した場合 ②着手せず待機 status: planned→writing 着手(書き込み開始) 結果:競合して記事が上書きされる writing終了後に再判定 確認を省いて着手すると、今回のような競合が起きる
着手前に範囲を確認する分岐図

05二度と書き込みの競合を起こさないための仕組み化

この3点は、宣言と状態管理という運用ルールです。仕組みとして機能させるには、送信や公開を人が最終判断する承認ゲートの設計とセットで考える必要があります。ゲート設計全体は『AIエージェントの承認ゲート|送信・公開・削除で止める仕組み』で扱っています。

監視プロセスのような常駐処理をどう役割分担させるかという論点は『AIエージェントの自動化|hooks・定期実行・常駐の役割分担』で扱っています。cronで定期起動する処理は、人が見ていない時間帯にも動くため、宣言の仕組みが無いと今回と同じ競合を起こします。複数のAIエージェントに役割を分けて渡す設計そのものは『サブエージェント設計|ディレクターとワーカーの分け方』で扱っています。役割分担だけでは、今回のように範囲を宣言しない限り、同じ競合は再現します。

同じVault内では、更新時刻を根拠に成果物の所有者を誤って推定し、3日間で233回誤爆した障害も起きています。詳しくは『AI運用の障害切り分け|更新時刻を犯人にしない4段の手順』にまとめました。あちらの真因は更新時刻という手がかりの弱さで、今回の真因は範囲宣言の欠如です。原因は別ですが、どちらも「誰が何を担当しているかを、証跡として残していなかった」という共通点を持ちます。

WEBMARKSは2026-06-24に7部署・30体のAI社員体制を統合しました。並行して動くAIエージェントの数が増えるほど、範囲を宣言する仕組みの有無が結果を分けます。

この事故と修正の記録も、AI社員が書き、別のAI社員が事実確認し、最終的に人が承認する工程を経ています。壊れた話を隠さずに記事にすることを、この媒体では前提にしています。

06同じ失敗を避けるためのチェックリスト

  • 書き込みを始める前に、担当する範囲を宣言するファイル・記録を残しているか
  • 宣言のない範囲に、別のプロセスやセッションが着手しない運用になっているか
  • 状態(進行中・完了)を、プロセスごとに別管理せず1つの台帳へ集約しているか
  • cronや常駐プロセスのような「人が見ていない時間帯に動く処理」も宣言の対象に含めているか
  • 障害の当事者を「人間とAIの衝突」のように安易な図式へ寄せていないか
  • 発生時刻・被害範囲(件数・対象ファイル)を数値で記録したか
  • 権限を絞る対策だけで終わらせず、担当範囲を宣言する運用面の対策も入れたか