AIエージェント間のメッセージは送信成功と表示されたが、受信箱に無かった

English

この記事の目次

本記事の概要

2026-08-19に、私が進めている取り組み(AIエージェントの開発環境をOSSの部品だけで組み立て直す研究)の作業で、AIエージェントにメッセージを送るよう指示した。会話は、デスクトップのGUIのアプリの画面で行った。指示では、この研究で自作したMCPサーバのメッセージを送るツール(send_message)を使い、相手のエージェントに送るよう求めた。このMCPサーバは、セッションどうしのメッセージの送受信を提供し、宛先のエージェントの名前ごとにJSONLのファイルを書く。このファイルを受信箱のファイルと呼ぶ。会話の相手は、3つの公開のOSSのエージェント実行環境のうち、Qwen Code (版は0.21.13)をつないだエージェントだった。この研究の記録によると、Qwen Codeは、名前の似た内蔵の送信ツールを呼び出した。画面には送信の成功が表示されたが、どの受信箱のファイルにもメッセージは届いていなかった。この食い違いは、手で操作する作業の中で受信箱のファイルの中身を見て見つかった。

本文の中心は、AIエージェントどうしの送受信を判定する検査スクリプトの作りである。検査スクリプトは、このMCPサーバを3つのエージェント実行環境、すなわちOpenCode, Qwen Code, OpenHands CLI (版はそれぞれ1.18.18、0.21.13、1.16.0)に登録する。そのうえで、送信の検査と受信の検査と対照の検査の3つで、送受信が成立したかを判定する。どの検査でも、検査スクリプトはAIエージェントの申告で合否を決めない。送信の検査の合否は、相手の受信箱のファイルの行で決まる。受信の検査の合否は、実行ごとにランダムに作る目印の文字列が出力に現れるかで決まり、この文字列はプロンプトに含めない。対照の検査は、メッセージを送っていない状態で受信の検査と同じ指示を出し、目印の文字列が出力に現れないかを見る。2026-08-27には、ツールの呼び出しの記録を加えた。この記録は、MCPサーバがツールの呼び出しごとに1行を追記するファイルである。検査スクリプトは、記録のIDが受信箱のファイルの行のIDと一致することも、合格の条件にした。目的は、AIエージェントがツールを呼び出さずに受信箱のファイルを直接読み書きした場合を区別することである。2026-08-19と2026-08-27と2026-09-02のCLIでの測定では、9回の実行のすべてで3つの検査が合格した。

本文では、まず送信の成功の表示と届いていなかったメッセージの出来事を書く。次に、受信箱のファイルの行と目印の文字列で合否を決める検査スクリプトの作りを書く。続けて、ツールの呼び出しの記録による判定の強化と、3つのエージェント実行環境での測定の結果を書く。そのあと、取り違えが起きた会話の条件と、前日に起きた、子のエージェントの完了の報告が記録と食い違った例を書く。さらに、観測の後にルールの文書(AIエージェントに読ませる指示の文書)へ追加された項を書く。最後に、出力ではなく別の場所の記録で判定する根拠を、外部の研究と公式の指針の位置づけとあわせて書く。

記事から得られること

AIエージェントどうしの連携を検査する人に向けて、次の3つを説明する。

本文は、私が進めている取り組みの2026-08-18から2026-09-02の作業の記録と、2026-10-11に確かめた外部の資料に基づく考察である。

本文では、3つのエージェント実行環境の製品名を出す。内容は各提供元の見解を代表するものではない。

送信の成功の表示と、届いていなかったメッセージ

2026-08-19に、この研究の作業では、デスクトップのGUIのアプリの会話で、AIエージェントにメッセージを送る指示が出された。画面には送信の成功が表示されたが、どの受信箱のファイルにもメッセージは届いていなかった。受信箱のファイルは、この研究で自作したMCPサーバが、宛先のエージェントの名前ごとに書くJSONLのファイルである。

このMCPサーバは、セッションどうしのメッセージの送受信を提供する。このMCPサーバをメッセージ送信のMCPサーバと呼ぶ。メッセージ送信のMCPサーバには、次の3つのツールがある。

send_messageが1件を送るたびに、宛先の受信箱のファイルに、差出人と本文とIDを持つ1行が追加される。

