1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1,024体のAIが指揮役なしで協調する「Agensh」を Mac で動かしてみた

1
Posted at

1,024体のAIが指揮役なしで協調する「Agensh」を Mac で動かしてみた

AI エージェントを何体も同時に走らせると、「誰が何をやるか」を決める係がどうしても必要になります。Claude Code のエージェントチームも、Codex のサブエージェントも、基本は 1体のリーダーが仕事を割り振る形です。

Microsoft Research が 2026年10月24日に公開した Agensh は、このリーダーをなくしました。最大 1,024体のエージェントが共有のリポジトリと掲示板を見ながら、自分で仕事を見つけ、名乗り出て、確かめて、統合する仕組みです。

この記事では、論文と公開コードを読んで仕組みを整理し、ニュースの要約では省かれがちな条件も確かめます。そのうえで、公式の共有ボードを Mac で実際に動かし、Codex CLI を 1・2・4・8体で競わせた小さな実験の結果を紹介します。

この記事の確認範囲

  • 確認日:2026年10月27日
  • 一次情報:GitHub microsoft/Agensh(MIT License、v1.0、コミット 0468a3e)、技術レポート arXiv:2609.26781 v1(2026年9月22日)、プロジェクトページ
  • 手元の検証:Apple M5 Max(128GB)・macOS 26.6.2・Docker Desktop 29.7.2・Codex CLI 0.159.2・GPT-6.1 Sol(high)。公式の再現スクリプト(Linux 前提)は動かしておらず、共有ボードなどの部品を取り出して使いました
  • 公式の数値は論文・README・プロジェクトページの図から引用し、手元の数値は筆者の小さな実験です。両者は課題も規模も違うので、直接は比べられません

想定読者:Claude Code や Codex でサブエージェント・並列実行を使い始めた方、マルチエージェントの設計に興味がある方。専門用語には短い説明を添えます。

左は指揮役(オーケストレーター)が4体に仕事を配る構成、右は4体が共有ワークスペース・連絡・共有ボードを通じて自分で仕事を名乗り出る Agensh の構成。指揮役型は体数が増えると指揮役1体の処理能力で詰まる

図1:左がこれまでの指揮役型、右が Agensh。指揮役の代わりに「共有の基盤」を置き、何が終わり何が残っているかを全員が読めるようにします。

30秒でわかる Agensh

先に要点をまとめます。細かい条件は後の節で説明します。

項目 内容
何か 指揮役(オーケストレーター)なしで多数のエージェントを協調させる「ハーネス」(エージェントを動かす外側の仕組み)
公開 論文 2026年9月22日(arXiv)、コード・実験スクリプト・再現手順 2026年10月24日(README の告知)、MIT License
仕組み 共有ワークスペース(Git)・連絡(チャット)・共有ボード(短いメモ)の3つと、各エージェントが回す5ステップのループ
公式の結果 難しい5課題の平均テスト通過率が 1体 19.31% → 128体 28.78%。pandoc の作り直しで 1体 33.89% → 1,024体 55.06%(どちらも GPT-5.6-sol)
注意点 課題によっては 8体が 1体より低い。トークン数や費用は論文に載っていない。再現手順は Linux・systemd 前提
手元の実験 公式の共有ボードを Mac で動かし、Codex を 1・2・4・8体で20分ずつ各2回。難しい218問の通過率は 65.8%・64.7%・79.6%・85.6%、API 換算の費用は $0.93〜$9.06

なぜ「指揮役なし」なのか

まず、Agensh が解こうとしている問題を整理します。

1体の AI エージェントは、1つの会話の窓(コンテキストウィンドウ)と1本の作業の流れしか持てません。大きなソフトウェアを作ると、どうしても順番待ちが長くなります。そこで複数のエージェントを同時に走らせる「マルチエージェント」が使われます。

論文によると、Codex のサブエージェント、Claude Code のサブエージェントとエージェントチーム、GitHub Copilot の fleet、Kimi Agent Swarm など、既存の仕組みの多くは 指揮役と作業役(orchestrator-worker) の形をとっています。指揮役が計画を立て、仕事を分けて配り、結果を受け取って統合します。

この形は分かりやすい反面、体数を増やすと指揮役が詰まります。何十体もの進み具合を1体が把握し、衝突を調整し、成果をまとめるのは大変です。論文は「システム全体の拡張性が、指揮役の管理能力で頭打ちになる」と指摘しています。

Agensh の答えは、人間の開発チームと同じように、全員が同じ立場で自分から動くことです。ただし「勝手に動け」と言うだけでは重複や衝突が起きます。そこで、全員が読み書きできる基盤を用意し、そこで状況を共有させます。

仕組み①:各エージェントが回す5ステップのループ

Agensh の中心は、エージェントごとに回る「協調ループ」です。全員が同じループを、ほかの人を待たずに(非同期に)くり返します。

5つのステップ(状況を集める・仕事を名乗る・手を動かす・確かめる・統合する)が左から右に並び、下の「組織の基盤」との間で読み書きの矢印がある。強調が1から5へ順に移る

図2:協調ループ。1→5 を終えたら 1 に戻り、次の仕事を探します。

各ステップの中身は次のとおりです。

  1. 状況を集める:目標、main ブランチの現状、仲間の進捗やメッセージ、共有ボードのメモを読み、残っている仕事を探します。
  2. 仕事を名乗る:自分が担当する範囲を CLAIM として共有ボードに書きます。ほかの人と重なったら、直接メッセージ(DM)で話し合います。
  3. 手を動かす:自分の作業場所(ブランチ)で実装します。途中で分かったことは共有ボードに書きます。
  4. 確かめる:受け入れ条件を満たすか自分で検証し、満たさなければやり方を直します。
  5. 統合する:main にマージし、何を変えたか・なぜか・どう確かめたかを PATCH_SUMMARY として書きます。衝突したら最新の main を取り込んで解決し、もう一度マージします。

