前面幾天都在把別人的能力接進來,今天反過來,看這個 agent 能以什麼形式被別人呼叫。它有四個指令名字裡帶 serve 或 peer,mcp serve、serve、acp、peer。四個做的事各不相同,其中只有一個是 agent 對 agent 的委派。
hermes mcp serve 走 stdio,拿 JSON-RPC 打一次 initialize 加 tools/list 就看得到全部。回來的握手資訊:
| 欄位 | 值 |
|---|---|
protocolVersion |
2025-11-25 |
serverInfo.name |
hermes |
capabilities |
experimental、prompts、resources、tools 四項,listChanged 全為 false |
instructions |
167 byte |
那段 instructions 把用途寫得很直接:
Hermes Agent messaging bridge. Use these tools to interact with conversations across Telegram, Discord, Slack, WhatsApp, Signal, Matrix, and other connected platforms
這個 server 暴露的是訊息層,呼叫端拿到的是讀寫對話的能力。 十個工具按職責分三組:
conversations_list、conversation_get、messages_read、attachments_fetch
events_poll、events_wait
messages_send、channels_list、permissions_list_open、permissions_respond
工具清單裡沒有「把一段任務交給這個 agent 去做」這種東西。要讓它做事,走的是送一則訊息進它的對話,再從同一座橋把回覆讀回來。
| 工具 | schema byte | 其中描述 |
|---|---|---|
conversations_list |
979 | 456 |
events_poll |
962 | 470 |
messages_send |
925 | 514 |
events_wait |
910 | 407 |
attachments_fetch |
745 | 314 |
messages_read |
742 | 332 |
channels_list |
677 | 314 |
permissions_respond |
597 | 190 |
permissions_list_open |
584 | 289 |
conversation_get |
508 | 149 |
| 合計 | 7,629 | 3,435 |
描述佔 45%。自建那個 MCP 的五個工具量到的是 54%,兩組都落在將近一半的位置。
這座橋掛到另一個 profile 身上的代價可以直接疊:同一台機器上那個 profile 目前的工具 schema 是 37,012 byte、20 個工具,接上去之後工具數加五成,byte 數加兩成。工具個數與 schema byte 的成長比例對不上,這一組工具的參數結構相對簡單。
量測工具這一側有個限制要先講。prompt-size 報的 20 個工具是內建工具集,它建的是離線檢視用的 agent,MCP 掛載的工具不在它的統計裡。MCP 這一側的 byte 要自己打 tools/list 算。
| 指令 | 對外暴露什麼 | 呼叫端是誰 |
|---|---|---|
hermes mcp serve |
訊息橋接的 MCP server,十個工具 | 任何 MCP client |
hermes serve |
JSON-RPC/WebSocket 後端,預設 port 9119 | 桌面應用程式與遠端 client |
hermes acp |
ACP 模式 | VS Code、Zed、JetBrains |
hermes peer |
把另一台機器的 gateway 註冊成 peer | 這台機器上的 agent 或人 |
agent 對 agent 的委派在 hermes peer。 它的說明寫的是:hermes peer dm <peer>[/<agent>] "..." 把訊息送進遠端 agent 的 Bot Chat,印出回覆,是 hermes -p <bot> chat 的跨機器版本。
長時任務走另外三個子指令:
peer run 送出一段長任務並回傳 run ID,支援 --idempotency-key
peer status 讀該次執行的狀態與最終輸出peer stop 停掉其中一次執行而不影響同機器上的其他輪次退出碼分三種:0 送達、1 投遞或 peer 錯誤、2 用法錯誤。前置條件是對方的 gateway 要跑 api_server 這個平台,它的 API_SERVER_KEY 以憑證形式存在本機的 .env。
這個形狀與前兩天的非同步工具是同一套想法。送出之後拿一個代號,之後憑代號查狀態,--idempotency-key 讓重送同一個請求不會變成兩次執行。
前面量可替換性那天留下一個失敗案例,剛好是這件事的反面。當時把一個 agent 的 OpenAI 相容端點填進另一個 agent 的模型欄位,外層以為自己接的是模型,內層實際是個會自己跑工具迴圈的 agent。
內層把它內部已經執行過的 tool_calls 一併回在回應裡,外層照 OpenAI 的語意理解成「這是要我執行的工具」,在自己的工具表裡找不到:
⚠ Unknown tool 'get_environment_status' — sending error to model for agent-correction (1/3)
✗ Max retries (3) for invalid tool calls exceeded. Stopping as partial.
tool_calls 這個欄位在兩邊的語意不同。 模型回它表示「請呼叫端執行」,agent 回它表示「我執行過了」,欄位名一樣,方向相反。
peer 與 mcp serve 兩條路都避開了這個問題。 前者把對方當成會回話的對象,收到的是最終文字,後者把對方的能力包成工具,由呼叫端決定要不要執行。兩條路都把 agent 放在 agent 的位置上。
一個元件回傳的欄位要怎麼解讀,取決於它在架構裡被放在哪個位置
被呼叫的那一側是一個完整的 agent,它有自己的身分宣告、記憶與工具集。委派時哪些東西跟著過去:
| 項目 | 跨不跨邊界 |
|---|---|
| 任務描述 | 跨,就是送過去的那段文字 |
| 呼叫端的 system prompt 與記憶 | 留在呼叫端 |
| 被呼叫端的身分宣告與記憶 | 留在被呼叫端,並且作用在這次執行上 |
| 工具執行的結果 | 以回覆文字的形式回來 |
委派出去的那段任務,實際是在另一套身分與另一組記憶底下被執行的。要它照某個規則做事,規則得寫在那一側,或者逐次寫進任務描述裡。
打 tools/list 之前,預期看到的是一個可以接受任務的工具。回來的清單第一個是 conversations_list,第二個是 conversation_get,看到第三個 messages_read 的時候才確定方向整個不同。
instructions 那 167 byte 把它講得很清楚,messaging bridge。這個欄位在 MCP 的握手裡是給呼叫端看的說明,平常容易當成客套話跳過,這次它是唯一一句直接回答「這個 server 是做什麼的」的內容。
指令名稱裡的 serve 指的是「把某個東西對外提供」,至於提供的是哪個東西,名稱裡沒有寫。四個指令都叫 serve 或 peer,要分辨只能一個一個打開看。
握手回傳的 instructions 是 server 自己對用途的宣告,比指令名稱更接近它實際做的事
同一支私鑰,換一種路徑寫法,判定從放行變成要確認。