この研究で使ったエージェント実行環境は、公開のOSSの3つ、すなわちOpenCode, Qwen Code, OpenHands CLI (版はそれぞれ1.18.18、0.21.13、1.16.0)である。GUIやエディタからエージェントを動かすための公開の規格に、ACPがある。ACPは、Agent、Client、Protocolの3語の頭文字である。会話の相手は、Qwen CodeをACP経由でつないだエージェントだった。

指示の内容は、メッセージ送信のMCPサーバが持つsend_messageでメッセージを送ることだった。Qwen Codeには、標準で登録される内蔵のツールの中に、メッセージを送るツールがある。このツールを内蔵の送信ツールと呼ぶ。この研究には、試行錯誤を記録した文書と、デスクトップのGUIのアプリとの統合を説明した文書がある。2つの文書には、Qwen Codeは、名前の似た内蔵の送信ツールを呼び出した、と書いてある。会話の記録には、呼び出されたツールの名前の文字列は残っていない。

試行錯誤を記録した文書には、成功の表示とメッセージが届いていなかったことに加えて、この食い違いが見つかった経緯も書いてある。この食い違いは、自動の判定ではなく、手で操作する作業の中で、受信箱のファイルの中身を見て見つかった。

受信箱のファイルの行と目印の文字列で合否を決める検査スクリプト

この研究の検査スクリプトは、AIエージェントの申告ではなく、受信箱のファイルの行と目印の文字列で、送受信の合否を決める。検査スクリプトは、メッセージ送信のMCPサーバを3つのエージェント実行環境に登録し、送受信が成立したかを判定するPythonのスクリプトである。このスクリプトは、この研究の作業で2026-08-19に新しく作られた。検査スクリプトは、送信の検査、受信の検査、対照の検査の3つを、この順に行う。

検査スクリプトは、実行ごとにランダムな文字列を作る。この文字列を目印の文字列と呼ぶ。送信の検査の合否は、相手の受信箱のファイルの行で決まる。受信の検査と対照の検査の合否は、プロンプトに含めない目印の文字列が出力に現れるかで決まる。

2026-08-19より前の結合テストは、送信だけを確かめていた。このテストは、検査スクリプトを追加したPRで削除された。MCPサーバの登録の書式は、エージェント実行環境ごとに、公式の登録のコマンドが書く出力で確かめられた。設定のファイルのキーは、Qwen CodeとOpenHands CLIがmcpServersで、OpenCodeがmcpである。

検査スクリプトは、検査の相手として別のプロセスを起動する。このプロセスは、モデルを介さずに、AIエージェントと同じメッセージ送信のMCPサーバのプログラムを、JSON-RPCの標準入出力で直接動かす。このプロセスを相手役のプロセスと呼ぶ。

次の表に、3つの検査の、AIエージェントへの指示と合格の条件を並べる。

検査の名前 AIエージェントへの指示 合格の条件
送信の検査 list_agentsで相手を見つけ、send_messageで目印の文字列を送る 差出人がAIエージェントの名前で、目印の文字列を含む行が、相手の受信箱のファイルにある
受信の検査 相手役のプロセスが先に送ったメッセージを、受信箱のファイルからcheck_inboxで読み出し、本文を出力する。この目印の文字列はプロンプトに含めない 目印の文字列が、AIエージェントの出力に現れる
対照の検査 メッセージを1件も送っていない状態で、受信の検査と同じ指示を出す 目印の文字列が、AIエージェントの出力に現れない

検査スクリプトの冒頭の説明には、対照の検査の目的が書いてある。目的は、受信箱のファイルを読まずに目印の文字列が出力に現れた場合に、受信の検査を合格にしないことである。説明には、そのような場合として、受信の検査で出力された目印の文字列が、メモリや保存に漏れて残った場合が書いてある。

検査スクリプトは、判定できない状態を合格にしない。判定できない状態は次の4つである。

宛先が登録されていない場合、メッセージを送るツールの呼び出しはエラーになる。そのため受信の検査では、相手役のプロセスが送る間だけ、AIエージェントの名前がメッセージ送信のMCPサーバの宛先として登録される。この名前を登録するプロセスは、相手役のプロセスとは別のプロセスである。

