五反田式: スティグマジーを応用した自律型マルチエージェントシステム【日本語訳】

本記事は、Hashnodeに公開した AI Agents Don't Need Meetings: Gotanda Style for Stigmergic Software Maintenanceの日本語訳です。
AIコーディングエージェントによって、コードを書く速度は大きく上がりつつあります。
これは素晴らしい変化です。しかし、コードを書く速度が2倍になれば、保守運用の負荷もまた増えます。より多くのコードが、より短い期間で本番環境に入り、より多くの変更が監視、デバッグ、リファクタリング、テスト、設計改善の対象になります。
AI駆動開発では、実装速度だけを上げても十分ではありません。実装速度に見合うだけの、保守運用の仕組みも強化する必要があります。
LLMを使ったマルチエージェントシステムでは、複数のエージェントをどう協調させるかが難しい問題になります。
よくある設計は、エージェント同士を会話させる、またはSupervisor役のエージェントが全体を管理する方式です。これは直感的で扱いやすい一方、エージェント数が増えるほど、通信量、文脈管理、合意形成、トークン消費が膨らみます。
私たちは別の方式を試しています。
代わりに、各エージェントは観測した事実や懸念を共有環境に「痕跡(フェロモン)」として残します。別のエージェントは、その痕跡を後から読み取り、統合し、必要ならIssue化し、さらに別のエージェントがPRを作成します。
このように、個体同士が直接通信せず、環境に残した痕跡を通じて協調する仕組みは stigmergy (スティグマジー) と呼ばれます。この考え方を、ソフトウェア保守運用のためのLLMマルチエージェントワークフローに応用しました。
私たちは、この方式を 五反田式エージェンティック・ワークフロー と呼んでいます。
これは単なる理論上のアイデアではありません。私たちはこの方式を、すでに20万行規模のPythonリポジトリの保守運用に使っています。SentryアラートやDatadogメトリクスを起点にフェロモンを沈着し、集約されたシグナルからIssueを作り、さらに自動実装可能なものを改善PRへ変換するところまで、実際に動いています。
なぜ保守運用に注目するのか
AIエージェントは、新しいコードを書く作業を強力に支援します。
しかし、ソフトウェア開発のコストは「コードを書くこと」だけではありません。むしろ、長期的には次のような保守運用のコストが大きくなります。
- 本番エラーを調査する
- 性能劣化を検知する
- テスト不足を補う
- 設計のほころびを見つける
- 依存関係や境界の崩れを直す
- 小さな改善を継続的にPRへ変換する
AIがコードを書く速度を上げるほど、これらの保守対象も増えます。つまり、AI駆動開発を本当にスケールさせるには、コード生成の自動化だけでなく、保守運用そのものをエージェント化する必要があります。
五反田式エージェンティック・ワークフローは、この問題意識から生まれたワークフローです。
新機能の意思決定をAIに全面委任するのではなく、保守運用のように反復的で観測可能な領域を、複数のAIエージェントで継続的に支えることを狙っています。
なぜ会話型マルチエージェントはスケールしにくいのか
マルチエージェントというと、複数の専門家エージェントが会話しながら問題を解く姿を想像しがちです。
たとえば、次のような構成です。
- Planner agent がタスクを分解する
- Research agent が調査する
- Coding agent が実装する
- Reviewer agent がレビューする
- Supervisor agent が全体を判断する
この構成は小さなタスクではうまく機能します。実際、現在の多くのエージェントフレームワークも、Supervisor、handoff、router、subagent といったパターンを中心に設計されています。
しかし、ソフトウェア保守運用のように、継続的で、非同期で、対象範囲が広い問題では、会話中心の協調にはいくつかの弱点があります。
- エージェント数が増えるほど通信グラフが複雑になる
- 各エージェントが他エージェントの文脈を読むため、トークン消費が増える
- Supervisorに情報が集中し、単一障害点になりやすい
- 大規模コードベースでは、全員が同じ情報を読むのは非効率
- 一時的な判断やノイズが会話履歴に残り、後続判断を汚染しやすい
人間の組織でも同じです。全員が常に会議で同期しながら働く組織は、人数が増えるほど遅くなります。
LLMエージェントでも、全員を会話させる設計は、ある規模を超えると協調そのものがコストになります。
五反田式エージェンティック・ワークフロー: 会話ではなく環境で協調する
五反田式エージェンティック・ワークフローの基本方針はシンプルです。
エージェント同士が会話することなく、共有環境に残った痕跡(フェロモン)を元に連携する
各エージェントは、自分の担当領域だけを観測します。そして、見つけたシグナルを共有環境に書き込みます。
この共有環境を、私たちは pheromone field と呼んでいます。日本語では「フェロモン場」です。
たとえば、以下のようなエージェントがいます。
- Sentry worker: 実行時エラーを観測する
- Datadog worker: 遅いリクエスト、遅いSQL、5xx、コストスパイクなどを観測する
- Quality worker: レイヤリング違反、例外処理漏れ、テスト不足、API契約のズレなどを探索する
- Refactor worker: フェロモン場を読み、複数の観測結果を統合してIssue化する
- Code worker: Gotandaラベル付きIssueを実装し、PRを作成する
重要なのは、観測系のworkerが直接Issueを乱立させないことです。
Sentry workerは「このファイルでエラーが起きている」という痕跡を残します。Datadog workerは「このエンドポイントが遅い」という痕跡を残します。Quality workerは「この関数には例外処理の問題がありそうだ」という痕跡を残します。
それらを直接会話で調整するのではなく、Refactor workerが後から集約されたフェロモン場を読みます。
この流れは、次の3段階に分けられます。
- Observer: 外部世界やコードベースを観測し、フェロモンを沈着する
- Integrator: フェロモン場を読み、複数シグナルを統合してIssue化する
- Implementer: 自動実装可能なIssueをPRに変換する
Sentry worker ----+
Datadog worker ----+--> Pheromone field --> Refactor worker --> GitHub Issue --> Code worker --> Pull Request
Quality worker ----+
フェロモンとは何か
フェロモンは、エージェントが共有環境に残す構造化されたシグナルです。
最小限のモデルは次のようになります。
(scope, location, worker, strength, half_life, metadata)
それぞれの意味は次の通りです。
-
scope: シグナルの粒度。file、function、endpoint、sql など -
location: 実際の場所。ファイルパス、関数名、APIパス、SQL fingerprint など -
worker: どのエージェントが沈着したか -
strength: どれくらい強いシグナルか -
half_life: どれくらいの時間で弱まるか -
metadata: エラー種別、環境、根拠、分類などの追加情報
たとえば、Sentry workerが本番エラーを見つけた場合、次のようなフェロモンを沈着します。
{
"scope": "file",
"location": "app/services/invoices.py",
"worker": "sentry-worker",
"strength": 2.0,
"half_life_days": 14,
"metadata": {
"category": "runtime_error",
"environment": "production",
"error_type": "IntegrityError"
}
}
Quality workerが同じファイルにテスト不足を見つけた場合、別のフェロモンを沈着します。
{
"scope": "file",
"location": "app/services/invoices.py",
"worker": "quality-worker",
"strength": 1.0,
"half_life_days": 21,
"metadata": {
"category": "test_gap",
"severity": "medium"
}
}
Refactor workerは、個々の沈着ではなく、集約されたフェロモン場を読みます。
同じ場所に複数のworkerからシグナルが集まっていれば、そこは優先的に見るべきhotspotです。
正のフェロモンと負のフェロモン
五反田式エージェンティック・ワークフローでは、フェロモンは正の値だけではありません。
正のフェロモンは「ここを見るべき」という誘引シグナルです。
一方、負のフェロモンは「ここは一度検討したが、今は追わない」という抑制シグナルです。
たとえば、Refactor workerがある候補を調査し、「これは設計上許容されている」「今は修正しない」と判断した場合、負のフェロモンを沈着できます。
{
"scope": "fingerprint",
"location": "layering_violation:abc123",
"worker": "refactor-worker",
"strength": -1.5,
"half_life_days": 60,
"metadata": {
"reason": "accepted design exception"
}
}
これにより、同じ候補が何度もIssue化されることを防げます。
ただし、負のフェロモンは永久に残るわけではありません。時間とともに減衰します。もし後日、SentryやDatadogから強いシグナルが再び沈着されれば、その場所は再び注目されます。
この「一度Won't Fixにしたが、状況が変わったら再浮上する」という性質は、保守運用ではとても重要です。
なぜこの方式はスケールしやすいのか
1. エージェント数を増やしても通信量が爆発しにくい
会話型の設計では、エージェント数が増えるほど、誰が誰に何を伝えるかが問題になります。
五反田式エージェンティック・ワークフローでは、各エージェントは他のエージェントを知る必要がありません。共有環境に対して、決められた形式でシグナルを書き込むだけです。
新しいworkerを追加するときも、必要なのは「どんなフェロモンを沈着するか」という契約です。
これはプラグイン的です。
Security workerを追加したければ、セキュリティ観点のシグナルを沈着すればよい。Performance workerを追加したければ、性能観点のシグナルを沈着すればよい。
Refactor workerは、それらを同じフェロモン場の一部として読めます。
2. 大規模コードベースを効率的に探索できる
大規模コードベースでは、毎回すべてのファイルを読むのは現実的ではありません。
重要なのは、限られた探索予算をどこに使うかです。
フェロモン場があると、探索は完全なランダムでも、単純なrecent files偏重でもなくなります。
- 直近変更されたファイルを見る
- ランダムに一部を見る
- SentryやDatadogが示したhotspotを見る
- 過去に負のフェロモンが強い場所は優先度を下げる
- 複数workerが同じ場所に沈着したら優先度を上げる
このように、観測結果によって探索予算を動的に配分できます。
これは、大規模コードベースに対する「AIによる継続的な保守探索」と相性が良いです。
3. トークン効率が良い
エージェント同士が長い会話をしないため、他エージェントの詳細な思考過程や会話履歴を読む必要がありません。
共有されるのは、構造化された小さなシグナルです。
{
"scope": "endpoint",
"location": "GET /api/reports",
"worker": "datadog-worker",
"strength": 1.2,
"metadata": {
"category": "slow_request",
"p95_ms": 1800
}
}
これは、数千トークンの会話ログよりずっと安い。
必要なときだけ、Integratorがコードやログを深掘りします。
4. 非同期に動かせる
すべてのworkerが同じタイミングで動く必要はありません。
Sentry workerは10分ごと、Datadog workerは1日1回、Quality workerは夜間、Code workerは5分ごと、といった運用ができます。
各workerは、自分のペースで環境を観測し、フェロモンを沈着します。
これは実運用では大きな利点です。外部API、CI、GitHub、Sentry、Datadogなどは、それぞれレート制限や失敗特性が違います。各workerを独立に動かせると、障害が局所化しやすくなります。
5. ノイズを時間で減衰させる
LLMエージェントの判断にはノイズがあります。
あるworkerが一度だけ弱いシグナルを出したとしても、それがすぐにIssueになるべきとは限りません。
五反田式エージェンティックワークフローでは、フェロモンは時間とともに減衰します。
一度だけの弱いシグナルは自然に消えます。複数回観測されるシグナル、複数workerから集まるシグナル、本番影響のあるシグナルは強く残ります。
この性質により、単発ノイズよりも継続的な問題を優先しやすくなります。
単純な合計だけでは足りない
ここで注意が必要です。
フェロモンを単純に合計するだけだと、重要な情報を失うことがあります。
たとえば、ある場所に次の2つのシグナルがあるとします。
sentry-worker: +2.0
refactor-worker: -2.0
単純合計は0です。
しかし、これは「何も起きていない場所」ではありません。
実際には、「本番エラーが起きているが、過去にはWon't Fix判断もある」という衝突状態です。
この2つを同じ0として扱うと、重要な候補を見逃します。
そこで五反田式エージェンティック・ワークフローでは、正の成分、負の成分、総変動、衝突率を分けて扱います。
-
current_strength: 正味の強さ -
positive_strength: 正のシグナル量 -
negative_mass: 負のシグナル量 -
total_variation: 正負を相殺しない総量 -
conflict_ratio: 正負がどれくらい衝突しているか
数学的な詳細は補足に回しますが、実務上の意味はシンプルです。
沈黙と衝突を区別する。
これにより、Refactor workerは次のような判断ができます。
- 強い正のシグナルだけがある: 自動実装候補かもしれない
- 強い負のシグナルだけがある: 今は追わない
- 正負が強く衝突している: 人間レビューに回すべきかもしれない
- 何もない: 探索優先度を下げる
五反田式エージェンティック・ワークフローにおけるIssue化の考え方
五反田式エージェンティック・ワークフローでは、観測workerが直接Issueを作ることをなるべく避けます。
理由は、観測時点では文脈が足りないことが多いからです。
Sentry workerはエラーを知っています。しかし、それが局所修正で済むのか、設計変更が必要なのか、既知の許容例なのかまでは判断しきれません。
Datadog workerは遅いSQLを知っています。しかし、そのSQLが本当に問題なのか、バッチ処理として許容されているのか、上位の業務要件まで含めて判断するのは難しい。
Quality workerはレイヤリング違反らしきものを見つけます。しかし、例外的に許容されている設計かもしれません。
そのため、観測workerは原則としてフェロモンを沈着するだけにします。
Issue化はIntegratorに集約します。
Integratorは、複数のフェロモン、現在のコード、既存Issue、過去のWon't Fix判断を見て、総合的に判断します。これによって、矛盾したIssue起票、重複した起票を避けることができます。
Issueは次のように分類します。
| 分類 | 意味 | 送り先 |
|---|---|---|
| A | 問題なし、または既知の許容例 | 起票しない |
| B1 | 局所修正で安全に直せる | Code worker |
| B2 | 設計判断が必要 | 人間 |
| C | 原因不明、調査が必要 | 人間 |
Code workerに流すのは、B1だけです。
これは安全性のためです。自動実装エージェントに渡すIssueは、意図が明確で、修正範囲が限定され、PRからIssueの意図を読み戻せる粒度であるべきです。
大きな設計判断は人間が行います。人間が一度方針を決めたら、その後の局所的な適用作業はCode workerに分解できます。
実際の運用
五反田式エージェンティック・ワークフローは、20万行規模のPythonリポジトリの保守運用に適用しています。
AWS EC2上に構築し、各エージェントはDockerコンテナ上で動作しています。
フェロモン場はPostgresを使い、エージェントが読み書きしています。
エージェントからの報告はSlackに通知されるようにし、人間がいつでも見れるようにしています。
IssueやPRを作成すると人間の担当者にメンションします。
Code Workerが作成したPRは、ただ作成するだけでなくCIの実行やbotレビューまで監視し、CIが完全に通り、botレビュー指摘がすべて解決するまで対応します。これによって、人間がPRをレビューする際には、一定の品質が保たれるようにしています。
すべては自律的であり、人間の手を介さずにメンテナンスループが回るようにしています。
課題
もちろん、この方式にも難しさがあります。
最大の課題は、フェロモン場の品質です。
フェロモン場がノイズだらけになれば、システム全体がノイズに引っ張られます。逆に抑制が強すぎると、本当に重要な問題を見逃します。
特に難しいのは次の点です。
locationの正規化
同じ場所を指しているのに、workerごとに別のlocationとして沈着してしまうと、シグナルが集約されません。
たとえば、同じAPIを次のように別々に表現してしまうケースです。
GET /api/users/{id}
/api/users/:id
app/api/users.py:get_user
これらをどこまで同一視するかは、設計上とても重要です。
strengthの較正
Sentryの本番エラー +2.0 と、Quality workerの低確信度の懸念 +0.5 は同じ重みではありません。
workerごとの信頼度、カテゴリごとの重要度、環境ごとの影響度をどう重みに反映するかは、継続的な調整が必要です。
負のフェロモンの意味論
負のフェロモンは便利ですが、危険でもあります。
「今は追わない」と「永久に無視する」は違います。
そのため、負のフェロモンには理由、対象fingerprint、半減期、再浮上条件が必要です。
監査性
自動化が進むほど、なぜそのIssueが作られたのか、なぜそのPRが作られたのかを追える必要があります。
フェロモンの沈着履歴、worker run、関連Issue、関連PRを辿れるようにしなければ、運用で信用されません。
エージェントを管理する管理画面も、今後整備する必要があるでしょう。
死活監視
自律型のエージェントが正しく動いているか、PR作成途中で落ちたり、トークンの期限切れで止まったりしていないか。
監視を行う仕組みを作り、クラッシュリカバリの方法も整える必要があります。
今後やりたいこと
五反田式エージェンティック・ワークフローはまだ発展途上です。
今後、特に重要だと考えているのは次の領域です。
- workerごとの信頼度重み
- カテゴリごとの重み
- location aliasの正規化
- run_idによる監査ログ
- self-stop条件
- canary運用
- human-in-the-loopの境界設計
- フェロモン場を使った探索対象の再配分
特に、フェロモン場を「読む」だけでなく、次回の探索範囲そのものに反映することが重要です。
たとえば、Quality workerが完全ランダムに探索するのではなく、以下のように探索予算を分配します。
- recent files: 40%
- random files: 30%
- pheromone hotspot: 20%
- cooling follow-up: 10%
こうすると、探索はランダム性を保ちながら、過去の観測結果に適応できます。
まとめ
LLMマルチエージェントシステムでは、エージェントをどう協調させるかが本質的な課題です。
会話型の協調はわかりやすいですが、エージェント数、コードベース規模、運用期間が大きくなるほど、通信コストと文脈管理コストが重くなります。
五反田式エージェンティック・ワークフローでは、エージェント同士を直接会話させません。
代わりに、各エージェントは共有環境にフェロモンを沈着します。別のエージェントがそれを読み、統合し、Issue化し、自動実装可能なものだけをPRに変換します。
私たちは、この方式がソフトウェア保守運用におけるAIエージェントの有力な設計パターンになる可能性があると考えています。
AIエージェントによって開発速度が上がるなら、それに比例して保守運用も強くしなければなりません。コードを書くエージェントだけでなく、コードベースを観測し、異常を検知し、改善候補を統合し、安全な粒度のIssueを作り、PRへ変換するエージェント群が必要になります。
今後、より多くのエージェントがコードベースを継続的に観測し、改善し、PRを作るようになると、会話中心ではない協調モデルの重要性は増していくはずです。
補足: スティグマジーとは何か
スティグマジーは、生物学や群知能の文脈で使われる概念です。
典型例は、アリが環境にフェロモンを残し、他のアリがその痕跡を辿ることで集団として経路を発見する現象です。
重要なのは、個体同士が直接相談していないことです。
個体は環境を読み、環境を変えます。その変更が、別の個体の行動を変えます。
五反田式エージェンティック・ワークフローでは、コードベース、監視データ、Issue、PR、フェロモンDBがこの「環境」に相当します。
補足: アトラクターエンジニアリングとして
五反田式エージェンティック・ワークフローは、別の言い方をすると、コードベースを悪いアトラクターに向かわせないための実践的なアプローチです。
ここでいうアトラクターとは、変更が繰り返されるうちに、コードベースが自然に吸い寄せられていく構造や状態のことです。
良い責務境界、良い型、良いテスト、良い実装例があるコードベースでは、次の変更も良い方向に収まりやすくなります。逆に、巨大な common、曖昧なservice、便利すぎるhelper、悪い既存実装が近くにあると、変更はそこへ吸い寄せられやすくなります。
AIエージェントは、この力学をさらに強めます。
AIは真空中でコードを書くわけではありません。既存コード、周辺ファイル、命名、テスト、過去の実装例、ドキュメントを読み、それらを手がかりに次のpatchを生成します。つまり、コードベース全体がAIにとってのpromptになります。
そのため、コードベースに悪い局所文法があると、AIはそれを自然な解として再生産しやすい。開発速度が上がるほど、悪いアトラクターへ落ちる速度も上がります。
アトラクターエンジニアリングとは、この「未来の変更がどこへ吸い寄せられるか」を設計する考え方です。
五反田式エージェンティック・ワークフローでは、フェロモン場を使って次のようなシグナルを観測します。
- どのファイルやエンドポイントに本番エラーが集まっているか
- どこに性能劣化が出ているか
- どこにテスト不足や責務境界の崩れがあるか
- どの場所が複数workerから繰り返し指摘されているか
- どの候補が過去にWon't Fixと判断されたか
- どの場所で正負のシグナルが衝突しているか
これは単なるアラート集約ではありません。
コードベースがどの方向へ流れつつあるのか、どの場所が悪い basin (引き込み領域) になりかけているのかを観測し、必要に応じてIssueやPRとして軌道を修正する仕組みです。
codebase field
-> AI / human PR force
-> pheromone observation
-> issue / repair PR
-> updated codebase field
この意味で、五反田式エージェンティック・ワークフローは「AIにたくさんコードを書かせる仕組み」ではありません。
AIが高速に加える変更力を、悪いアトラクターではなく、保守可能で観測可能なコードベースへ向けるための運用設計です。
補足: 数学的な見方
フェロモン場は、直感的には (scope, location) ごとの重み付きシグナルです。
より形式的には、各workerが (worker, scope, location) に符号付きの重みを沈着し、それを (scope, location) に集約します。
正の重みは誘引、負の重みは抑制です。
時間経過により、各重みは指数的に減衰します。
current = strength * 0.5 ^ (elapsed / half_life)
単純合計だけでは、正負が相殺された衝突状態を見逃します。
そのため、正の成分、負の成分、総変動、衝突率を保持します。
net = positive - negative
total_variation = positive + negative
conflict_ratio = 1 - abs(net) / total_variation
この補助量により、「何もない場所」と「強い賛否が衝突している場所」を区別できます。
Discussion