一個可以存取錢包的 AI 代理聽起來很強大。

但這也聽起來可能伴隨風險。

語言模型可能誤解請求、選擇錯誤的工具、重複動作,或自信地追求一開始就不該被允許的目標。若給予它不受限制的簽章權限,這些錯誤就會轉變為實際的交易。

Arc 14 的目標是打造比這更有用的東西。

在第 92–98 天,我們讓代理存取 Solana 資料,之後逐步加入工具、錢包、MCP 伺服器、政策引擎以及自主工作流程。

在每一個階段,相同的界線都維持不變:

模型可以決定它想做什麼。

程式碼決定它被允許做什麼。

代理從唯讀工具開始

第一個挑戰將風險控制在低水位。

我們使用 Claude 以及一組 Solana devnet 工具,建立一個小型代理迴圈。這個代理可以回答自然語言問題,例如:

  • 這個錢包持有多少 SOL?
  • 誰擁有這個帳戶?
  • 這個帳戶是否可執行?
  • 它儲存了多少資料?

這個模型從未直接連線到 Solana。

它不會建構任意的 RPC 請求,也不會獲得不受限制的網路存取權限。應用程式定義了一小組工具,描述每個工具的用途,並決定如何執行它們。

Claude 可以檢視這些描述並選擇要呼叫哪個工具,但周圍的應用程式仍保有控制權。

這樣的互動仍感覺像對話。

我們用白話文提出問題。

代理選擇了餘額工具。

應用程式呼叫 RPC 端點。

結果返回給模型。

模型再向我們解釋。

這段互動背後是一個簡單的迴圈:

  1. 使用者給予代理一個目標或問題。
  2. 模型決定是否需要工具。
  3. 應用程式驗證並執行工具呼叫。
  4. 結果返回給模型。
  5. 迴圈持續進行,直到模型可以回答為止。

模型提供判斷。

應用程式提供能力。

工具定義形塑了代理能做的事

每個工具都有四個重要部分:

  • 說明模型何時應該使用它的描述。
  • 定義模型可以請求什麼的輸入結構描述。
  • 決定實際發生什麼的實作。
  • 給予模型下一步證據的輸出。

這些細節很重要。

模糊的描述可能導致模型選擇錯誤的工具。

寬鬆的結構描述可能允許格式錯誤或模稜兩可的請求。

信任每個參數的實作可能將模型的錯誤轉變為系統問題。

即使是唯讀工具也需要界線。

餘額工具應該接受有效的 Solana 地址。

帳戶檢查工具應該返回有用的結構化中繼資料。

錯誤應該以模型可以推理的形式返回,而不會對開發者隱藏原始細節。

提示詞描述了我們希望代理的行為方式。

工具定義確立了它實際上可以要求應用程式做什麼。

接著我們給了代理一個錢包

第 93 天提高了風險等級。

代理收到自己的 devnet 錢包以及兩項新能力:

  • 檢查餘額。
  • 傳送 SOL。

這將它從唯讀助理轉變為能夠改變鏈上狀態的系統。

錢包屬於應用程式,而非模型。

其私鑰保留在建構和簽署交易的程序內。它從未被插入提示詞、返回在工具結果中,或透過模型上下文暴露。

模型不需要金鑰。

它只需要一個接受建議收款人與金額的工具。

應用程式接著可以決定是否建構和簽署交易。

這種分離很重要,因為模型上下文不是存放機密的安全場所。

提示詞、工具呼叫、記錄和回應可能被儲存、檢視或在元件之間傳遞。放在那裡的私鑰可能意外洩漏或在產生的輸出中重複出現。

將金鑰保留在簽署層內,意味著模型可以請求動作,而無需擁有執行該動作所需的憑證。

代理可以要求傳送 0.05 SOL 到某個地址。

只有應用程式可以將該請求轉變為已簽署的交易。

轉帳限制存在於程式碼中

我們並未依賴提示詞來限制代理可以傳送多少 SOL。

轉帳工具執行硬性上限。

如果建議金額超過該限制,應用程式會在建構交易前拒絕請求。

我們可以告訴模型永遠不要傳送超過 0.1 SOL 的金額。它可能大多數時候都會遵循該指令。

但提示詞可能被誤解、被衝突的指令覆蓋,或被不一致地應用。

程式碼層級的檢查行為不同。

如果金額過高,轉帳就不會發生。

不管請求多麼有說服力都沒關係。

不管模型聽起來多麼自信都沒關係。

不管建議的動作看起來是否支持更廣泛的目標都沒關係。

簽署層會拒絕。

這就是涉及金錢、權限和不可逆動作的規則應該存在的地方。