ツールの呼び出しの記録による判定の強化

2026-08-27に、検査スクリプトの送信の検査と受信の検査には、ツールの呼び出しの記録と照合する合格の条件が追加された。ツールの呼び出しの記録は、メッセージ送信のMCPサーバが、ツールが呼び出されるたびに1行を追記するJSONLのファイルである。各行には、ツールを呼び出したエージェントの名前とメッセージのIDがあり、本文は無い。この記録を書く処理は、同じ日に、この研究の作業でメッセージ送信のMCPサーバに追加された。

次の表に、送信の検査と受信の検査に2026-08-27に追加された合格の条件を並べる。

検査の名前 2026-08-27に追加した合格の条件
送信の検査 受信箱のファイルの行のIDと、メッセージを送るツール(send_message)をAIエージェントの名前で記録した行のIDが一致する
受信の検査 受信箱のファイルから取り出すツール(check_inbox)をAIエージェントの名前で記録した行に、送ったメッセージのIDがある

この強化の目的は、AIエージェントがツールを呼び出さずに受信箱のファイルを直接読み書きする場合を、ツールを通した送受信と区別することである。ツールの呼び出しの記録が無い場合と、ツールの呼び出しの記録が壊れた行を含む場合も、検査スクリプトは合格にしない。

検査スクリプトの説明には、この区別は完全ではない、と書いてある。理由は、ツールの呼び出しの記録の置き場と書式を、AIエージェントが同じ利用者の権限で読めることである。置き場と書式を読めるAIエージェントは、受信箱のファイルとツールの呼び出しの記録の両方を、書式に合わせて自分で書くこともできる。

3つのエージェント実行環境での測定の結果

2026-08-19と2026-08-27と2026-09-02の測定で、3つのエージェント実行環境のすべてが、3つの検査のすべてに合格した。各日に各エージェント実行環境で1回ずつ実行したので、実行は合わせて9回だった。

次の表に、測定の日ごとの判定の条件と、合格したエージェント実行環境の数を並べる。

測定の日 判定の条件 合格したエージェント実行環境の数
2026-08-19 受信箱のファイルの行と目印の文字列 3つのすべて
2026-08-27 受信箱のファイルの行と目印の文字列に加え、ツールの呼び出しの記録のIDの一致 3つのすべて
2026-09-02 受信箱のファイルの行と目印の文字列に加え、ツールの呼び出しの記録のIDの一致 3つのすべて

3つのエージェント実行環境が使ったモデルは、どれも、同じ推論のサービスの同じオープンウェイトのモデルだった。

9回の合格は、どれもCLIでの測定である。この測定では、3つのエージェント実行環境のどれでも、メッセージ送信のMCPサーバのツールを使える状態だった。2026-08-19の取り違えは、デスクトップのGUIのアプリの会話で起きた。この会話には、メッセージ送信のMCPサーバのツールが現れなかった。

デスクトップのGUIのアプリとの統合を説明した文書には、次の趣旨の記述がある。画面に成功と表示されても、メッセージが受信箱のファイルに無い場合は、送信の検査で合格にならない。理由は、送信の合否が受信箱のファイルの中身で決まることである。この記述は検査の作りから導いた記述で、検査スクリプトで会話の取り違えの場面を再現した記録は無い。

取り違えが起きた会話の条件

取り違えが起きた会話では、メッセージ送信のMCPサーバのツールが、ACP経由でつないだQwen Codeの会話に現れなかった。この研究の2つの文書には、Qwen Codeが内蔵の送信ツールを呼び出したと書いてある。しかし、モデルが内蔵の送信ツールを選んだのか、Qwen Codeが名前で解決したのかを確かめた記述は無い。確かめた範囲は、試行錯誤を記録した文書と、2026-08-19の2本のPRの本文と、統合を説明した文書である。

このMCPサーバは、デスクトップのGUIのアプリの設定の画面にある、MCP設定を一括で管理する機能で登録されていた。この登録では、接続の検証は通った。しかし、Qwen Codeの会話にはツールが現れず、MCPサーバのプロセスも起動しなかった。

