Claude Media
Claude Code SendMessageで複数マシンのエージェントを連携する

Claude Code SendMessageで複数マシンのエージェントを連携する

Claude CodeのSendMessageはv2.1.224で別マシンのセッションにも届くようになりました。届く条件・受信側の承認待ち・止め方を公式の仕様と実機の出力で確かめます。

同じSendMessageというツールが、v2.1.77では一時停止したサブエージェントを起こし直すためだけの内線電話でした。v2.1.224では、別マシンで動く別セッションへメッセージを送る手段に変わっています。この記事は、どの相手にどの経路で届くのか、受信側で何が起きるのか、届かないときはどこを見るのかを、公式ドキュメントの仕様と手元のclaudeで確認できた範囲からたどります。送信時の拒否文言はセッション間送信エラー3種の記事で引けます。

Claude CodeのSendMessageとは

SendMessageは、Claude Codeのエージェントが別のエージェントセッションへメッセージを送るビルトインツールです。呼び出すのはユーザーではなく実行中のClaude自身で、宛先にはエージェントIDか名前を指定します。

使い方は、プロンプトで頼むだけです。公式の例文は次の2つです。

  • Ask the session running in my other terminal whether the migration finished
  • Let @api-worker know the schema migration finished

送る文面そのものはClaudeが書くので、プロンプトでは中身まで指定しなくて構いません。頼まれなくても、必要と判断すればClaudeが自分で送ることもあります。

宛先は3種類あります。完了または停止したサブエージェント、Agent Teamsのチームメイト、そして自分の別のClaude Codeセッションです。3つ目はv2.1.224以降の話で、同じマシンのセッションも、別マシンやクラウドのセッションも含みます。

SendMessage自体はAgent Teamsを有効にしなくても使えます。Agent Teamsが必要になるのは、shutdown_requestやplan_approval_responseのような構造化されたチーム用メッセージだけです。Agent Teamsは公式が実験的機能と位置付ける仕組みで、既定では無効です。試すときはCLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS環境変数を1にします。

運用に効く既知の制限は3つあります。/resumeや/rewindでセッションを再開しても、プロセス内のチームメイトは復元されません。タスクの完了ステータスが実際の進捗より遅れることがあります。シャットダウンには、チームメイトが処理中のリクエストを終えるまでの時間がかかります。

用途宛先対応バージョン
停止・完了したサブエージェントの再開宛先エージェントID・名前対応バージョンv2.1.77以降
Agent Teamsのチームメイトへの直接連絡宛先チームメイトの名前対応バージョンAgent Teams有効時
自分の別セッションへの連絡(同じマシン・別マシン・クラウド)宛先ListAgentsで見つけた名前対応バージョンv2.1.224以降

同一セッション内でSendMessageはどう機能するか

サブエージェントが完了すると、Claudeはそのエージェントの一意なIDを受け取ります。組み込みのExploreとPlanは1回限りの実行で、エージェントIDを返しません。継続作業をさせたい場合の選択肢は、general-purposeか独自定義のサブエージェントです。

再開の実体はSendMessage({to: agentId})です。完了済みのサブエージェントにメッセージが届くと、新しいAgent呼び出しなしにバックグラウンドで再開します。Claude自身がTaskStopツールで止めたサブエージェントも、止めた実行が終了したあとなら同じように再開します。

例外は、ユーザーが/tasksでxキーを押すか、SDKのstop_taskで止めたサブエージェントです。この場合SendMessageは拒否され、Claudeには「取り消された」と伝わります。再開するには、サブエージェントパネルにその行が残っている間に、そのサブエージェントのトランスクリプトへ直接入力します。そのあとは、Claudeからのメッセージでも再び自動で再開します。

サブエージェント自身がSendMessageを持っていれば、別のエージェントを再開することもできます。対話セッションでは、再開された側の結果は再開した側のサブエージェントに返り、メイン会話には返りません。

名前の解決にも安全策が入っています。v2.1.199以降、SendMessageは名前が会話内で以前と同じエージェントを指しているかを確認します。再起動したバックグラウンドエージェントが同じ名前を使い回していたら、Claude Codeは送信を拒否し、その名前がいま誰を指すかをエラーで返します。確実に届けたいなら、起動時に受け取ったエージェントIDを使います。