單一轉帳上限還不夠

每筆轉帳限制可以防範單一大額交易。

但它無法阻止代理進行許多小額交易。

被限制為每次轉帳 0.1 SOL 的代理,仍可能嘗試十次轉帳,總共花費 1 SOL。

這說明為什麼轉帳工具內部的驗證只是開始。

更廣泛的系統還需要決定:

  • 哪些收款人是被允許的?
  • 一筆交易可以傳送多少?
  • 整個工作階段可以花費多少?
  • 代理可以進行多少次工具呼叫?
  • 迴圈可以持續多久?
  • 交易失敗後應該發生什麼?
  • 哪些動作需要被記錄?

這些決定屬於專用的政策層,而非散落在提示詞和工具實作中。

MCP 讓工具可重複使用

第 94 天將 Solana 工具移至 Model Context Protocol 伺服器。

在此之前,這些工具只存在於一個應用程式內。

這雖然可行,但將能力綁定在特定的代理實作上。

MCP 伺服器讓它們變得可重複使用。

它暴露了用於以下任務的工具,例如:

  • 讀取錢包餘額。
  • 檢查鏈上金庫狀態。
  • 呼叫受保護的程式指令。

任何相容的 AI 用戶端都可以透過相同的協議發現並使用這些工具。

伺服器描述了可用的內容,接受結構化請求並返回結構化結果。

這類似於 Arc 13 中 IDL 扮演的角色。

IDL 讓 Solana 程式可被軟體發現。

MCP 讓面向代理的能力可被 AI 用戶端發現。

有用的部分不只是另一個用戶端可以呼叫這些工具。

錢包金鑰和安全規則仍留在伺服器上。

新的用戶端不會獲得對兩者的直接存取權。

它獲得與其他每個用戶端相同的受控介面。

這意味著我們可以更換模型、桌面用戶端或代理框架,而無需重建 Solana 整合或將權限移至新用戶端。

伺服器仍是信任邊界

MCP 讓工具更容易被發現和重複使用。

但它並沒有讓每個用戶端都值得信任。

相容的用戶端可以請求工具呼叫,但伺服器仍必須驗證它。

用戶端可能配置錯誤。

模型可能選擇錯誤的工具。

使用者可能請求超出預期範圍的動作。

請求可能包含無效地址或過大金額。

伺服器仍負責:

  • 驗證工具輸入。
  • 套用政策檢查。
  • 保護私鑰。
  • 建構和簽署交易。
  • 返回有用的錯誤訊息。
  • 記錄發生的事情。

工具結果也是不受信任的。

鏈上文字和中繼資料可能由其他人撰寫。返回給模型的備忘錄、代幣名稱或解碼的帳戶欄位可能包含意圖影響其行為的指令。

應用程式不能僅因為內容來自工具,就將其視為可信任的指導。

即使敵對資料改變了模型的推理,相同的政策規則仍控制什麼可以被簽署。被污染的回應可能影響模型提出的內容,但無法擴大允許清單、提高支出上限或重設工作階段預算。

這延續了 Arc 12 的安全教訓。

不受信任的輸入不限於交易帳戶。它也包括代理讀取並帶入其上下文的資料。

我們建立了預設拒絕的政策引擎

第 95 天將簡單的轉帳上限轉變為適當的政策層。

建議的轉帳會被拒絕,除非它通過每項規則。

政策檢查:

  • 收款人是否為有效的 Solana 地址。
  • 收款人是否出現在允許清單上。
  • 金額是否低於每筆轉帳上限。
  • 工作階段總支出是否仍在預算內。

應用程式在模型上下文之外追蹤累積支出。

代理無法記住、重設或重新解釋自己剩餘的預算。政策引擎會根據應用程式擁有的工作階段狀態進行計算。

這是一個預設拒絕的設計。

系統不會尋找拒絕轉帳的理由。

它要求轉帳滿足所有條件才能獲得核准。

如果任何檢查失敗,交易就不會被簽署。

缺少允許清單條目會導致拒絕。

格式錯誤的地址會導致拒絕。

超過上限的金額會導致拒絕。

耗盡的工作階段預算會導致拒絕。

意外的輸入不會落入執行階段。

它會停止。

意圖和權限是分開的問題

模型的工作是推理目標。

政策引擎的工作是決定建議的動作是否符合規則。

代理可能正確計算出錢包缺少 0.4 SOL。

但這並不意味著它有權限轉帳 0.4 SOL。

金額可能超過每筆轉帳上限。

目的地可能不在允許清單上。

剩餘的工作階段預算可能只有 0.2 SOL。

