Claude Code の channels 機能で「Claude Code を」AI 社員にする
こんにちは、小笠原みつき(@yamitzky)です。
Claude Code で AI 社員を何人も並べて、Discord から動かす仕組みを作ったので共有します。
人間は Discord に書き込むだけで、AI 社員(エージェント)同士もお互いにメッセージを送り合いながら応答する、マルチエージェントな仕組みです。
マルチエージェントな Hermes Agent や OpenClaw を、Claude Code で再現した、と言った方が伝わりやすいかもしれません。

その正体は、Discord チャネルごとに、1つひとつが独立した Claude Code のセッション です。Claude Agent SDK などではなく、チャンネルごとに Claude Code そのものを動かしている、ということです。
全体を支えているのは、Claude Code の channels という機能です。
全体像
先に、やっていることの全体像を1枚の図で示します。
土台にあるのが Claude Code の channels という機能で、その上に Discord と claude-peers という2つの channel が乗っています。
人間は Discord 越しに話し、セッション同士は claude-peers 越しに話します。
受け手の Claude Code から見ると、どちらも同じ形のメッセージとして届きます。
ここから、土台の channels から順に見ていきます。
channels とは
channels は、ターミナルの外で起きたことを Claude Code のセッションに流し込む機能です(執筆時点では research preview で、Claude Code v2.1.80 以降が必要です)。例えば、Discord や Telegramなどで受け取ったメッセージを、Claude Code のセッションに push 型で流し込むことができます。
仕組みはシンプルで、1つの channel は1つの MCP サーバーです。
ふつうの MCP サーバーは Claude が呼び出すツールを生やしますが、channel はその逆で、サーバー側から Claude にイベントを push します。
MCP サーバーを channel にするのは、capability を1つ宣言するだけです。
const mcp = new Server(
{ name: 'webhook', version: '0.0.1' },
{
// このキーがあると Claude Code が channel として扱ってくれる
capabilities: { experimental: { 'claude/channel': {} } },
instructions: 'イベントは <channel source="webhook" ...> の形で届きます。',
},
)
あとはイベントが起きたときに notifications/claude/channel を投げると、Claude のセッション内にこういう形で割り込みます。
<channel source="webhook" severity="high" run_id="1234">
hello world
</channel>
自分で作った channel を試すときは、--dangerously-load-development-channels を付けて起動します。
claude --dangerously-load-development-channels server:webhook
いくつか、anthropics/claude-plugins-official に公式の実装も用意されています(現在は Telegram、Discord、iMessage のみが対応)。
2つの channel を組み合わせる
今回の仕組みは、この channels の上に2つの channel を載せただけです。
Discord(公式の channel)
人間の入口には Discord を使っています。(ただし後述するように、フォークしています)
Discord は公式プラグインに入っている双方向の channel で、ローカルで Discord の API をポーリングし、新しい発言を <channel> として Claude に届けます。
受付になる1つのセッションに、Discord の channel を載せて起動します。
claude --dangerously-skip-permissions \
--dangerously-load-development-channels \
server:discord-router server:claude-peers
人間が Discord に書き込むと、受付セッションにこう届きます。
<channel source="discord" chat_id="..." user="..." ts="...">
本文
</channel>
返信は reply ツールに chat_id を渡すだけです。
ちなみに channel は、送り主を allowlist で絞る作りになっています。
誰でも書き込める口をそのまま Claude に流すと prompt injection の経路になるので、ペアリングで許可した相手だけを通します。
claude-peers(OSS の channel)
セッション同士の会話には、louislva/claude-peers-mcp を channel として使っています。
これは localhost:7899 で動くブローカー1つを介して、同じマシンの Claude Code 同士を発見させ、メッセージを送り合わせるものです。
あるセッションが相手を一覧して send_message を呼ぶと、相手のコンテキストに同じ <channel> の形で届きます。
<channel source="claude-peers" from_id="..." from_cwd="channels/general">
今日のリマインダーは何件ある?
担当セッションへ振り分ける
Discord channel が届くのは受付セッション1つだけとしています。これは Discord への接続数を多くしすぎないためです。
そのうえで、公式の Discord channel をフォークし、担当セッションへ振り分ける処理を自分で足しました。
# ルーティング用
claude --dangerously-skip-permissions --dangerously-load-development-channels server:discord-router server:claude-peers
各セッションは、作業ディレクトリで識別します。Discord の chat_id から作業ディレクトリへの対応表を1枚の JSON に持たせ、その対応をたどって宛先を決めます。フォークした discord-router が claude-peers を使ってメッセージを分配します。
// channel-map.json
{
"661226294062612493": {
"name": "リマインダー", // Discord のチャンネル名
"category": "秘書室", // Discord のカテゴリ
"path": "/path/to/reminder" // Claude Code を動かすフォルダ
}
}
各セッションのディレクトリには CLAUDE.md を置いて、役割と固有ルールを書いておきます。
同じ Claude Code を起動しても、置き場所が違えば読み込む CLAUDE.md が違うので、別の社員として振る舞います。
社員の人格を起動引数ではなく、ファイルの置き場所で表しているわけです。
cd /path/to/channel/dir && claude --dangerously-skip-permissions --dangerously-load-development-channels server:claude-peers
実際の動き方
実際の流れを1つ見てみます。
人間が Discord の「一般」チャンネルに書き込みます。
<channel source="discord" chat_id="6612..." user="yamitzky">
このブログのドラフト書いて
受付セッションがこれを担当の作業ディレクトリへ解決して、claude-peers 経由で送ります。
担当セッションには、こう届きます。
<channel source="claude-peers" from_id="discord-router" ...>
[discord chat_id=6612... user=yamitzky]
このブログのドラフト書いて
実際の Discord の様子

内部の Claude Code の様子

メリット・デメリット
良くも悪くも、仕組みはただの Claude Code です。
良い点としては、
- Claude Code なので内部の仕組みがわかりやすい
- セッションやコンテキスト圧縮、モデル選択、CLAUDE.md、Agent Skill、MEMORY.md などの仕組みで動いていることがわかる
- Claude Code で使える機能は全部使える
- ultracode で実装したり、Web 検索したり
- 多分 Claude のサブスクリプションの中で動く
悪い点としては、
- 各セッションがフルの Claude Code プロセスなので重い
- AI 社員(Discord チャンネル)の数だけプロセスが立ち上がり、メモリを食う
- zellij 経由で Claude Code を動かしているため不安定なことがある
- 再起動すると (/resume しないと)コンテキストが揮発する
実際のスタートアップでもよく「◯人の壁」という言葉が言われますが、この仕組みも Claude Code のセッションのためのメモリが足りないため、AI 社員の採用が途中で止まります。笑
私は、Hermes Agentも併用しているのですがこのようなメリット・デメリットがあるために、
- Claude Code でやりたいごく一部のユースケースをこの記事で説明した仕組み
- リマインダーなどカジュアルな用途は Hermes Agent
という使い分けに落ち着きました。
もしよかったら参考に AI 社員作ってみてください〜!
Discussion