v2.1.206からは、サブエージェントの初期コンテキストに「兄弟エージェント一覧」というシステムリマインダーも入ります。mainと名前を持つ他の全エージェントを並べたもので、toに指定できる値の一覧です。出る条件は、そのサブエージェントのtoolsにSendMessageがあり、名前を持つ他のエージェントが1つ以上いることです。

別マシンやクラウドのセッションにはどう届くか

v2.1.224でSendMessageは同一マシンの縛りを外れ、相手を探すためのListAgentsツールが加わりました。どちらも利用者が呼ぶものではありません。Claudeが必要と判断したとき、または頼まれたときに使います。

くらべる

相手がどこにいるかで経路が変わる

サーバーを通らない

同じマシン

セッションごとのソケットで直接届きます。ネイティブWindowsでは名前付きパイプです。Anthropicのサーバーは経由しません。ログイン方法を問わず、Bedrockなどのクラウドプロバイダでもv2.1.248以降なら使えます。

サーバーを通る

別マシン・クラウド

Anthropicのサーバーを経由し、別マシンではその機械のRemote Control接続で届きます。見つけるには、送る側もRemote Controlに接続していて、claude.aiのサインインが有効な認証である必要があります。APIキーやBedrock利用のセッションからは探せません。

ここが公式ページ同士で読み違えやすい点です。変更履歴の最初の告知は「どの機械のセッションにも送れる」という書きぶりですが、実際の条件は相手に応じて分かれます。別マシンのセッションへ自分から話しかけられるのはv2.1.225以降で、それまでは相手が先に送ってきた場合の返信しかできませんでした。

見える相手は/list-agents(別名/peers)で確認できます。一覧に出るのは、現在のセッション内のサブエージェントとチームメイト、同じマシンの他のセッションです。Remote Control接続中なら、クラウドのセッションと他マシンのRemote Controlセッションも出ます。切断された相手にはofflineが付きます。Remote Control接続中は、/list-agentsの出力で作業ディレクトリや帰属不明の名前が一部伏せられます。Claudeが見る一覧は変わりません。

offlineの相手にも送信自体は通ります。ただし届くのは、その機械が再接続したあとです。相手の行にcan't receive cross-session messagesと出ているときは、そのセッションで機能が使えないか、crossSessionInboundがrefuseになっています。この場合は送信側でNot sentとして止まり、メッセージはマシンの外に出ません。

自分がRemote Controlに接続していない状態で別マシンへ送ることもできますが、返信先が付きません。受け取った側のClaudeは返事を返せない、一方通行のメッセージになります。

到達しない組み合わせもあります。コンテナ内のセッションとホストのセッションは互いに届きません。同じコンテナの中どうしなら届きます。同じPC上でも、WSL 2内のセッションとネイティブWindowsのセッションは互いに届きません。

メッセージの宛先は名前で指定します。/renameか--nameで付けた名前が使われ、未設定ならClaude Codeが名前を付けます。同じ名前のセッションが複数あるときは、Claudeが一覧に短い識別子を付けてそれで指定します。プロンプトに@api-workerのように書けば、一覧を引かずに相手を指名できます。これはv2.1.232以降の機能です。別マシンやクラウドのセッションは、Claudeが一度一覧を取るか送信するまで、@の候補に出ません。

バージョンごとの変遷

バージョン変更内容
v2.1.77変更内容Agentツールのresumeパラメーターを廃止。再開をSendMessage({to: agentId})に一本化
v2.1.118変更内容再開したサブエージェントが作業ディレクトリを復元しない不具合を修正
v2.1.162変更内容CLAUDE_CODE_TMPDIRや$TMPDIRが深い階層を指すとクロスセッションメッセージが壊れる不具合を修正
v2.1.166変更内容他セッションから中継されたメッセージにユーザー権限を持たせない強化
v2.1.191変更内容タスクパネルから止めたバックグラウンドエージェントが復活しないよう修正(停止を恒久化)
v2.1.198変更内容サブエージェントが、起動元のメッセージを通常のタスク指示として扱う
v2.1.199変更内容名前の使い回しを検出し、以前と別のエージェントへの送信を拒否
v2.1.205変更内容再開したサブエージェントが古い失敗・完了ステータスのまま表示される不具合を修正
v2.1.206変更内容兄弟エージェント一覧を初期コンテキストに追加
v2.1.212変更内容メッセージ本文が履歴とツール結果に二重展開されないよう変更
v2.1.222変更内容auto modeで、送信メッセージが配送前に権限分類器の評価を受ける
v2.1.224変更内容ListAgentsとcrossSessionInbound・dialogExpiryを追加し、別マシンへ拡大
v2.1.225変更内容別マシンのRemote Controlセッションへ、自分から会話を始められる
v2.1.232変更内容プロンプトで@による相手の指名、/configに受信設定と承認待ちの期限の2行
v2.1.236変更内容notify_when_idleで、同じマシンの相手が手空きになったとき1回だけ通知

