- 12 min read

【Agentic Payment】Ghost Pay:Payment as Infrastructure,把 Agent 支付能力下沉到 Kubernetes 基礎設施層

以 Istio mTLS 與 Envoy Lua Filter 構建隱形支付攔截層,讓 Kubernetes 內的 Agent 零程式碼修改、零私鑰持有,就能自主完成 x402 鏈上微支付。核心理念:支付是基礎設施的責任,不是 Agent 的責任。

AI Agent Kubernetes Istio x402 EIP-3009 Payments Blockchain Ghost Pay Agentic Payment Agentic Economy

回顧基礎設施的演進史,有一條清晰的主線:越來越多的事情,不再需要應用程式自己處理。

基礎設施能力下沉的演進史:服務發現、認證、憑證管理相繼離開應用程式碼,下一個是支付

服務發現與流量治理曾經散落在每個服務的程式碼裡,後來交給了 Service Mesh;認證與限流曾經是每個 API 自己實作的責任,後來交給了 API Gateway;憑證管理與 mTLS 曾經是 SRE 半夜的惡夢,後來交給了 Sidecar 與 cert-manager。每一次「下沉」,應用程式碼都變得更乾淨,而那個能力反而變得更可靠。

那麼,下一個被下沉的能力會是什麼?我的答案是:AI Agent 支付。

這就是筆者開源的 ghost-pay 這個實驗專案想驗證的命題,它的核心哲學是 Payment as Infrastructure(支付即基礎設施):

支付是基礎設施的責任,不是 Agent 的責任。


問題背景:六行程式碼,仍然是程式碼

在 Agentic Payment 系列第四篇,我用 Golang 展示過 x402 SDK 的開發體驗:六行程式碼,你的 Agent 就能自動處理 402 Payment Required、簽署支付、完成鏈上結算。

→ 【Agentic Payment 系列 #4】從理論到實作:用 Golang 親手跑一遍 x402 支付流程

六行很少,但把場景從「一個 Demo」放大到「一個叢集裡的數十個 Agent」,SDK 模式的結構性問題就浮現了:

  1. 私鑰散落:每個需要付費的 Agent Pod 都得持有一把 EVM 私鑰。私鑰的數量與外洩面積成正比,這是任何資安團隊看了都會皺眉的架構
  2. 語言綁定:SDK 目前有 TypeScript 與 Golang 實作。你的 Python Agent、你的 legacy Java 服務呢?每多一種語言,就多一份要維護的支付邏輯
  3. 預算失控:支付決策分散在每個 Agent 內部,沒有一個中央位置能回答「某個團隊這個月花了多少錢」,也沒有辦法一鍵「把某個團隊的額度砍半」
  4. 程式碼侵入:就算只有六行,你還是得改 code、重新打包、重新部署跑一輪。更別說那些拿不到原始碼的第三方 Agent 映像檔,這條路根本走不通

這組問題似曾相識。把「支付」三個字換成「TLS」,就是 2016 年 Service Mesh 誕生前夜的處境:每個服務自己管憑證、自己實作加密、自己處理輪替。業界後來的答案不是「寫一個更好用的 TLS SDK」,而是把整件事搬出應用程式,放進 Sidecar。這就是 Istio、Linkerd 這些 Service Mesh 走的路。

Ghost Pay 對支付做了一模一樣的事。


核心架構:四個元件、三個 Namespace

Ghost Pay 在 Kubernetes 叢集裡部署了四個元件,用 Namespace 切出多租戶的費用隔離邊界:

元件Namespace角色
Ghost-News-Agentnews業務 Agent,採購加密貨幣市場情報
Ghost-Security-Agentsecurity業務 Agent,採購威脅情報與漏洞公告
Ghost-Paymasterghost-pay中央簽署服務,唯一持有 EVM 私鑰的元件
x402-Provider叢集外部真實的付費 API,在 BASE Sepolia 測試網收取 USDC