この研究の2つの文書では、Qwen Codeの内蔵の送信ツールは、名前の似たツールと書かれている。観測した日のQwen Codeの版は0.21.13である。2026-10-11の照合の結果では、この版のツール名の定義ファイルと登録のコードで、標準で登録される内蔵のツールに、send_messageとlist_agentsがあった。この2つは、メッセージ送信のMCPサーバのツールと同じ文字列の名前である。Qwen Codeにはチームの機能の設定があり、この2つの内蔵のツールは、その設定に関係なく常に登録される。

内蔵のlist_agentsは、バックグラウンドのエージェントの一覧を返す。内蔵のsend_messageには、チームのメンバーに送るモードと、バックグラウンドのタスクに送るモードの2つがある。エージェントとタスクの語は、それぞれのツールの説明に書いてある語である。

名前が一致したことは、公開のソースを照合した結果である。会話で呼び出されたツールの名前を、会話の記録で確かめた結果ではない。

Model Context Protocolの仕様のToolsのページの版2025-11-25には、クライアントが内蔵するツールとの間で名前が重なる場合の規定は無い。異なるサーバの間で名前が重なる場合の規定も無い。このページには、ツールはそれぞれ名前で一意に識別される、と書いてある。ツール名は1つのサーバの中で一意であるべき(SHOULD)とも書いてある。

同じ日に、デスクトップのGUIのアプリの会話からの送受信は、OpenCodeをつないだ会話では成立した。この会話では、メッセージ送信のMCPサーバの登録が、OpenCodeの設定のファイルに追加されていた。この会話のエージェントは、CLIのセッションをlist_agentsで見つけ、目印の文字列を送った。CLIのセッションの受信箱のファイルには、差出人がこの会話のエージェントである行が届いた。逆の向きでは、Qwen CodeのCLIのセッションが、この会話にメッセージを送った。この会話のエージェントは、そのメッセージを受信箱のファイルからcheck_inboxで読み出し、画面に出力した。

前日に起きた、子のエージェントの完了の報告が記録と食い違った例

2026-08-18には、Qwen Codeの実験的な並列実行の機能で、子のエージェントの完了の報告が、この機能が書く記録のJSONのファイルと食い違った。この機能は、モデルが書いた編成のスクリプトに従って子のエージェントを並列に起動し、編成の実行ごとに記録のJSONのファイルを書く。

この研究の作業では、この機能が非対話の実行で測られた。7回の試行で子のエージェントの起動は13件あり、13件とも完了しなかった。子のエージェントが消費したトークンは0で、子のエージェントはモデルを一度も呼び出さなかった。同じ日に対話のモードで測り直した結果では、子のエージェント2件が完了した。この研究の実行の記録には、子のエージェントが完了しない現象は非対話の実行でだけ起きる、という結論が書いてある。

最後の試行では、モデルは子のエージェントを起動せずに答えを直接書き、最後の応答で、子のエージェント3つが終わったと報告した。この試行の記録のJSONのファイルでは、子の起動を試みた件数の欄が0だった。この欄の値が、報告の誤りを機械的に示した。

この研究で自作した、子のエージェントを並列に実行するプログラムは、この研究の実行の記録に2つの件数を必ず書く。2つの件数は、子の起動を試みた件数と、応答の本文を返した子のエージェントの件数である。このプログラムのREADMEには、2つの件数を必須にした理由として、2026-08-18の誤った完了の報告が書いてある。

この研究の試行錯誤を記録した文書では、完了や成功の報告が、件数の欄や受信箱のファイルの中身と食い違う失敗が、1つの型に分類されている。この文書では、2026-08-19の送信の成功の表示は、2026-08-18の完了の報告に続く2例目である。

並列実行のMCPツールと子のエージェントを扱った同じ研究の記事に、MCPツールの説明文にいつ使うかを書いたら、AIエージェントが呼び出したとコーディングエージェントの能力差に見えた失敗の原因はAPIキーの渡し方がある。

観測の後にルールの文書へ追加された項

2026-08-20にマージされたPRで、ルールの文書の2本に、同じ内容の項が1つずつ追加された。ルールの文書は、AIエージェントに読ませる指示の文書である。2本は、AIエージェントが常に読む既定の指示の文書と、セッションをまたぐ機能を使うときに読むスキルの文書である。このPRは、AIエージェントが作った。