受け取った側では何が起きるか

届いたメッセージは、受信側のClaudeに「ユーザーではなく別のセッションから来た」と伝えられます。そのうえで、できることが絞られます。

  • 保留中の権限確認への承認にはならない
  • CLAUDE.mdや権限設定を書き換える根拠にならない
  • 本文中の/compactのようなコマンドは、ただの文字列として届き、実行されない
  • 受信側の権限プロンプトは通常どおり出る

メッセージはプレーンテキストだけで、本文中の@によるファイルやMCPリソースの指定も展開されません。受信側の画面には、› Message from @api-worker: …のような薄い1行のプレビューが残ります。全文はCtrl+Oのトランスクリプトか、--verboseで起動したセッションで読めます。Claudeはプレビューが短くても全文を読んでいます。

この1行プレビューには、送り手が付ける任意のsummary入力が使われます。目安は5〜10語です。省かれたプレーンテキストのメッセージでは、本文の1行目が代わりに入ります。

auto modeで動く送信側では、v2.1.222以降、配送の前に権限分類器がメッセージを評価します。plan modeでauto分類器がコマンドを審査している間も同様です。

受信側の既定は権限モードで決まる

メッセージを受けるか保留にするかは、crossSessionInboundが決めます。設定しないときの既定は、送り手と受け手の権限モードの組み合わせです。

まとめ

crossSessionInboundの3つの値

  • accept

    届いたメッセージを、そのままClaudeに渡します。

  • hold

    届いた事実の通知だけを出し、Claudeには渡しません。あとでacceptが適用された時点で、保留分が放出されます。

  • refuse

    メッセージをClaudeに渡さず、そのまま捨てます。

値を設定しないとき、権限プロンプトを出さないセッション(bypassPermissions)と、それ以外に分けて判断されます。受け手が通常どおり権限を確認するセッションなら、メッセージは届きます。送り手がbypassPermissionsを名乗っている場合だけ、受け手の承認を待ちます。

逆に、受け手がbypassPermissionsのセッションなら、メッセージは承認待ちです。送り手もbypassPermissionsのときだけ、そのまま届きます。plan modeは、bypassPermissionsを使える対話端末では「確認しない側」に数えられ、auto・acceptEdits・dontAskは「確認する側」に数えられます。

承認待ちになると、受信側に送り手とプレビューを表示するダイアログが開きます。承認すればそのメッセージ1通が届き、拒否するか閉じれば捨てられます。保留できるのは100通までで、超えると古いものから落ちます。

承認待ちの期限と、期限切れのときの結果

ダイアログには期限があり、dialogExpiryが決めます。既定は5分で、60s・5m・10m・neverのいずれかを選べます。neverは期限の無効化です。dialogExpiryは個人またはmanaged設定の項目で、プロジェクトの設定ファイルには書けません。1回のセッションだけ変えたいなら、CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS環境変数が優先します。

期限内に応答がなければ、メッセージは捨てられます。-pセッションでは、届く送り手に期限切れとして知らされます。端末が接続されていないバックグラウンドセッションだけは例外で、接続されるまでダイアログを開いたままにします。接続後、1期限ぶん放置すれば閉じて捨てます。

dialogExpiryは、SendMessageの承認待ちだけが対象ではありません。Remote ControlやSDKホストなど、接続先のクライアントへ転送するダイアログ全般が対象です。通常の権限プロンプトとAskUserQuestionは別の仕組みなので、この期限の外にあります。