因此,即使模型的推理正確,最終結果也可能是拒絕。

這是系統的一個重要特性。

它的安全性並不依賴於模型每次都做出正確的安全決策。

模型可能犯錯、過度自信、被使用者操縱,或受到敵對工具輸出的影響。

對於相同的建議動作和相同的工作階段狀態,政策應該產生相同的結果。

模型行為是可變的。

政策行為應該是可預測的。

拒絕是正常的系統行為

被拒絕的動作不一定是錯誤。

有時這正是系統按照設計運作。

如果代理建議將資金傳送到允許清單之外的地址,政策引擎會拒絕請求並返回原因。

代理接著可以決定下一步要做什麼。

它可能告訴使用者該動作不被允許。

它可能要求不同的收款人。

它可能建議較小的轉帳。

它可能得出結論,在目前的限制下無法完成目標。

這比將每次拒絕都視為導致工作流程崩潰的例外狀況要好。

政策結果成為代理可以推理的資訊。

被核准的動作可以繼續進行簽署。

被拒絕的動作會帶回結構化的解釋。

代理可以適應該決定,但無法覆蓋它。

自主工作流程整合了所有內容

第 96 天將代理迴圈、錢包工具和政策引擎結合在目標導向的工作流程中。

範例目標是確保儲蓄錢包至少持有指定數額的 SOL。

代理需要:

  1. 檢查儲蓄錢包餘額。
  2. 將其與目標進行比較。
  3. 計算任何不足金額。
  4. 檢查資金錢包。
  5. 提出轉帳建議。
  6. 讓建議通過政策。
  7. 提交已核准的交易。
  8. 驗證新餘額。
  9. 記錄發生的事情。

這不只是一次工具呼叫後回答問題。

代理必須檢查目前狀態,決定是否需要採取行動,在限制範圍內行動,然後檢查結果。

最後的驗證很重要。

交易簽章顯示交易已提交。

但它本身並不能證明目標已達成。

代理再次讀取鏈上狀態,並與目標進行比較。

這就完成了迴圈:

觀察。

推理。

行動。

驗證。

正常、受限和不可能的情境表現不同

我們在多種條件下測試了工作流程。

在正常情況下,目標錢包低於最低餘額,資金錢包有足夠的 SOL,且所需的轉帳通過政策。

代理計算不足金額,請求轉帳並驗證新餘額。

在受限情況下,目標只能在轉帳上限和剩餘工作階段預算內達成。

代理必須在這些限制內運作,而非簡單地選擇最直接的動作。

在不可能的情況下,政策或可用資金使目標無法達成。

收款人可能不在允許清單上。

不足金額可能超過工作階段預算。

資金錢包可能沒有足夠的 SOL。

代理可能推理正確,但仍無法完成目標。

這不是系統的失敗。

正確的行為是停止、解釋限制並維護政策邊界。

「無法繼續」有時是正確的結果。

回合限制防止無限迴圈

代理迴圈需要停止條件。

如果沒有,模型可能會持續呼叫工具、重試失敗的動作,或無限期地重新檢視相同的推理。

Arc 14 包含明確的回合限制,因此應用程式可以在固定步驟數後停止工作流程。

這可以防止意外迴圈,並限制單一請求可能消耗的時間、代幣和網路活動量。

回合限制是一個簡單的控制,但它解決了代理系統的一個真實特性。

模型決定下一步要做什麼。

應用程式決定允許它持續決策多久。

其他系統也可能使用時間限制、工具呼叫限制或特定動作的核准閘道。

確切的控制方式可能不同。

重要的是代理無法自行授予無限時間或無限嘗試次數。

結構化記錄讓工作流程可檢視

當我們只能看到最終答案時,自主行為很難被信任。

因此,工作流程會為每個重要步驟寫入結構化記錄。

這些記錄可以記錄:

  • 代理收到的目標。
  • 它選擇了哪個工具。
  • 它提出的參數。
  • 相關的政策決定。
  • 為什麼動作被核准或拒絕。
  • 交易簽章。
  • 驗證步驟的結果。
  • 最終結果。

這建立了系統從原始目標移動到結果的追蹤。

這些記錄對除錯很有用,但其價值遠不止於此。

它們顯示代理是否正確解讀目標。

它們揭示政策引擎是否套用了預期的規則。

它們讓重複的動作變得可見。

它們提供了成功工作流程已驗證其工作的證據。

它們也讓拒絕更容易解釋。

如果沒有記錄,我們可能只知道轉帳沒有發生。

有了記錄,我們可以看到收款人不在允許清單上,或剩餘預算太低。

自主系統需要這種證據。