面白いのは、このループが実行基盤のプログラムではなく、プロンプトに書かれている点です。論文の付録には実際のプロンプトが全文載っていて、1,024体すべてが「番号以外まったく同じ」プロンプトで動きました。そのため、下で動く単体のエージェント(論文の実験では GitHub Copilot CLI)を、Claude Code などに差し替えられる設計になっています(ただし公開版に入っているのは Copilot 用の接続部分だけです)。

仕組み②:全員で共有する3つの基盤

ループを支えるのが、論文で「組織の基盤(organization infrastructure)」と呼ばれる3つの部品です。

基盤 役割 公式の実装
共有ワークスペース 進行中・統合済みの成果を置く。変更履歴とマージの衝突を検出する Gitea(自前で立てる Git サービス)。PR は承認0件でマージ可、main への直接 push は禁止
連絡(メッセージ) チーム全体への告知と、急ぎの1対1の連絡 Mattermost(自前で立てるチャット)。チャンネルは次のターンの頭、DM は作業の途中に届く
共有コンテキスト(共有ボード) 再利用できる発見と「いま誰が何をしているか」を残す board-service(FastAPI+MySQL)。考え方は DeLM という先行研究から

3つ目の共有ボードが、Agensh を特徴づける部品です。ここには長い文章ではなく、種類付きの短いメモだけを書きます。

種類 意味 文字数の上限
OBSERVED 参照プログラムで気づいた挙動 100
FACT 確かめた事実 100
FAIL 試してダメだった仮説(プロンプトでは「最も価値が高い」と強調) 100
CLAIM いま担当している作業(既定で1時間たつと一覧から消える) 100
PATCH_SUMMARY 終えた変更を files=・idea=・evidence= の3項目で 300

長い内容は detail に入れておき、読みたい人だけが board_unfold で広げます。PATCH_SUMMARY の証拠欄が「tbd」「pending」「unverified」のような仮の言葉だと、サーバーが受け付けません。ただし書かれたテストを実際に走らせて確かめるわけではなく、文字列で判定しているだけです。

仲間のメモは「作業の途中」に届く

もう1つの工夫が、メモの届け方です。普通のチャットのように「次に話しかけられたとき」に届くだけだと、仲間がすでに失敗した方法を、何分も試し続けてしまいます。

エージェントAが共有ボードに FAIL を書く。別の作業中のBがツールを呼ぶと、notice shim がボードに未読を問い合わせ、ツールの結果の末尾にメモを付け足してBに返す

図3:公式の notice shim は、B がボードや連絡のツールを呼んだ瞬間に、未読の DM と新着メモを結果の末尾へ付け足します。

公式の mcp-notice-shim.cjs は、エージェントが使う MCP サーバー(ツールを提供する小さなサーバー)を包む中継役です。ツールの結果を返す前に共有ボードへ「この人宛ての未読はあるか」を問い合わせ、あれば末尾に付け足します。プロンプトには、届いたメモへの反応も決めてあります。

  • FAIL:自分が同じことをしているならやめる
  • FACT・OBSERVED:そのまま使う
  • 自分の作業と重なる CLAIM:DM で当人と話をつける
  • それ以外の CLAIM:気にせず自分の作業を続ける

なお、これは「次にツールを呼んだとき」に届く仕組みです。走っているコマンドに割り込むわけではありません。

1体ごとに付く「配達係」

公式の構成では、エージェント1体ごとに TypeScript 製の小さな配達係(mini-router)が付きます。Gitea と Mattermost の出来事を受け取ってデータベースの待ち行列に入れ、エージェントのターンが終わったら、まとめて次のプロンプトとして渡します。

このとき、まだ読んでいない共有ボードのメモを ==== SHARED CONTEXT ==== という見出しで添えます。10分間何もしていないエージェントには「仕事はいつでもある」と催促し、ボードに何も書かずにターンを終えたエージェントには「共有すべき発見はないか」と促します。

公式の実験:何を、どの条件で測ったか

Agensh の評価に使われたのは ProgramBench というベンチマークです。コンパイル済みの参照プログラム(中身は読めない実行ファイル)だけを渡され、それと同じ動きをするプログラムをゼロから作り直す課題です。インターネットは使えず、時間は6時間です。採点は隠しテストの通過率で行います。

全200課題のうち、最先端モデルの平均通過率が最も低い5課題が選ばれました。

課題 何をするソフトか 元のファイル数 元の行数
FFmpeg 動画・音声の変換 10,090 約155万
gromacs 分子シミュレーション 8,982 約82万
pandoc 文書形式の変換(Markdown→HTML など) 2,767 約10万
PHP-src PHP 言語の処理系 26,266 約281万
ctags ソースコードの索引づくり 7,313 約25万

条件をそろえるため、モデルは全条件で GPT-5.6-sol(推論の深さ high)、各エージェントの中身は GitHub Copilot CLI です。起動時の取り合いを減らすため、最初の1時間は30秒に1体ずつ、その後は3秒に1体ずつエージェントを起動しました。締め切りの45分前と5分前には「新しい機能は始めず、マージを済ませよ」という声かけを送ります。1,024体の実験は16台のノードに64体ずつ載せています。