crossSessionInboundの置き場所には非対称なルールがあります。プロジェクト設定とローカル設定の値は、managed設定・--settings・ユーザー設定が与える値より厳しいときだけ有効です。順序はaccept、hold、refuseの順に厳しくなります。チェックイン済みのプロジェクトファイルから、受信を緩める方向には働きません。

認識できない値を書いたときも安全側に倒れます。v2.1.248以降は警告を出し、メッセージをholdします。managed設定に書かれていた場合はrefuse扱いです。それ以前のバージョンは、警告なしで無視していました。

非対話のclaude -pセッションも受信口を開き、一覧に出ます。ただしbare modeのセッションは受信できません。無人のワーカーに受けさせるなら、--settingsでcrossSessionInboundをacceptにします。既定の判断で保留された分はdialogExpiryの期限で捨てられますが、明示的にholdを設定したときの保留は期限切れになりません。

実際に使えるか手元で確かめる

設定を触る前に、バージョンと一覧を見るのが近道です。

手順

使える状態かを確かめる手順

  1. 1

    バージョンを見る

    全マシンでv2.1.224以降(ネイティブWindowsはv2.1.234以降)であることを確認します。

  2. 2

    セッションの一覧を出す

    セッションで/list-agentsを実行します。コマンドが認識されなければ、そのセッションに機能がありません。

  3. 3

    相手の状態を読む

    offlineなら再接続待ち、can't receiveなら相手側の設定を疑います。別マシンの相手が出ないときは、双方がRemote Controlに接続しているかを見ます。

  4. 4

    送ってみる

    @で相手を指名して依頼を書きます。長い作業の終了を待つなら、手が空いたら知らせてほしいと頼むこともできます。

手元のclaude(v2.1.286)で確認できたのは、次の範囲です。

claude --version
claude --help | grep -i -E "agents|permission-mode"
2.1.286 (Claude Code)
  --permission-mode <mode>   Permission mode to use for the session
  agents [options]           Manage background agents

--permission-modeの選択肢にはbypassPermissionsが含まれ、承認待ちの既定の分岐が見ている権限モードそのものです。claude agentsはバックグラウンドエージェントを管理するサブコマンドで、/list-agentsとは別物です。/list-agentsは対話セッション内のスラッシュコマンドなので、今回の確認では実行していません。メッセージの送受信も、ログイン済みの複数セッションが必要になるため実機では試していません。ここから先の挙動は、公式ドキュメントの記述に基づきます。

notify_when_idleの使い方も書いておきます。v2.1.236以降、同じマシンの別セッションに「手が空いたら1回だけ知らせて」と頼めます。待つ側は、通知が来るまで何度も状況を聞き直す必要がありません。相手のセッションでトークンを使わずに購読でき、すでに手空きならすぐ通知が来ます。

制限もあります。頼めるのはメイン会話のClaudeだけで、相手は同じマシンのセッションに限られます。チームメイトやサブエージェント、別マシンの相手には、添えたメッセージごと拒否されます。12時間たっても通知がなければ、購読は破棄されます。

届かないときに見る場所

症状から原因を絞るための表です。

症状考えられる原因見る場所
/list-agentsが認識されない考えられる原因その機能がないバージョン・環境見る場所claude --version、OSの条件
一覧は出るが相手に届かない考えられる原因受信側のhold・refuse、SendMessageの拒否ルール見る場所受信側の設定、permissions.deny
別マシンやクラウドの相手が出ない考えられる原因Remote Control未接続、APIキーやBedrockでの利用見る場所双方のRemote Control接続
結果がNot sentで始まる考えられる原因相手が受信不可と表示されている見る場所相手のcrossSessionInboundとバージョン
古いクラウドセッションが名前で指せない考えられる原因一覧が新しい順に有限ページだけ読まれる見る場所識別子での指定、一覧の再取得

ほかに知っておきたい上限もあります。送れるのはプレーンテキストだけで、同じマシンへの1通は直列化後でおよそ100万文字までです。短時間に集中して送ると、送信側が先に拒否し、まとめて1通にするよう促します。受信側は同一の繰り返しを捨て、受け付けるのは50通までです。この制限があるため、2つのセッションがメッセージを投げ合うループは自然に止まります。

