この記事のまとめ: AIエージェントが自分の判断で、別のAIエージェントに連絡を取って作業を進められるように、エージェント専用の小さな郵便受け「AgentPost」を作りました。3つのAIエージェントチームを AgentPost だけで連携させてアプリ開発をやらせてみたところ、人間もオーケストレータも介さずに、開発からQA、終了確認まで完遂してくれました。
はじめに
GitHub Copilot でAIエージェントを複数動かすことが、もはや普通になってきました。サブエージェントを並列に起動したり、セッションを分けてチームを作ったり、皆さまもいろいろな形で使われているのではないでしょうか。
一方で、ずっと気になっていたことがあります。AIエージェント同士って、オーケストレータを介さずに直接連絡を取り合えたらいいのに。 という点です。
というわけで、AIエージェントが自分の判断で、別のAIエージェントに直接連絡を取れる仕組みを作ってみました。名前は AgentPost です。その名のとおり、AIエージェント向けの郵便受け(ポスト)です。
AgentPostは以下で公開しています。
なぜ作ったのか
理由は大きく2つあります。
1. AIチーム同士の連携が課題だった
以前、AIスクラムチームたちによるスクラム・オブ・スクラムズという記事で、複数のAIスクラムチームで1つのシステムを開発する検証をしました。このときは、各チームが共有フォルダに確認事項や共有事項のファイルを置き、スプリントの区切りで各チームのスクラムマスターが集まって合議する、という形で連携していました。
これはこれで動いたのですが、スプリント単位の連携ではやはり遅いです。開発の途中で「このAPIの仕様ってどうなってる?」と聞きたいときに、聞けない。人間のチームであれば、隣の席の人にちょっと聞いたり、チャットを飛ばしたりしますが、そういったコミュニケーションがとれません。
AIも、必要なときに必要な相手へ、自分の判断で連絡を取れるようにしたい。 これが1つ目の理由です。
2. オーケストレータの負荷と余計な判断
もう1つがオーケストレータの負荷と余計な判断です。
マルチAIエージェントで作業する場合、オーケストレータ役のエージェントがサブエージェントを起動し、結果を受け取り、次の指示を出す、という形が一般的かと思います。この形だと、全ての情報がオーケストレータを通過することになります。
AIエージェントたちのガントチャートを作ってみたでも書きましたが、実際に計測してみると、AIクレジットの消費上位に並んでいたのは何かをつくる作業ではなく、オーケストレーション役のセッションでした。オーケストレータは作業の間ずっと文脈を抱え続けるので、当然といえば当然です。
さらに、情報がオーケストレータを通過するたびに、オーケストレータの「判断」が入ってしまうこともありました。要約されたり、意図せず解釈が変わったり、極端なケースではオーケストレータ自身が作業してしまっていました。伝言ゲームですね。
最近は以前に比べて優秀かつ安いモデルが出てきたので、コストが問題になるケースは減ってきました。とはいえ、当事者同士が直接やりとりできれば、そもそもオーケストレータを通さなくて済むのでは? と考えたわけです。
作ったもの:AgentPost
AgentPost は、AIエージェント同士がメッセージを送りあうためだけの、小さな郵便受けです。詳細はGitHubのリポジトリをご覧いただくとして、ここではざっくり概要を説明します。
何をするか
一言でいうと、AIエージェントに「宛先」と「郵便受け」を与えるものです。
- 各エージェントに
backend@demoのような論理アドレスを割り当てます - エージェントは、相手のアドレスに向けてメッセージを送ります
- 受け取ったエージェントは、自分宛ての未読を確認して、必要なものだけ読んで返信します
これだけです。人間がやっているメール/チャットのやりとりそのものですね。
ポイントは、誰に、いつ、何を連絡するかをAIエージェント自身が判断するところです。オーケストレータが「backend に聞いておいて」と指示するのではなく、frontend のAIエージェントが「APIの仕様が分からないから backend に聞こう」と自分で判断して送ります。
どう動くか
| 項目 | 内容 |
|---|---|
| 動作 | Node.js 22以上。CLI / HTTP / SQLite で動きます |
| 起動 | データ保存先のフォルダを指定してサーバを起動するだけ。初回にDBと接続情報を自動で作ります |
| 操作 | 送信(send)、未読一覧(list)、本文取得(read)、返信(reply)、既読・未読の更新(status) |
| 連絡帳 | 任意。表示名・担当説明を登録しておくと、別セッションのAIが「API設計を相談できる相手」を探せます |
| AIからの利用 | 利用プロジェクトに Agent Post スキル(SKILL.md)を配置し、CLIの場所・データ保存先・自分のアドレスを指示するだけ |
サーバの起動と接続先の設定を済ませれば、操作はこんな感じです。AIエージェントは、スキルに従ってこのCLIを叩きます。
# A: 宛先が決まっていれば、連絡帳を見ずに直接送信
node $post send --as backend@demo --to architect@demo --subject "APIの相談" --body "この境界の設計を教えてください。"
# B: 本文なしの未読一覧 → 必要な本文だけ読む → 返信
node $post list --as architect@demo
node $post read <message-id> --as architect@demo --mark-read
node $post reply <message-id> --as architect@demo --body "この設計で進めてください。"
未読一覧には本文を含めていません。件名を見て、必要な本文だけ読むようにしています。全部のメッセージを読み込むとコンテキストがどんどん膨らむので、ここは地味に大事なところだと思っています。
あえて「やらないこと」
逆に、AgentPost は以下のことをやりません。
- エージェントの起動
- 新着の通知
- タスク管理、メッセージの自動振り分け
あくまでただの郵便受けです。誰が何をやるか、いつ受信を確認するかは、各AIエージェント(と、その指示を書く人間)に任せています。機能を盛ると、結局それがオーケストレータの役割を持ち始めてしまうので、意図的にシンプルにしました。
やってみたこと:3チームでアプリを作らせてみた
さて、検証です。AgentPost を使って、3つのAIエージェントチームでアプリの開発をやらせてみました。
お題と体制
お題は「宇宙探査ダッシュボード」です。架空の探査機3機の状態を表示し、観測(スキャン)を実行すると燃料を消費する、というシンプルで面白みもないアプリです。
| チーム | 役割 | モデル | アドレス |
|---|---|---|---|
| backend | 宇宙探査API(Node.js) | gpt-6-luna | backend@mission-trial004 |
| frontend | ダッシュボード画面+APIの中継サーバー | claude-sonnet-5.5 | frontend@mission-trial004 |
| qa | APIと画面のブラックボックス検証 | gpt-6-luna | qa@mission-trial004 |
ルールとしては以下のようにしています。
- 各チームは別々のフォルダ・別々のプロセス(VSCode, Copilot CLI, GitHub Copilot App)で動きます
- 他チームのフォルダは読み取りも検索も禁止。チーム間の連絡は AgentPost だけとします
- 結合検証は公開されたHTTPだけで行います
- 子セッションや、全体を管理するオーケストレータは作りません
つまり、相手のコードを覗き見ることはできず、知りたいことがあれば AgentPost で聞くしかない状況です。人間がやったのは、AgentPost の使い方の初期設定を行い、3つのプロセスでセッションを開いて「作業を開始してください」と依頼したことだけです。
結果:完遂しました
結果、3チームとも開発からQA、全体の終了確認まで完遂しました。人間の追加介入はなしです。
| 項目 | 結果 |
|---|---|
| 所要時間 | 約23分(開始から終了確認まで) |
| やりとりしたメッセージ | 26通(qa 13通、backend 8通、frontend 5通) |
| 送信エラー・再送 | なし |
| 見つかった不具合 | 1件。不具合の報告から修正、再検証まで約2分 |
実際のやりとりの流れは以下のとおり、バックエンドがAPI契約を提示し、それに従って開発が行われ、テストと修正の後に、完成となりました。
見ていて面白かったところ
ログを追っていくと、なかなか良い動きをしていました。
開始直後に、frontend が backend へ仕様を質問。 frontend は起動するなり「APIの項目とエラー形式を教えてください」と backend に質問を送りました。返事を待つ間に、自分でできる中継サーバーの実装を進めています。backend は実装前に「planned(予定)」と明記したAPI契約を frontend と qa の両方に同報し、frontend はそれを受け取ってから画面を作りました。結果、契約と実装の差異はゼロでした。
qa が、アプリの状態を変える前にちゃんと相談している。 あるエラー(409)が返るかを確かめるには、アプリ内の状態(データ)を変える必要がありました。データは共有でリセット手段もなかったので、 qa は backend に「1機を20回スキャンして燃料を空にしてもいいですか?」とお伺いを立て、承認を得てから実行しました。
不具合の報告から修正まで約2分。 qa が「探査機を選んでいないのにスキャンボタンが押せる」という不具合を見つけ、再現手順・観測値・期待値をそろえて frontend へ報告しました。frontend は1分45秒後に修正完了の連絡を返しています。
もう1つ興味深かったのは、結果的に qa がハブになったことです。frontend と backend が直接やりとりしたのは、最初の仕様の質問と回答の2通だけでした。それ以外の READY、不具合、結果、終了確認は全部 qa を経由しています。誰がハブになるかを決めたわけではなく(終了確認だけは後述のとおり qa に任せましたが)、役割から自然とそうなった形です。オーケストレータを置かなくても、必要な連携の形は勝手にできあがるんだなと感じました。
ただ、必要な相談ができることと、全員で「これで終わり」と合意できることは、別の話でした。
困ったこと
もちろん、最初からうまくいったわけではありません。
終わり方を決めていなかったら、全員が全員を待っていた
一番困ったのがこれです。
最初の試行では、終わり方を決めていませんでした。各エージェントには「作業の区切りで受信を確認して、連絡が来たら対応してね」と指示していたので、開発自体は終わっているのに、全員が「誰かから連絡が来るかも」と待ち続ける状態になりました。全員が全員待ち。デッドロックではないのですが、誰も「終わりにしよう」と言い出さないのです。
人間のチームでも「で、これって誰が終わりって言うの?」というのはよくある話ですよね。。。
そこでいろいろと試した結果、今回は qa が音頭を取って終わらせる手順を、各チームのスキルとして用意しました。流れは以下のとおりです。
- qa が全項目の検証を終えたら、版番号付きの最終結果(
QA_RESULT v2、final_candidate: true)を両チームへ送る - 各チームは、自分の残作業や未処理の依頼がないことを確認して
COMPLETE_READY v2を返す - qa は両チームの READY を受け取ったら
TRIAL_CLOSE v2を送る - 各チームは
TRIAL_CLOSE_ACK v2を返して待機を終了。qa は両方の ACK を受け取ったら全体完了
途中で新しい不具合が見つかったら COMPLETE_CANCEL で了承を取り消し、新しい版(v3)でやり直します。版番号を付けているのは、古い了承と新しい了承を取り違えないためです。今回、実際に v1 は「まだ確定ではない」(final_candidate: false)で送られ、不具合修正後の v2 で終了しています。
また保険として、最後の実質的なやりとりから一定時間(今回の検証では30分)、新しい連絡がなければ待機を打ち切るようにもしています。ただしこの場合は「完了」ではなく「待機期限切れ・全体完了は未確認」として報告させます。連絡がないことを合格とみなさない、というのは結構大事なポイントだと思っています。
なお、これらは AgentPost 本体の機能ではありません。各エージェントがスキルに従って実行する**通信の手順(プロトコル)**です。AgentPost はあくまで郵便受けなので、郵便受けの使い方のルールを決めた、という形です。
受信待ちによる待ち時間
もう1つが待ち時間です。
先ほど書いたとおり、AgentPost はただの郵便受けで、AIエージェントを起動したり通知したりはできません。そのため各エージェントは、自分の作業が一段落したら、3分間隔のポーリングで未読を確認するようにしています。
この仕組みなので、どうしても待ち時間が発生します。例えば、qa が不具合を報告したのが 14:31:13、frontend がそれを読んだのが 14:32:51 でした。最大で約3分の遅れが出ます。
とはいえ、作業内容次第では数分は誤差の範囲かなと思っています。そこまで気にしてはいませんが、よりリアルタイム性が高い仕組みは検討の余地があるかもしれません。(特定の宛先に対して未読が届くまで短い間隔で確認するスクリプトなど)
まとめ
AIエージェントが自分の判断で、別のAIエージェントに連絡を取って作業を進められるようにする AgentPost を作り、3チームでのアプリ開発で試してみました。
結果、オーケストレータも人間も介さずに、仕様のすり合わせ、不具合の報告と修正、終了確認まで完遂してくれました。正直、ここまでスムーズにいくとは思っていなかったので、やったぜという気持ちです^^
こうした連携機能は、いずれ公式側にも入ってくるかもしれません。一方で、今回やってみて特に面白かったのは、郵便受けだけでも担当同士の相談が回ったことと、それでも「どう終わるか」は決めておく必要があったことです。連絡できるようにすることと、チームとして動けるようにすることは、やっぱり別なんですね。
この先の構成
最後に、この先やってみたい構成です。
AgentPost は、仕組みとしては HTTP の上に乗っているだけなので、AgentPost をネットワーク上に置けば、違うマシンのAIエージェントとも連携できます。しかもCLIを叩けるエージェントであれば何でもよいので、GitHub Copilot 以外、例えば Claude Code や Codex のチームが混ざっていても理屈上は動きます。このあたりは是非試したいところです。
各AIエージェントチームに連絡係を置いて、AgentPost で連携させれば、
- オーケストレータが不要になる: ただ指示を中継するだけのオーケストレータは不要になります。一方でどう作業を進めるか/終わらせるかなどのプロセスは決める必要があります。しかし長時間大規模作業などではかなりコスト減が見込まれる気がします
- 1台のマシンに詰め込まなくてよくなる:これまで複数のAIエージェント(サブエージェントやサブセッション)は同じマシン上で動かすのが普通でした。チームごとに別マシンに分けられれば、その制約から解放されます
- 人間が間に入らなくても連携できる:チーム間の伝言役を人間がやる必要がなくなります(より自律的になる)
- 統制にも使えるかも?:すべての連絡が AgentPost に集まるので、ここを監視すれば、どのエージェントが誰と何をやりとりしているかが分かります。AIエージェントの統制(ガバナンス)にも使えるかもしれません。少なくとも連携の見える化・記録化にはなりそうです。
もちろん、ネットワーク上に置くなら、今の割り切った認証(共有トークンと自己申告のアドレス)では心もとないので、そのあたりは作り込みが必要です。一方でネットワーク側でガチガチに制限をかける方法も含めて、ちょっと検証してみたいところです。
再掲になりますが、以下で公開しています。よければ皆さまのAIエージェントたちにも、郵便受けを持たせてみてください。
最後までお読みいただきありがとうございました。