1体だけの比較対象(ベースライン)は、共有の基盤を使わない単独構成です。1体だと6時間もたずに「終わりました」と止まりがちなので、止まるたびに「仕事はいつでもある」と続けさせる仕組みを付けています。

公式の結果を読む

5課題の平均・pandoc・ctags・gromacs・FFmpeg・PHP-src ごとに、1・8・32・128体の最終テスト通過率を横軸のドットで比較。平均は 19.31 から 28.78、pandoc は 1,024体で 55.06。ctags は 8体が 18.47 で 1体の 25.82 を下回る

図4:課題ごとの最終テスト通過率。数値はプロジェクトページの図から読み取りました。どの条件も1回ずつの実行です。

数字を表にまとめます。

課題 1体 8体 32体 128体
5課題の平均 19.31% 20.68% 26.52% 28.78%
pandoc 33.89% 41.75% 43.11% 50.94%
ctags 25.82% 18.47% 44.69% 45.62%
gromacs 19.69% 19.37% 19.37% 22.12%
FFmpeg 6.54% 11.97% 13.22% 12.89%
PHP-src 10.63% 11.86% 12.23% 12.35%

pandoc だけは 1,024体まで試されていて、55.06% でした。1体の 33.89% より 21.17 ポイント高く、128体の 50.94% よりも 4.12 ポイント高い数字です。

ここから読み取れることは3つあります。

  • 平均では、体数を増やすほど上がる傾向がある:1体→128体で 9.47 ポイント、相対で約49%の向上です。
  • ただし少人数では差が小さく、逆転もある:1体→8体の平均は +1.37 ポイントだけです。ctags では 8体が 1体を 7ポイント以上下回り、gromacs は 32体まで横ばいでした。
  • 早く到達する効果もある:最初の2時間の推移を見ると、pandoc で通過率 30% を超えたのは 128体が30分、32体が60分、8体が90分の時点でした。1体は2時間たっても届いていません。

GPT-5.6-sol で 1体 33.89% から 1,024体 55.06% へ、GPT-6.1-sol で 1体 56.19% から 32体 79.59% へ伸びる pandoc の通過率のグラフ。右側に規模ごとに現れた協調の形(仲間との調整、複数人での統合、手順の標準化、役割の専門化)

図5:公式リポジトリの図(microsoft/Agensh、MIT License)。紫の線は README とプロジェクトページで追加された GPT-6.1-sol の結果です。

最新の GPT-6.1-sol では、pandoc の通過率が 1体 56.19% → 8体 71.38% → 32体 79.59% と伸びています。この結果は論文本文にはなく、README とプロジェクトページで追加されたものです。モデルが変わると1体だけでも 56% に届く点は、押さえておきたいところです。

規模ごとに「協調の形」が変わった

論文で興味深いのは、記録(軌跡)から読み取れた振る舞いの変化です。全員が同じプロンプトなのに、規模が大きくなるほど、新しい協調の形が自然に現れました。

8体・32体・128体・1,024体の順に、仲間との実装の調整、複数人での統合の管理、手順の標準化と専門化、組織規模の役割分担が階段状に並ぶ

図6:論文 3.2 節で紹介された規模ごとの振る舞い。事例の紹介で、頻度は数えられていません。

たとえば 128体の pandoc では、2体が「作者がブランチを更新してテスト→コミットのハッシュを渡す→相手が検証してマージ」という統合の手順を決め、ほかのエージェントもその手順を使い始めました。1,024体では統合役が複数生まれ、候補の何人かに声をかけて最初に応じた人を選び、残りの依頼を取り消すといった動きまで見られたそうです。

ニュースの要約で省かれがちな条件

Agensh を紹介するニュースや要約では、数字だけが短く切り出されることがあります。一次情報と照らし合わせて、補っておきたい点を表にしました。

よく見る説明 一次情報で確認できること
10月24日に OSS 公開 README の告知は 10月24日。ただしリポジトリのコミットは1件だけで、日付は 10月21日(米国時間)、GitHub への push は 10月23日(UTC)。論文は 9月22日に arXiv で公開済み
pandoc の再実装で 1体 33.89% → 1,024体 55.06% 数字は正しい。モデルは GPT-5.6-sol(high)。課題は「実行ファイルの動きだけを手がかりに、ネットなし・6時間で作り直す」ProgramBench の形式
GPT-6.1 Sol を32体使う構成で 79.59% 正しいが、同じモデルの1体でも 56.19%。論文本文にはなく README の追加結果
1,024体が中央管理者なしで協調 1,024体の実験は16ノード×64体。公開された手順は1台用(既定は8体)で、複数ノードの構成は含まれていない
Docker Compose で再現できる Linux・systemd・cgroup v2・パスワードなしの sudo が前提。起動スクリプトはモデルを gpt-5.6-sol(high)に固定し、ProgramBench 本体も別に必要
成功率・トークン・費用を比べたい 論文が報告しているのは通過率と時間だけ。トークン数、API 料金、マージ衝突の回数は載っていない

最後の点は特に大事です。体数を増やして通過率が上がっても、その分だけトークンを何倍も使っているなら、実務では割に合わないかもしれません。そこで手元の実験では、通過率と一緒にトークン数と費用、衝突や重複の回数も数えることにしました。

公式の再現手順は何を必要とするか