受信と送信を絞りたいとき

別マシンへの送信に自分の承認を挟みたいなら、isolatePeerMachinesをtrueにします。bypassPermissionsでも、別マシンのセッションに届く前に確認が出ます。同じマシンの相手には聞かれません。どの設定ファイルからでもtrueが適用されるため、プロジェクトのファイルでオンにできても、オフにはできません。

{
  "isolatePeerMachines": true
}

機能を止めるときは、受信と送信を別々に止めます。受信はcrossSessionInboundをrefuseにします。送信と一覧は、permissions.denyにSendMessageとListAgentsを並べます。どちらも指定子なしの名前だけです。管理者が組織全体で止めるときは、両方をmanaged設定に置きます。

{
  "permissions": {
    "deny": ["SendMessage", "ListAgents"]
  },
  "crossSessionInbound": "refuse"
}

この設定にしても、各セッションの受信口は開いたままです。届いたものを捨てるだけで、Claudeには何も渡しません。SendMessageを拒否するとサブエージェントやチームメイトへの連絡も同時になくなる点に注意が必要です。拒否しているセッションの/statusや、他セッションの一覧には目に見える変化が出ません。確かめるには、そのセッションに適用される設定ファイルを見ます。

紛らわしい機能とどこが違うか

似た響きの機能は、つなぐ対象が違います。

サブエージェントは結果をメインへ返す一方通行です。Agent TeamsのチームメイトはSendMessageで互いに連絡を取り合い、共有のタスク一覧を見ながら作業を拾います。トークン消費はサブエージェントより高い代わりに、調査結果を持ち寄って議論させる構成に向きます。共有タスク一覧はTask系ツールが渡されているセッションが前提で、Opus 4.8やSonnet 5などの新世代モデルでは既定で提供されません。影響と復活方法はClaude Code TodoツールがOpus 4.8以降で既定オフで扱いました。

機能つなぐもの主な用途
SendMessage(クロスセッション)つなぐもの別々のセッション同士(別マシン・クラウドも)主な用途エージェント同士の連絡・再開
Agent Teamsつなぐもの同一セッション内の複数チームメイト主な用途並列探索・議論・相互レビュー
agent viewつなぐもの同一マシン上の複数バックグラウンドセッション主な用途一覧監視・ディスパッチ
Remote Controlつなぐもの人間のデバイスと1つのローカルセッション主な用途外出先からの操作・確認

人間がスマホから覗きたいならRemote Control、エージェント同士で連絡を取らせたいならSendMessageという切り分けです。ただしSendMessageが別マシンを見つける手段は、Remote Controlの接続そのものです。両者は競合する機能ではなく、後者が前者の通り道になっています。Claude Codeのサブエージェントの延長で試すなら、まず同一セッション内の再開から入るのが分かりやすい入り口です。

公式ドキュメントに記載のない点

次の2点は公式に記述がないため、断定を避けます。1つは、別マシンのセッション配下にあるサブエージェントを、直接指定して再開できるかどうかです。ListAgentsが一覧に載せるサブエージェントは、現在のセッション内のものと記されています。もう1つは、別々のclaude.aiアカウントのマシン間で使えるかどうかです。公式は「あなたの」セッションと書いており、他人のアカウントとの連携には触れていません。

まとめ

複数のセッションを並行して回しているなら、受信側のcrossSessionInboundとdialogExpiryを先に決めておくと、無人の運用で届かない理由を追いやすくなります。1台で完結する使い方には、ほとんど影響がありません。Claude Code v2.1.224では、この機能とあわせてサブエージェントの総発行数上限も撤廃されました。オーケストレーター設計のような多エージェント運用を前提にした変更が、続けて入った回です。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/changelog
  2. code.claude.com/docs/en/sub-agents
  3. code.claude.com/docs/en/agent-teams
  4. code.claude.com/docs/en/tools-reference
  5. code.claude.com/docs/en/settings
  6. code.claude.com/docs/en/settings-reference
  7. code.claude.com/docs/en/cross-session-messaging
  8. code.claude.com/docs/en/remote-control
この記事を共有:XはてブLinkedIn