最終回應是不夠的。

文件迫使我們描述邊界

第 97 天從建構系統轉向解釋系統。

我們撰寫了一份公開的技術演練,涵蓋:

  • 代理迴圈。
  • 可用的工具。
  • MCP 伺服器。
  • 錢包邊界。
  • 政策引擎。
  • 工具合約。
  • 整體架構。
  • 實際執行的記錄。

最重要的區別在於可變和不變的行為。

模型的推理是可變的。

它可能選擇不同的工具、以不同的方式表述解釋,或採取另一條路徑達成相同的目標。

政策層是不變的。

相同的建議動作和工作階段狀態,無論模型如何解釋其意圖,都應該產生相同的核准決定。

這讓架構更容易理解。

代理的安全不是因為模型被指示要如何行為。

它是安全的,因為模型只能透過執行固定規則的程式碼才能接觸到簽署能力。

文件需要確切顯示該邊界存在於何處。

工具合約與提示詞同樣重要

代理系統的公開演練很容易變成冗長的提示詞解釋。

提示詞很重要,但它們只是這個 Arc 的一部分。

更有力的材料在於工具合約和政策規則。

轉帳請求需要哪些欄位?

政策之前進行了哪些驗證?

拒絕後返回了哪個政策結果?

私鑰存放在哪裡?

累積的工作階段支出儲存在哪裡?

哪個元件建構了交易?

工作流程如何確認成功?

工具呼叫和政策決定是如何被記錄的?

不受信任的工具輸出如何被阻止繞過簽署規則?

這些細節解釋了系統實際上可以保證什麼。

提示詞描述了預期的行為。

工具合約定義了模型可以請求的動作。

政策引擎定義了哪些請求可以繼續進行。

簽署者控制什麼可以到達網路。

記錄顯示了發生了什麼。

這就是完整的安全故事。

最終示範同時展示了動作和拒絕

第 98 天將工作流程轉變為簡短的錄製示範。

示範從自然語言目標開始。

代理檢查餘額、選擇工具、提出動作並通過政策。

已核准的交易出現在 devnet 上,可以在鏈上驗證。

但示範也需要展示拒絕。

這與成功的轉帳同樣重要。

一個可以移動資金的系統很容易示範。

一個可以拒絕不安全或不允許請求的系統更具說服力。

拒絕顯示,即使模型提出動作,政策引擎仍保有控制權。

因此,最有用的示範包括:

  • 原始目標。
  • 代理的工具呼叫。
  • 政策決定。
  • 已核准動作的交易簽章。
  • 產生的鏈上狀態。
  • 被政策拒絕的請求。
  • 拒絕的原因。

這讓邊界變得可見,而非要求觀眾相信它們存在於程式碼的某處。

Arc 14 教會了我們什麼

Arc 14 不是關於將錢包交給 AI 模型並期望最好的結果。

而是關於在保留控制權的系統內建構代理。

在這個 Arc 結束時,我們學會了如何:

  • 圍繞明確定義的 Solana 工具建構代理迴圈。
  • 將網路存取和私鑰保留在模型上下文之外。
  • 將工具結果和鏈上資料視為不受信任的輸入。
  • 在應用程式程式碼中執行轉帳限制、允許清單和預算。
  • 將可重複使用的 Solana 能力封裝在 MCP 伺服器中。
  • 在不同的 AI 用戶端上套用相同的安全規則。
  • 執行觀察、行動和驗證的工作流程。
  • 在模型之外追蹤工作階段狀態。
  • 限制代理回合並記錄結構化的執行記錄。
  • 示範已核准和已拒絕的動作。

核心教訓是自主性和權限不是同一件事。

模型可以決定哪個工具可能有幫助。

它可以解讀目標。

它可以計算不足金額。

它可以提出轉帳。

它可以解釋拒絕。

但它不持有私鑰。

它不決定哪些收款人被允許。

它不設定自己的支出上限。

它不記住或重設自己的工作階段預算。

它不覆蓋政策引擎。

模型進行推理。

程式碼持有權限。

重溫 Arc 14 挑戰

第 92 天:建構一個透過定義工具回答問題的唯讀 Solana 代理

第 93 天:給予代理一個 devnet 錢包,同時將其金鑰和支出限制保留在程式碼中

第 94 天:將 Solana 工具封裝為可重複使用的 MCP 伺服器

第 95 天:建構具有允許清單和預算的預設拒絕政策引擎

第 96 天:執行並驗證自主錢包管理工作流程

第 97 天:記錄代理架構、工具合約、政策規則和執行記錄

第 98 天:錄製公開示範,同時展示成功的動作和政策拒絕