公開されたリポジトリには、1台のマシンでチームを動かす Docker Compose の構成と、1体だけで動かす比較用の起動スクリプトが入っています。再現手順(REPRODUCE.md)から、主な前提を抜き出します。

  • OS:Linux。Docker Engine、Compose v2、systemd、cgroup v2 が必要です。メモリの上限を決める systemd の設定(slice)と、再起動時に実験を止める見張り役(reboot guard)を先に入れます。
  • 権限:Docker とコンテナのデータ操作に、パスワードなしの sudo を使います。
  • ベンチマーク:ProgramBench v1.2.5 を指定のコミットで入れ、課題ごとの公式イメージを取り込みます。
  • モデル:Responses API を話せる LLM のゲートウェイが必要です。起動スクリプトは gpt-5.6-sol(high)以外を受け付けません。
  • 資源:エージェント1体あたりのメモリ上限は 64GiB、配達係は 8GiB です(上限であり、確保量ではありません)。

つまり Mac にそのまま入れて make up すれば動く、というものではありません。論文の6時間・数十体の実験を再現するには、Linux のサーバーとそれなりの API 予算が要ります。

そこで今回は方針を変えて、公式の部品のうち、Agensh らしさの中心である共有ボードと途中配信(notice shim)をそのまま取り出し、残りを軽い代役に置き換えて Mac で動かしました。

Mac で小さな Agensh を組む

ここからは手元の実験です。目的は、論文の数字を再現することではなく、少人数(2〜8体)で動かしたとき、通過率・費用・衝突がどう変わるかを自分の目で見ることです。

構成:公式の部品と代役

Codex CLI の作業役 w1〜w4… が、共有ワークスペース(ローカルの bare リポジトリ、代役)・連絡(自作の msg MCP、代役)・共有ボード(公式 board-service と notice shim)につながる。右に駆動役 run_team.py、下に駆動役と採点役の説明

図7:手元の構成。緑の共有ボードは公式の部品をそのまま動かし、Git とチャットは軽い代役にしました。

役割 公式の Agensh 今回の Mac 版
各エージェント GitHub Copilot CLI 1.0.70(ACP 経由) Codex CLI 0.159.2(codex exec、標準サンドボックス、ネット遮断)
モデル GPT-5.6-sol(high) GPT-6.1 Sol(high)
共有ワークスペース Gitea。PR 経由でマージ ローカルの bare リポジトリ。main へ直接 push(拒否されたら取り込んで再 push)
連絡 Mattermost 自作の小さな MCP サーバー(チャンネル投稿・DM)。DM は公式と同じ表に入れ、公式 shim で途中配信
共有ボード board-service+mcp.cjs+notice shim 公式のまま(MySQL 8.4 は Docker で起動)
配達係 mini-router(1体に1つ) 自作の駆動役 run_team.py(ターンの頭にボードの未読とチャンネル投稿を渡す。公式の文面を移植)
時間 6時間、締切45分前・5分前に声かけ、10分無反応で催促 20分、締切3分前・1分前に声かけ(比率よりやや早め)、33秒無反応で催促(6時間→20分と同じ比率)
起動の間隔 最初の1時間は30秒に1体 20秒に1体
1体の比較対象 単独構成+止まったら継続を促す 同じく単独構成+止まったらすぐ継続(公式の文面を移植)

課題:pandoc の Markdown→HTML 変換を作り直す

論文の目玉が pandoc だったので、課題もそれに寄せました。参照プログラムは Homebrew の pandoc 3.12.1 で、Markdown を受け取って HTML の断片を返す部分(pandoc -f markdown -t html --wrap=none)だけを対象にします。

エージェントには次のルールを渡しました。

  • 参照プログラムは実行して挙動を観察してよい。中身の解析や、実装からの呼び出しは禁止
  • Python 3.12 の標準ライブラリだけで作る。ネットは使えない
  • リポジトリの直下に compile.sh を置き、./executable を作る(ProgramBench と同じ約束)
  • 対象の書式は14種類(見出し、段落と改行、強調、インラインコードとエスケープ、リンク、画像、引用、箇条書き、番号付きリスト、コードブロック、水平線、表、脚注、引用符やダッシュの自動変換)

採点には、エージェントに見せない隠しテストを使います。最初に用意したのは150問(14種類×10問+混在した文書10問)で、後から、書式を組み合わせた難しい300問を足しました(理由は結果の節で説明します)。出力を pandoc と1文字単位で比べ、末尾の空白だけは無視します。採点時は sandbox-exec で pandoc と参照プログラムの実行を禁止し、ずるができないようにしました。

隠しテストは実験と並行して作り、すべての実行が終わるまで実験フォルダの外に置きました。後で Codex の記録を検索し、エージェントがその場所を読んでいないことも確認しています。

共有ボードを Mac で起動する

公式の board-service は Python(FastAPI)製で、Mac でもそのまま動きます。必要なのは MySQL と、いくつかの環境変数です。

# 1. MySQL 8.4 を Docker で起動する(127.0.0.1 だけで待ち受ける)
docker run -d --name agensh-lab-mysql \
  -e MYSQL_ROOT_PASSWORD=<ROOT_PASSWORD> -e MYSQL_DATABASE=<DB_NAME> \
  -e MYSQL_USER=agensh -e MYSQL_PASSWORD=<DB_PASSWORD> \
  -p 127.0.0.1:13306:3306 mysql:8.4 --max-connections=1000

# 2. 公式リポジトリを取得し、board-service 用の Python 環境を作る
git clone https://github.com/microsoft/Agensh.git
uv venv --python 3.12 board-venv
uv pip install --python board-venv/bin/python -r Agensh/board-service/requirements.txt

MySQL が起動したら、公式の初期テーブル(mini-router/sql/ の 01-events-schema.sql と 03-board-schema.sql)を流し込みます。