兩個業務 Agent 以 Google ADK 建構,但它們的程式碼裡沒有任何一行支付邏輯:沒有 x402 SDK、沒有私鑰、沒有錢包地址。對它們來說,付費 API 和免費 API 的呼叫方式完全相同,就是一個普通的 HTTP GET。

真正的魔法發生在 Istio 注入的 Envoy Sidecar 裡。


隱形攔截層:Envoy Lua Filter 的八步流程

Ghost Pay 用一個 EnvoyFilter 在業務 Agent 的 Sidecar 上掛載 Lua Filter,攔截所有外部回應。當付費資源回覆 402 挑戰時,完整流程如下:

  1. 業務 Agent 對外部付費資源發出普通的 HTTP GET
  2. x402-Provider 回覆 402 Payment Required,Header 內附上支付條件(價格、收款地址、鏈 ID)
  3. Envoy Sidecar 的 Lua Filter 攔截這個 402 回應,Agent 本身完全不知情
  4. Lua Filter 呼叫 Paymaster 的 POST /v1/pay,附上支付條件與來源 Namespace
  5. Paymaster 檢查該 Namespace 的預算餘額,通過後以 EVM 私鑰在本地簽署 EIP-3009 支付授權
  6. Paymaster 將 payment_signature 回傳給 Lua Filter
  7. Lua Filter 帶著 PAYMENT-SIGNATURE Header 重送原始請求
  8. x402-Provider 驗證簽名,透過 x402.org 的外部 Facilitator 完成 BASE Sepolia 上的鏈上結算,回傳 200 OK 與資源內容

從業務 Agent 的視角看,第 2 到第 7 步根本不存在。它發出一個請求,收到一個 200,中間那筆鏈上結算像 TCP 重傳一樣消失在網路層。這就是「隱形攔截」的意義:K8s Pod 零感知、零程式碼修改,即可跨越叢集邊界自主調用付費資源。

EIP-3009:為什麼業務 Pod 連 Gas 費都不用付

這套機制能成立,關鍵在於 x402 底層採用的 EIP-3009(Transfer With Authorization) 標準,但這不是所有 ERC-20 都支援的能力,而 Circle 的 USDC 正是原生實作此標準的代表,這也是 x402 選它作為結算資產的原因之一。傳統的鏈上轉帳需要付款方持有原生代幣(如 ETH)支付 Gas 費,這意味著每個錢包都得先「儲值兩種資產」才能動起來。

EIP-3009 把流程拆成兩段:付款方只做離線簽署(不需要 Gas),實際把交易送上鏈、支付 Gas 費的是 x402 的 Facilitator。這個 Gasless(免 Gas 費) 特性對 Ghost Pay 的架構至關重要:

  • Paymaster 的錢包只需要持有 USDC,不需要 ETH
  • 業務 Pod:連錢包都沒有,自然也沒有任何錢包私鑰要管理(免除資安風險)
  • 整個叢集的鏈上資產管理收斂到一個 Kubernetes Secret,甚至可以更進一步整合 AWS KMS 這類金鑰託管服務,讓私鑰完全不落地,需要簽署時才呼叫 KMS 完成(這已列在 Ghost Pay 的 TODO 裡)

簽署是純粹的密碼學運算,在 Paymaster 的記憶體裡毫秒級完成,這也讓 Lua Filter 的非同步委派不至於成為請求路徑上的瓶頸。


安全模型:Mesh 原生的信任邊界

把所有私鑰集中到 Paymaster,等於把雞蛋放進同一個籃子,所以這個籃子必須用叢集能提供的所有手段保護起來:

  • Istio mTLS 全面強制:所有 Pod 間通訊走雙向 TLS,Lua Filter 與 Paymaster 之間的支付委派流量無法被叢集內其他工作負載竊聽或偽造
  • AuthorizationPolicy 白名單:只有 news 與 security 兩個 Namespace 的身份(以 mTLS 的 SPIFFE identity 判定)可以呼叫 Paymaster 的 /v1/pay,其他任何來源一律拒絕。完整規則定義在 k8s/istio/authorization-policy.yaml
  • Namespace 預算隔離:Paymaster 為每個 Namespace 維護獨立額度,超額的支付請求會直接被擋下,單一租戶失控不會燒掉整個叢集的錢包。額度定義在 k8s/paymaster/configmap.yaml
  • 私鑰只存在於 Kubernetes Secret:不進 ConfigMap、不進 image、不進環境變數

