← 返回文章列表

把幾台機器上的 AI Agent 連成一張能互相調用的網

起點:我有一堆機器,但它們彼此夠不着

我手上散着好幾台機器:一台有公網的雲服務器、一部常年插着電的手機、一台 Mac,還有幾台雜七雜八的 Linux。每台上面都跑着 agent,各幹各的活。

問題是它們互相不認識。我想讓 Mac 上的 agent 臨時把一段重活派給雲服務器,或者讓雲上的 agent 去問一下手機本地才有的某個上下文——做不到。它們之間隔着一層我一開始沒太當回事、後來才發現是整件事核心的東西:網絡可達性。

先分清兩個面:控制面和數據面

在動手連之前,我先想清楚我到底要的是哪種「互通」。

我早就有一套基於 Git 的「郵箱」機制充當控制面:每台機器的 agent 往一個共享倉庫裏留言、協調、交接任務,所有動作都落進 git history。這套東西的好處是耐久、異步、可審計——誰在什麼時候説了什麼、做了什麼決定,全部留痕。壞處也很明顯:它慢。它適合「留個話」,不適合「我現在就要結果」。

這次要補的是另一半——數據面:一台機器把任務派給另一台,秒級拿回結果。實時互調。我選了 Google 的 A2A(Agent-to-Agent)這個開放協議來做標準化的互調接口,不想自己再發明一套消息格式。

一句話定位:郵箱是控制面(慢、可靠、留痕),A2A 是數據面(快、實時)。兩個面互補,不是誰替代誰。

真正的攔路虎:NAT

協議選完,我以為剩下的是體力活。結果一上手就撞牆。

雲服務器有公網 IP,它能被任何機器主動連接,這沒問題。但反過來——雲服務器連不動那些躲在家庭寬帶和移動網絡 NAT 後面的機器。我的手機、我的 Mac,它們只有「出站」的能力,沒有「入站」的地址。

為什麼入站不可達?因為這些設備在 NAT 後面根本沒有一個外部世界能撥過去的地址。它們的內網 IP 對公網毫無意義;NAT 設備只會在它們主動發起一個連接、並因此在轉換表裏留下一條記錄之後,才知道把回來的包送給誰。沒有這條記錄,外面打進來的包不知道該交給內網裏的哪台機器,直接被丟掉。所以「hub 主動去連 spoke」這個方向,在物理上就走不通——不是端口沒開,是壓根沒有能被撥的號碼。

這一下就把拓撲給定死了。能被別人連的,只有那台有公網的雲服務器。於是它順理成章當 hub,其它機器全部當 spoke,圍着它轉。Hub-and-Spoke,沒得選。

            [手機 spoke]
                 |
   [Mac spoke]--[雲服務器 hub]--[Linux spoke]
                 |
            (公網可達的只有 hub)

兩個方向,難度天差地別

連通這件事拆開看是兩個方向,得分別解決。

方向一,spoke 調 hub——這個簡單。 Spoke 作為客户端主動連 hub,發起的是出站連接,天然可達。NAT 不攔出站。所以這條路我先跑通了,幾乎沒費什麼勁:spoke 上的 agent 直接把 A2A 請求打到 hub 的端點,拿結果回來。

方向二,hub 調 spoke——這個才是真問題。 我想讓 hub 上的 agent 反過來把任務派給某台 NAT 後的 spoke 去跑。可前面説了,hub 撥不進去。

解法是把方向掉個頭:worker-pull,長輪詢。

我不讓 hub 去推任務,而是讓 spoke 主動出站去 hub「拉」任務。Spoke 上常駐一個 worker,它去 long-poll hub 上的一個 /poll 端點——連接掛在那兒,hub 暫時沒活就把這個請求 hold 住不回,一旦有派給這台 spoke 的任務,立刻順着這條已經建立好的出站連接把任務吐回去。Spoke 在本地跑完自己的推理,再把結果 POST 回 hub。

妙就妙在:從 NAT 的視角看,全程都是 spoke 在出站。轉換表裏一直有它那條記錄,回包永遠找得到家。我用「出站長輪詢」把「入站不可達」徹底繞開了。這是穿 NAT 的經典招,不花哨,但可靠。

一些工程上的真實細節

跑通之後,有幾個點是實際運維裏才浮出來的。

成本。 A2A server 空閒時幾乎是 0 成本——它就掛在那兒等。只有任務真到達,才點火大模型推理。沒有任務,沒有賬單。這點讓我敢把它一直開着。

常駐。 Worker 必須活着,死了整條鏈路就斷。手機我用開機自啓加一個 keepalive 腳本兜底;Mac 上我換成了 launchd 守護進程——交給系統管比自己寫 keepalive 省心得多,掉了它會幫我拉起來。

安全。 明文 HTTP 在公網上裸跑是不能接受的,任務內容和結果都在線上飄。我儘快上了 TLS,並用 Bearer token 做鑑權。這不是可選項,是開着公網端點的最低門檻。

最後:連通性是入場券,不是護城河

把這張 mesh 搭通之後,我反而冷靜下來想了想它到底值多少。

連通性本身——A2A 協議、長輪詢、hub-spoke——正在被快速商品化。它是借來的開放協議,誰都能用,我用的招別人也能照搬。它是入場券,不是護城河。把這部分當成核心競爭力,是看錯了重點。

真正難抄、真正承重的是另一樣東西:驗證面。

當 agent 的數量上去、自主運行的時長拉長,一個「沒有痛覺」的系統會出大問題。它會默默跑偏,並且把錯誤一層層放大——agent 幹錯了事,系統自己根本不知道,只能靠我這個人肉「痛覺傳感器」事後去發現。機器越多、跑得越久,我能盯過來的比例就越小,失控面就越大。

所以我現在的判斷很明確:

在加更多機器之前,先給每一個跨機任務裝一個「可機器判定的驗收契約」,並且讓結果能回看。先裝痛覺,再加肌肉。

肌肉是算力節點,是更多的 spoke。痛覺是驗證迴路——每個任務派出去之前就定義好「什麼樣算成功」,回來之後機器能自動判一次,判不過就報警、就留痕。沒有這層,肌肉加得越多,系統失控的面積就越大,最後是負資產。

把網連起來只用了幾天,但我打算把接下來的時間,先花在給它裝上痛覺。