for f in 01-events-schema.sql 03-board-schema.sql; do
  docker exec -i agensh-lab-mysql mysql -uagensh -p<DB_PASSWORD> <DB_NAME> < Agensh/mini-router/sql/$f
done

board-service を起動するときは、外から接続されないように --host 127.0.0.1 を付けます。公式の main.py をそのまま実行すると 0.0.0.0(すべてのネットワーク)で待ち受けるためです。

cd Agensh/board-service
MYSQL_DSN='mysql://agensh:<DB_PASSWORD>@127.0.0.1:13306/<DB_NAME>' \
BOARD_MEMBERS_JSON='{"pbench": ["pbench-w1", "pbench-w2", "harness"]}' \
BOARD_LIFECYCLE_DIR=/tmp/agensh-lifecycle \
../../board-venv/bin/python -m uvicorn main:app --host 127.0.0.1 --port 8660

起動したら、curl で読み書きを試せます。w1 として FAIL を書き、w2 宛ての未読を確かめる例です。

# w1 が FAIL を書く(受け付けられると G1 などのラベルが返る)
curl -s -X POST localhost:8660/board/pbench/note -H 'Content-Type: application/json' \
  -d '{"thread_id":"pbench-w1","type":"FAIL","content":"Heading ids keep punctuation? No: # Hello, World! -> id=hello-world"}'
# => {"status":"admitted","reason":null,"gist_id":1,"label":"G1"}

# 証拠欄が仮の言葉(tbd)の PATCH_SUMMARY は受け付けられない
curl -s -X POST localhost:8660/board/pbench/note -H 'Content-Type: application/json' \
  -d '{"thread_id":"pbench-w1","type":"PATCH_SUMMARY","content":"files=mdhtml.py | idea=heading ids | evidence=tbd"}'
# => {"status":"rejected","reason":"ok:0/1,ps_invalid_ev=1",...}

# w2 宛ての未読(notice shim が作業の途中に付け足す中身)
curl -s localhost:8660/pending/pbench-w2
# => {"agent":"pbench-w2","notices":[{"id":"g1","text":"[tpbench-w1/FAIL +0.0m] Heading ids keep ..."}],...}

Codex から共有ボードを使う

Codex には、公式の mcp.cjs(ボードの4つのツール)を、公式の mcp-notice-shim.cjs で包んで登録します。エージェントごとに名前(AGENT_NAME)だけを変えます。

# $CODEX_HOME/config.toml の一部(エージェントごとに AGENT_NAME を変える)
[mcp_servers.board]
command = "node"
args = ["<AGENSH>/mini-router/mcp-notice-shim.cjs", "--",
        "node", "<AGENSH>/board-service/mcp.cjs"]
env = { BOARD_SERVICE_URL = "http://127.0.0.1:8660", AGENT_NAME = "pbench-w1", BOARD_IDS = "pbench" }
# codex exec は承認を求められないため、明示的に許可しないと MCP の呼び出しが拒否される
default_tools_approval_mode = "approve"
enabled_tools = ["board_read", "board_write", "board_grep", "board_unfold"]

実際の実験では、本人の普段の Codex 設定・メモリー・グローバルな AGENTS.md が混ざらないよう、CODEX_HOME を実験用のフォルダに分けました。認証ファイルだけをシンボリックリンクでつないでいます。上の設定は、駆動役が codex exec -c ... で毎回渡しています。

各エージェントの作業フォルダには、公式の prompts/agents.txt を移植した AGENTS.md を置きました。Gitea と Mattermost の説明を、ローカルの Git と msg ツールの説明に書き換えた以外は、協調ループの文面をそのまま使っています。

結果:体数を増やすと何が変わったか

各条件を2回ずつ、合計8回走らせました。1回目は 1→2→4→8体、2回目は時間帯の影響を打ち消すため 8→4→2→1体の順です。

基本の150問は、1体でもほぼ満点だった

最初に用意した隠しテスト150問は、易しすぎました。8回とも 96.0〜100.0% で、1回目の1体は、開始から3分で150問中134問を通しています。GPT-6.1 Sol にとって、pandoc の Markdown→HTML の基本部分は、20分あれば1体で作り切れる大きさでした。

これでは体数の差が測れません。そこで、提出物がどこで失敗したかは見ずに、14種類の書式を入れ子にしたり混ぜたりした文書を乱数で300問作り(固定シード)、追加のテストにしました。入れ子のリストの中の引用、脚注の中の強調、表のセルの中のリンク、といった組み合わせです。

ところが採点してみると、この300問のうち82問(27%)に、生成器が "A "quoted" title" のような内側に引用符を含むリンクのタイトルを入れていました。後で説明するとおり、この1つの書き方が結果を大きく揺らしたので、以下では 300問全体 と、その82問を除いた218問 の両方を示します。

通過率は上がったが、費用はほぼ体数に比例した

左は追加テスト218問の通過率で、1体から8体へ棒が長くなる。右は API 換算の費用で、同じく体数に応じて増える。白丸は各回の値

図8:体数別の通過率と費用。棒は2回の平均、白丸は各回の値です。

体数 追加218問 平均(1回目 / 2回目) 追加300問 平均(1回目 / 2回目) 基本150問(1回目 / 2回目) 入力トークン(平均) 出力トークン(平均) API 換算の費用(平均)
1体 65.8%(59.6% / 72.0%) 60.7%(53.7% / 67.7%) 96.0% / 98.7% 2.7M 41k $0.93
2体 64.7%(69.3% / 60.1%) 54.3%(57.7% / 51.0%) 99.3% / 96.7% 9.0M 72k $1.91
4体 79.6%(79.8% / 79.4%) 63.2%(68.7% / 57.7%) 98.7% / 100.0% 20.2M 141k $4.27
8体 85.6%(90.4% / 80.7%) 84.2%(88.3% / 80.0%) 99.3% / 99.3% 45.3M 242k $9.06