值得注意的是預算隔離這一項:它讓「費用治理」第一次和 RBAC、ResourceQuota 站在同一個抽象層。平台團隊管理 Agent 的支付額度,用的是和管理 CPU limits 一樣的心智模型,一份 ConfigMap,一個 Namespace 一行。當然,實際的治理需求會比一份靜態設定檔更複雜,比如需要一個後台介面讓財務或平台團隊審核、動態增減各團隊的預算;但只要有「額度收斂在一個中央位置管理」這個基礎,之後想在上面加什麼治理工具,都是順理成章的事。

當支付額度變成一種 Namespace 級的資源配額,FinOps 和 Platform Engineering 的邊界就開始交集了。


動手跑一遍

專案提供了完整的自動化腳本,前置需求只有 Docker、kind 與一把 BASE Sepolia 測試網的私鑰(USDC 可以從 Circle Faucet 免費領取):

~$ git clone https://github.com/charles-hsiao/ghost-pay.git
~$ cd ghost-pay
~$ cp k8s/secrets.yaml.example k8s/secrets.yaml
# 編輯 secrets.yaml,填入 base64 編碼的測試網私鑰
~$ make all       # 建立 kind 叢集、建置映像檔、部署全部元件
~$ make demo      # 執行端到端支付流程
~$ make status    # 查看 Pod 狀態
~$ make teardown  # 清理環境

→ 【Agentic Payment 系列 #4】從理論到實作:用 Golang 親手跑一遍 x402 支付流程

make demo 會驅動兩個 Agent 分別採購市場情報與威脅情報,每一筆結算都可以在 Base Sepolia Scan 上查到對應的鏈上交易。Provider 也刻意放了一個 $20.00 的 ultra-premium-report 端點,用來驗證預算隔離確實會把超額請求擋下來。

實際互動可以參考以下截圖:

Paymaster 提供的 dashboard 可以即時觀察各 Namespace 的預算消耗與每一筆結算的鏈上交易:

Ghost-Paymaster dashboard:即時顯示各 Namespace 的預算額度、已消耗金額與每筆結算對應的鏈上交易

而在 Agent 這一端,整個支付流程完全隱形。在 news-agent 的對話介面裡,使用者只是請它去採購一份市場情報,背後的 x402 付款、簽署與鏈上結算全都由基礎設施層自動完成:

Ghost-News-Agent chat 介面:使用者請求採購市場情報,背後自動完成 x402 付款,Agent 對區塊鏈的存在毫無感知

Agent 回覆中的「View on Explorer」連結可以直接開啟 Base Sepolia Scan,查看對應的鏈上結算交易:

點擊 news-agent 回覆中的「View on Explorer」,在 Base Sepolia Scan 上查看對應的鏈上交易紀錄

同一筆交易也會即時反映在 Paymaster dashboard,並標記所屬的 Namespace:

Paymaster dashboard 顯示 news-agent 發起的交易與其所屬 namespace(news)

換到 security-agent 的對話介面,同樣的零感知體驗:使用者請求採購威脅情報,底層支付由基礎設施層靜默完成:

Ghost-Security-Agent chat 介面:使用者請求採購威脅情報,完成 x402 付款流程

Paymaster dashboard 同樣記錄了 security-agent 的交易,與 news namespace 的紀錄並列,費用完全隔離:

Paymaster dashboard 顯示 security-agent 發起的交易與其所屬 namespace(security)

