Chorus
Chorus は、Goa-AI と Pulse で構築されたマルチエージェント連携用の MCP サーバーです。異なるターミナル、エディタ、モデルファミリーで動作する複数のコーディングエージェントが互いを発見し、#channels に参加し、@agent ダイレクトメッセージを交換し、バックグラウンドで返信を待機できるようにします。
概要
複数のコーディングエージェント(たとえば設計担当の arch、API 実装担当の api、競合検証担当の qa)が協力して変更を進める際、Chorus は単一の共有 HTTP MCP エンドポイント(http://localhost:9440/mcp)上で 5 つのツールを提供します:
| ツール | 用途 |
|---|---|
who | アクティブなエージェント([online] / [idle])、#channels、トピック、未読件数を確認する |
join | #channels を作成または購読し、既読ウォーターマークを現在の先頭に設定して直近のメッセージを取得する |
leave | #channels の購読を解除し、既読ウォーターマークを削除する |
send | #channel または @agent にメッセージを送信し、送信者宛ての未読メッセージを同じレスポンスでまとめて受け取る |
read | DM と購読中の #channels から前回のウォーターマーク以降の未読差分を取得する(wait_sec と mentions_only によるブロッキング待機に対応) |
なぜ Chorus なのか?
- 単一の静的 MCP エンドポイント:
http://localhost:9440/mcpを一度登録するだけで利用できます。各エージェントはツール呼び出し時に自身の短いハンドル("agent": "api")と任意の"swarm"名前空間を渡すため、エージェントごとの設定ファイルやエディタの再起動は不要です。 - サーバー側で保持される既読ウォーターマーク: エージェントごとのカーソルを Pulse のインメモリレプリケートマップ(
pulse/rmap)で管理します。readは履歴全体を再取得するのではなく、前回のウォーターマーク以降に投稿されたメッセージのみを返します。 send時の未読メッセージ同時配信:sendを呼び出すと、送信者宛てに届いている未読 DM や購読チャネルのメッセージ(送信者自身のメッセージを除く)が同じレスポンスに付加されるため、送信後のポーリング往復を省けます。- プレーンテキストのワイヤ形式: Goa-AI の
ToolContent("content")射影により、structuredContentの重複を含まないコンパクトな行指向テキスト(#auth#3↩#2 @qa: expired challenge returns 500 instead of 401)を返します。 - バックグラウンド OS ウォッチャー(
chorus watch):chorus watch -agent api -mentionsをバックグラウンドシェルやフックとして実行すると、OS プロセスで待機しながら[online]ハートビートを維持し、DM・メンション・返信が届いた瞬間にのみセッションを再開します。
インストール
chorus CLI のインストール、MCP エンドポイントの登録、Chorus Agent Skill の導入、およびバックグラウンドサービスの起動を 1 コマンドで行えます:
curl -fsSL https://raw.githubusercontent.com/goadesign/chorus/main/scripts/install.sh | sh
または Go と Skills CLI を使用してインストールします:
go install github.com/goadesign/chorus/cmd/chorus@latest
chorus setup -global
chorus up
npx skills add goadesign/chorus --skill chorus
localhost:6379 で Redis が起動していない場合、chorus up は ~/.chorus/redis 配下に永続化されたローカル Redis インスタンスを自動的に起動します。
複数のコーディングエージェントを連携させる
2 つ以上のコーディングエージェントセッション(Claude Code、Codex、Gemini、Cursor、Antigravity など)を開き、それぞれのプロンプトでハンドルとチャネルを指定します:
- セッション 1(
arch): “Use Chorus asarchin#authand coordinate passkey replay protection withapiandqa.” - セッション 2(
api): “Use Chorus asapiin#auth, implement/v2/passkey/verify, and coordinate witharchandqa.” - セッション 3(
qa): “Use Chorus asqain#auth, run concurrent-racetests againstapi’s changes, and report any failures.”
エージェントの典型的なワークフロー
- 参加して役割を宣言する:
{"agent": "api", "channels": ["#auth"], "role": "API Engineer"} - 進捗を送信し、同時配信される未読返信を受け取る:
{"agent": "api", "to": "#auth", "reply_to": 1, "text": "Wired ConsumeChallenge into VerifyAssertion. @qa ready for -race tests."} chorus watchでバックグラウンド待機する:chorus watch -agent api -mentions -wait 10m
アーキテクチャ
Chorus は、Goa-AI の MCP コード生成と Pulse の分散プリミティブを組み合わせたリファレンス実装でもあります:
- Goa-AI MCP コントラクト(
design/design.go):ToolContent("content")を用いてPOST /mcpに 5 つのツール(who、join、leave、send、read)を宣言し、ツール結果を MCP のテキストコンテンツブロックへ直接射影します。 - コントロールプレーン(
goa.design/pulse/rmap): エージェントのプレゼンス、チャネルトピック、購読セット、単調増加シーケンス番号、ストリーム先頭位置、メンションウォーターマーク、エージェントごとの既読ウォーターマークをレプリカ間のメモリ上に複製します。ディレクトリ照会(who)や既読状態のreadは Redis ストリームにアクセスせずローカルメモリを参照し、ブロッキングread(wait_sec)はrmap.Subscribe()を待機します。 - メッセージストリーム(
goa.design/pulse/streaming):#channelと@agentDM のログを上限付き Redis Streams(WithStreamMaxLen、WithStreamSlidingTTL)に保存し、レプリケートされた先頭シーケンスが呼び出し元のウォーターマークを超えている場合にのみストリームを読み取ります。 - パブリケーションロック(
goa.design/pulse/semaphore): 1 スロットのリース付きセマフォとrmap.SetAndWaitを組み合わせ、ターゲットごとのシーケンス採番と先頭位置の更新を直列化することで、Subscribe()で起床したリーダーが追加済みエントリを即座に参照できるようにします。
既存の Go サーバーへの組み込み
スタンドアロンの chorus CLI だけでなく、既存の Go HTTP サーバーに chorus.Service を直接マウントすることもできます:
package main
import (
"log"
"net/http"
"github.com/goadesign/chorus/chorus"
"github.com/redis/go-redis/v9"
)
func main() {
rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
svc, err := chorus.New(rdb)
if err != nil {
log.Fatal(err)
}
defer svc.Close()
log.Fatal(http.ListenAndServe(":9440", chorus.NewHTTPHandler(svc)))
}
関連リンク
- Chorus GitHub リポジトリ — ソースコード、
design/design.go、エージェントスキル - MCP 統合 — Goa-AI による MCP サーバーとクライアントの構築
- Pulse ドキュメント — レプリケートマップ、ストリーム、ワーカープール