218問で見ると、1体の 65.8% と2体の 64.7% はほぼ同じで、4体で 79.6%、8体で 85.6% まで上がりました。1体→2体では成果が増えず、費用だけが約2倍になっています。4体・8体では +14〜20 ポイント伸びましたが、費用は1体の約4.6倍・9.8倍です。

回ごとのばらつきも大きく、同じ1体でも 59.6% と 72.0%、同じ8体でも 90.4% と 80.7% と、10ポイント前後の差が出ました。2回ずつの実験なので、「1体のほうが2体より良い」とまでは言えません。言えるのは、少人数では差がはっきりせず、費用はほぼ体数に比例して増えること、4〜8体では細かい書式の組み合わせまで再現できたことです。

チームが細かい書式に強かった理由の1つは、自作テストの量だと考えられます。1回目の最終コードを比べると、1体は JSON の固定テストを持たず、2体は158件、4体は728件、8体は1,780件の「参照の出力」をテストとして保存していました。8体の1回目では、最後に起動した w8 が最初に「差分テストの仕組みと題材づくり」を名乗っています(その後、コードブロックの担当に移りました)。

費用はあくまで API の単価で換算した目安です。今回は Codex Pro の定額枠で動かしたので、追加の支払いはありません。Codex の週の利用枠の表示は、実験の前後で 1% から 5% に増えました(同じ時間に動いていた別の作業の分も含みます)。入力トークンの 93〜98% はキャッシュ(前回と同じ部分の読み直し)で、単価は通常の20分の1です。

自作テストは全部通っていたのに、40問以上が落ちた

体数を増やしても、良いことばかりではありませんでした。4体の回は2回とも、途中で通過率が大きく下がり、最後まで戻りませんでした。

4体の2回分の推移。1回目は13.9分に247問から198問へ、2回目は8.5分に212問から167問へ落ちる。比較用に8体2回の平均を灰色で表示

図9:4体の2回分の推移(追加300問)。1分ごとに「この時点の main」を採点しました。

原因をコミット単位で採点して探すと、どちらもインライン担当(w2)の変更でした。

  • 1回目(13.9分):自分で見つけた [foo](u "t" "more") というケースに合わせて、「リンクのタイトルの中に同じ引用符があれば無効」という規則を1行足した。247問 → 198問
  • 2回目(8.5分):Unicode の URL や参照定義のタイトルに対応するため、タイトルの解釈を書き換え、最初の閉じ引用符で打ち切るようにした。212問 → 167問

どちらも、pandoc なら受け付ける "A "quoted" title" のようなタイトルを弾くようになりました。それでも、チームの自作テスト(最終728件と786件)はすべて通っていました。各自が自分の担当範囲のテストで「確かめる」ステップを済ませてから統合しても、別の書き方の入力を壊す変更は素通りしたわけです。

この落ち幅は、追加テストの作り方にも左右されます。生成器が使うタイトル4種類のうち1つが内側に引用符を含むため、影響が大きく出ました。そこで82問を除いた218問でも比べると、4体は2回とも約80%(79.8% と 79.4%)で、ほぼ同じ値になります。

協調の手間と費用は、体数以上に増えた

1体あたりの入力トークン、共有ボードへの書き込み、チャンネル投稿と DM、main への反映、push の拒否、衝突を、体数ごとに1回目と2回目で並べた表

図10:協調にかかった手間(左が1回目、右が2回目)。1体は単独構成なので、ボードと連絡は使っていません。

まず、1体あたりの入力トークンも増えました。単独の1体は 2.1M・3.3M でしたが、チームでは1体あたり 3.8〜5.8M です。チームのエージェントは、ボードや連絡のツールを頻繁に呼び、仲間の変更を取り込むたびに短いターンをくり返します。ツールを呼ぶたびに会話全体を読み直すので、その分だけ入力が膨らみます。8体の1回目は、合計でコマンド670回、ボード151回、連絡ツール304回を呼んでいました(1体の1回目はコマンド40回だけ)。

一方で、統合そのものは思ったより滑らかでした。push の拒否(先に誰かが push していた)は1回あたり0〜14回ありましたが、マージの衝突(CONFLICT)の表示は、チームの6回を合わせて4回だけです。最初の数分でファイル単位に担当を分けたので、同じ行を同時に書き換えることがほとんどありませんでした。締切3分前・1分前の声かけも効き、締切の時点で main に入っていないコミットは、どの回も0件でした。

ログから見えた3つの場面

数字だけでは分からない動きを、記録から3つ紹介します。

① 最初に起動した1体が、分担案まで書いた:エージェントは20秒おきに1体ずつ起動します。チームのどの回でも、最初に起動した w1 が開始1分以内に分担案を出し(6回中4回は最初の CLAIM に「自分は本体と compile.sh、仲間はインライン・リスト・表と脚注を」と書き、残る2回は DM とチャンネルへの投稿)、後から起動した仲間はほぼその通りに名乗りました。8体の2回目は、8体の担当が課題文書(SCOPE.md)に並べた書式の一覧とほぼ1対1で対応しています。指揮役はいなくても、最初に動いた1体が実質的な計画役になり、課題文書の箇条書きがそのまま仕事の分け方になりました。