當 news-agent 嘗試請求 $20.00 的 ultra-premium-report,超出 $2.00 的 namespace 預算上限,Paymaster 直接擋下這筆支付,業務 Agent 收到拒絕回應,而不是一筆超額的鏈上結算:

news-agent 嘗試超額請求 ultra-premium-report,Paymaster 以預算不足為由攔截,業務 Agent 收到拒絕而非完成支付

最後是 x402-Provider 端的 logs,可以清楚看到每一筆合法請求的結算紀錄,以及那筆被 Paymaster 在叢集內部就擋下、從未抵達 Provider 的超額請求:

x402-Provider logs:顯示合法結算請求的處理紀錄,超額請求由於被 Paymaster 攔截而未出現在此


誠實的邊界:這是實驗,不是產品

按照慣例,說清楚這個專案目前的定位。Ghost Pay 是一個驗證架構理念的實驗性專案,README 的 TODO 清單 毫不掩飾地列出了距離 production 的差距:

  • 私鑰託管:私鑰目前以 Kubernetes Secret 保存,正式環境應整合 AWS KMS 這類金鑰託管服務,讓私鑰完全不落地
  • 狀態管理:Paymaster 的預算與帳本目前存在記憶體,Pod 重啟即歸零,正式環境需要換成持久化資料庫
  • 併發限制:測試網 Facilitator 在高併發下會因 nonce 碰撞而結算失敗,缺少重試與排隊機制
  • Lua Filter 的簡化假設:重送邏輯目前寫死為 GET 且不支援 request body,結算回應的解析用的是正則而非嚴謹的 JSON 處理
  • 缺少 x402 service discovery:x402 endpoints 目前寫死在設定中,尚未整合 x402 Bazaar 的動態發現
  • 可觀測性缺口:沒有分散式追蹤、沒有 Prometheus 指標。一個替你花錢的系統卻沒有稽核軌跡,這件事在正式環境是不可接受的

值得注意的是,這些缺口都是工程問題,不是架構問題;沒有任何一項動搖「支付下沉到基礎設施層」這個核心命題。路已經證明是通的,剩下的只是把它鋪齊。


影響與啟示:當支付消失在背景

Ghost Pay 想證明的東西,其實在流程圖之外。

回頭看那條「下沉」的主線:TLS 下沉之後,沒有應用工程師再需要理解 X.509 憑證鏈;重試下沉之後,沒有人再手寫 exponential backoff。每一次能力下沉,換來的都是應用層的認知釋放,工程師得以把心力花在業務邏輯上。支付下沉的意義完全相同:Agent 的開發者應該思考的是「這份情報值不值得買」,而不是「EIP-3009 的 nonce 怎麼管理」。

這也呼應了系列第四篇結尾的那個觀察:基礎設施的偉大之處,在於它消失在背景中。沒有人在傳送 Email 時會想到 TCP/IP;同樣地,Ghost Pay 裡的 Agent 從頭到尾不知道區塊鏈的存在:402 Payment Required、EIP-3009、USDC、鏈上結算,全都隱身在基礎設施層。當叢集裡的 Agent 每天完成數千筆微支付、卻沒有任何一行業務程式碼提到「錢」這個字的時候,Agentic Payment 才算真正成為了基礎設施。

Service Mesh 用了五年時間,把 mTLS 從「先進團隊的炫技」變成「平台的預設值」。支付攔截層今天所處的位置,大概就是 mTLS 的 2017 年。而接下來必然要面對的那道問題:Payment-as-a-service 究竟是 Self-hosted 還是 Managed? 先劇透一下,其實這塊大餅已經有不少人在覬覦了,這邊挖個坑,之後再寫一篇文章來討論。


相關實作

延伸閱讀:【Agentic Payment 系列 #1】HTTP 402 沉睡三十年後醒來:x402 如何讓支付成為網際網路的一等公民

延伸閱讀:【Agentic Payment 系列 #4】從理論到實作:用 Golang 親手跑一遍 x402 支付流程