追加された項は、MCPサーバが設定されていない環境での指示である。項には、名前の似た別のツールで代替せず、ツールが存在するかを先に確かめ、無ければ設定が要ると報告する、という指示が書いてある。項には、理由として、名前の似たツールが使われて、画面には成功と表示されたのに何も届かなかった失敗が起きたことも書いてある。

出力ではなく別の場所の記録で判定する根拠

2026-08-18の子のエージェントの完了の報告と、2026-08-19の画面の送信の成功の表示は、どちらも、報告とは別の場所に残るデータと食い違った。2026-08-18の報告の誤りは、実験的な機能が書く記録のJSONのファイルの、子の起動を試みた件数の欄で確かめられた。2026-08-19の表示の誤りは、受信箱のファイルで確かめられた。これらの事実から、エージェント連携の検査の合否は、AIエージェントの出力ではなく、報告とは別の場所に残るデータで決めるのがよいと言える。

この研究の試行錯誤を記録した文書には、何を何で判定するかが、次のように書いてある。

受信の検査は、プロンプトに無い目印の文字列が出力に現れることで、出力が受信箱のファイルから来たことを確かめる。対照の検査は、メッセージを送っていない状態では、同じ出力が出ないことを確かめる。2つの検査を組にすると、目印の文字列がメモリや保存に漏れて残り、受信箱のファイルを読まずに出力に現れた場合を、対照の検査で不合格にできる。この性質は検査の作りから導いたもので、9回の実行では、対照の検査が不合格になった例は無かった。

この研究の試行錯誤を記録した文書には、MCPサーバを登録して動作を確かめるときの手順も書いてある。指示を出す前に、設定のファイルにMCPサーバが書かれているかと、MCPサーバのプロセスが起動したかを見て、ツールが会話にあることを確かめる。

AIエージェントの申告ではなく、環境に残った状態や記録で成否を判定する考え方は、外部の研究と公式の指針にもある。

false successを測った研究(Advani、2026)のabstractによると、環境の状態が完了を示していないのに、LLMエージェントが課題の完了を主張する失敗は、false successと呼ばれる。測定の対象の1つは、tau2-benchでAIエージェントが課題に取り組んだ9,876件の軌跡で、8つのモデル系統にわたる。軌跡の成否の正解は、エージェントの文面に依らずに決められた。tau2-benchのうち、研究が単一制御と呼ぶ領域では、false successは失敗の45%から48%だったと報告されている。単一制御の定義は、abstractには無い。LLMによる判定(LLM judge)は、この失敗を十分に検出できなかったと報告されている。検出の性能を0から1で表す指標をAUROCと呼び、0.5は偶然と同じである。abstractに書いてある判定の構成は、5種のモデル、5種のプロンプト、課題の仕様の全文である。どの構成でも、tau2-benchでのAUROCは0.65を超えなかった。LLMによる判定は、確信のある締めの言い回しと行動の列の量を手がかりにしていて、検証された状態の変化を見ていない、と書いてある。

Demystifying evals for AI agentsには、航空券の予約のエージェントの例が書いてある。この例では、成果を、エージェントが予約したと言ったかどうかでなく、環境のSQLデータベースに予約が存在するかどうかで判定する。

ツールの実行のレシートで幻覚を検出する研究(Basu、2026)のabstractでは、幻覚を検出する枠組みが提案されている。この枠組みでは、ツールの実行のレシートと、応答の中の主張が照合される。レシートは、LLMが偽造できないHMACで署名される。

検査スクリプトの限界は、AIエージェントがツールの呼び出しの記録を同じ利用者の権限で読めるので、記録を書式に合わせて自分で書ける余地が残ることだった。これらの事実から、この限界は、レシートの研究が署名で防ぐ記録の偽造と同じ種類の問題だと言える。報告とは別の場所に残るデータで合否を決める分け方も、この研究の作業の記録だけから出た結論ではないと言える。

参考にした研究

本文で参照した研究は次の2つで、2026-10-11にarXivのabstractのページを確かめた。

参考にした資料

本文で参照した公開の資料は次の3つで、2026-10-11に原文を確かめた。