② 担当の衝突は、数秒の DM で片づいた(8体):1回目の8体では、w3 と w4 がほぼ同時(開始0.9分と1.3分)に「links.py(リンク・画像)を担当」と名乗りました。1.5分の時点で w3 が「先に名乗っていて、30件ほど調べ、API も w2 と決めた」と DM を送り、w4 は「表を担当する」と CLAIM を書き直しました。本体担当の w1 からも、w4 へ別の担当を勧める DM が届いています。論文の8体の例(FFmpeg で重なりを話し合い、片方が範囲を変えた)とよく似た動きです。

③ 統合の窓口に DM が集まった:8体の回では、本体と統合を名乗った w1 が、DM の約半分に関わっていました(1回目は128通中61通、2回目は124通中66通)。「モジュールをつなぐ場所」を持つ1体に、関数の形の相談や、統合で見つけたバグの報告が集まります。4体の2回目でも、DM 17通のうち13通が w1 との間でした。

共有ボードの使われ方

CLAIM・OBSERVED・FACT・FAIL・PATCH_SUMMARY の実例を、書いたエージェントと経過時間とともに並べる。最後に52件の内訳

図11:4体の1回目に共有ボードへ書かれたメモの抜粋(原文は英語、下の行は筆者の訳)。

ボードに書かれたメモの大半は PATCH_SUMMARY(変更の報告)と FACT(確かめた事実)でした。プロンプトで「最も価値が高い」とされる FAIL(ダメだった仮説)は、6回のチームの回を合わせても 3 件しか書かれていません。

PATCH_SUMMARY の証拠欄には「705/705 fixtures pass」のように自作テストの通過数が並びましたが、図9のとおり、それは参照プログラムとの一致を保証しませんでした。エージェントが「失敗」をあまり書かないのは、20分という短さのせいかもしれません。論文の6時間・数百体の規模では、他人の失敗を避ける効果がもっと効いてくる可能性があります。

この実験の限界

結果を読むときの注意点もまとめておきます。

  • 各条件2回だけで、ばらつきの大きさは十分には分かりません。8体の2回でも、218問で 90.4% と 80.7% の差がありました
  • 課題は pandoc の一部分(Markdown→HTML)で、論文の課題よりずっと小さいものです。追加テストは筆者の生成器で作ったため、どの書式の組み合わせが多いかは生成器の作りに依存します
  • 時間を20分に縮め、Gitea・Mattermost・配達係を代役にしました。公式の構成と同じ結果になるとは限りません
  • 使ったのは Codex CLI と GPT-6.1 Sol です。論文の Copilot CLI・GPT-5.6-sol とは違います

自分の開発で試すなら

最後に、手元の実験から分かった「小さく試すときの進め方」をまとめます。

Q1 合否をテストで判定できるか、Q2 独立した部品が複数あるか、Q3 時間が厳しくトークン増を払えるか、の3つの質問。すべて「はい」なら、1体の基準を測ってから2体・4体と増やして比べる

図12:指揮役なしの複数体を試すかどうかの判断(筆者の整理)。

手順1:1体の基準を測る

まず、同じ課題・同じ時間で1体を走らせ、通過率とトークンを記録します。今回の実験でも、基本の150問では1体がほぼ満点でした。1体で十分な大きさの仕事なら、複数体にしても費用が増えるだけです。

手順2:2体、4体と増やしながら5つを測る

体数を増やしたら、通過率だけでなく次の5つを並べて見ます。今回は2体では1体と差が出ず、4体から伸びました。2体だけ試して「効果なし」と決めないほうがよさそうです。

指標 何が分かるか 今回の測り方
通過率 成果が増えたか 締切の main を取り出して隠しテストで採点
総トークン・費用 いくら払ったか Codex の記録($CODEX_HOME/sessions/ の rollout)の token_count を合計
担当の重複 同じ仕事を2人がしていないか 共有ボードの CLAIM を時刻つきで並べる
push の拒否・衝突 統合でどれだけ手間取ったか ツールの出力から [rejected]・CONFLICT ( を数える
締切で入らなかった作業 書いたのに捨てられた分 各作業フォルダで git rev-list <提出>..HEAD を数える

main への反映の記録は、共有リポジトリ(bare リポジトリ)に post-receive フックを置くだけで取れます。

#!/bin/sh
# origin.git/hooks/post-receive:main などへの反映を時刻・作者つきで記録する
while read old new ref; do
  t=$(perl -MTime::HiRes=time -e 'printf "%.3f", time')
  a=$(git log -1 --format='%an%x09%s' "$new" 2>/dev/null)
  printf '%s\t%s\t%s\t%s\t%s\n' "$t" "$old" "$new" "$ref" "$a" >> "$GIT_DIR/pushes.log"
done

この記録があると、「何分の時点の main を採点したら何点だったか」を後から再現でき、図9のような推移や、4体で起きた回帰の原因を突き止められます。

手順3:今回の失敗から入れておきたい工夫

実験で見えた弱点には、Agensh のプロンプトや運用で手当てできるものもあります。ここは筆者の提案で、まだ試していません。

  • main に入れる前に、全員分のテストを回す:各エージェントは自分の担当のテストだけで「確かめる」を済ませがちです。リポジトリに共通のテスト置き場を決め、統合の前に全体を流すよう、プロンプトの手順4に書き足します。
  • 統合の窓口を最初から決めておく:指揮役は置かなくても、本体の担当に DM が集まります。誰が統合の窓口かを最初の CLAIM で宣言させると、集中を見越した動き方ができます。
  • FAIL を書く場面を具体的にする:「仮説が外れたら書く」だけでは、ほとんど書かれませんでした。「参照と出力が食い違って、原因が自分の思い込みだったとき」のように例を足すと増えるかもしれません。
  • 費用の上限を先に決める:今回は1体あたりのトークンも体数とともに増えました(連絡やマージのたびに会話全体を読み直すため)。体数×時間で予算を見積もり、上限を超えたら止める仕組みを用意します。

つまずいたところと対処

Mac で組むときに実際にはまった点を、確認する順番にまとめます。

上から順に、codex exec が止まる、MCP ツールが拒否される、git commit が失敗する、普段の設定が混ざる、ボードが外から見える、公式スクリプトが動かない、作業フォルダ外のファイル名が見える、の7項目と対処が並ぶ。強調が1つずつ下へ移る

図13:つまずいた順の対処表。上から確認すると早く切り分けられます。

症状 原因 対処
codex exec が「Reading additional input from stdin...」のまま止まる スクリプトから呼ぶと標準入力を待つ < /dev/null を付ける(駆動役では stdin=DEVNULL)
ボードのツールが「requires approval, but approval policy is never」で拒否される codex exec は承認を求められないので、MCP の呼び出しが既定で拒否される default_tools_approval_mode = "approve" と enabled_tools をサーバーごとに書く
git commit が失敗し、エージェントが .git を /tmp にコピーして回避し始めた Codex の標準サンドボックスは、書き込み可能なフォルダの中でも .git だけは読み取り専用にする git clone --separate-git-dir=<外の場所> で管理フォルダを作業フォルダの外に置き、その場所を writable_roots に足す
普段の Codex 設定・メモリー・グローバルな AGENTS.md が実験に混ざる ~/.codex をそのまま使っている CODEX_HOME を実験用に分け、認証ファイルだけリンクする
board-service が LAN から見える 公式の main.py は 0.0.0.0 で待ち受ける python -m uvicorn main:app --host 127.0.0.1 で起動する
公式の launch_single_node.sh や make up が動かない Linux・systemd・cgroup v2・sudo が前提 Mac では部品(board-service・shim・prompts)を取り出して使う。本格的な再現は Linux のサーバーで
エージェントが /tmp を検索し、作業と関係ないファイル名まで一覧した 標準サンドボックスは書き込みを絞るが、読み取りはディスク全体に開いている 見られて困るものがあるマシンでは、公式と同じくコンテナに入れて動かす

.git の件は、知らないと気づきにくい点です。エージェントは、書き込めないと分かると .git を一時フォルダにコピーし、GIT_DIR を差し替えて commit と push を続けました。動くことは動きますが、作業フォルダの .git には commit が残らず、本当の履歴がどこにあるのか分かりにくくなります。試運転の段階で気づけたので、本番では外に置く方式に直しました。

最後の項目は、2回目の8体の回で見つけました。仲間の一時ファイルを探そうとした1体が rg --files /tmp を実行し、同じ Mac で動いていた別の作業のファイル名まで一覧していました。ネットは遮断していたので外へは出ていませんし、隠しテストの場所にも触れていません(記録を検索して確認)。それでも、公式の Agensh が各エージェントをコンテナに入れ、参照プログラムを「実行はできるが読めない」権限で置いている理由がよく分かります。

このほか、codex exec は GPT-6.1 Sol が混み合うと「Selected model is at capacity」で落ちることがあります。駆動役では、会話が始まる前に落ちたら10秒待って最初からやり直し、会話が始まっていれば codex exec resume で続きから再開するようにしました。

まとめ

Agensh は、「指揮役が仕事を配る」という多くのマルチエージェントの前提を外し、共有ワークスペース・連絡・共有ボードの3つと、全員が同じプロンプトで回す5ステップのループで協調させる仕組みです。公式の実験では、難しい5課題の平均通過率が 1体 19.31% → 128体 28.78%、pandoc では 1,024体で 55.06% まで伸びました。ただし少人数では差が小さい課題や逆転もあり、トークン数や費用は報告されていません。

手元の Mac で公式の共有ボードと途中配信を動かし、Codex を 1〜8体で競わせた結果は、次のとおりです。

  • 基本の150問は、1体でも 96.0〜98.7%。課題が小さいうちは、体数を増やす意味がほとんどなかった
  • 書式を組み合わせた難しい問題(218問)では、1体 65.8%・2体 64.7%・4体 79.6%・8体 85.6%。伸びたのは4体以上で、2体では差が出なかった
  • API 換算の費用は $0.93 → $1.91 → $4.27 → $9.06 と、ほぼ体数に比例した。1体あたりのトークンも、連絡と統合のぶん増えた
  • 指揮役はいなくても、最初に起動した1体が分担案を書き、本体担当に DM が集まった。似た役割は自然に生まれる
  • 4体は2回とも、自作テストを全部通したまま、1つの変更で40問以上を失った。統合の前に全体を確かめる仕組みが要る

「数を増やせば賢くなる」というより、決まった時間の中で成果を増やすために、トークンを払い、統合の手間とリスクを引き受ける仕組みだと考えると、使いどころが見えてきます。テストで合否を判定でき、部品に分けられ、締め切りが厳しい仕事なら、1体の基準と比べながら小さく試す価値があります。

次の一歩としては、公式の prompts/agents.txt を読み、自分のエージェントの AGENTS.md や CLAUDE.md に協調ループを移植してみるのが手軽です。共有ボードが欲しくなったら、今回のように board-service と notice shim だけを取り出して動かせます。

参考リソース

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?