代理工作流程(Agentic Workflow)是一種多步驟系統,語言模型在其中不僅僅是回答一次:它會規劃、選擇工具、執行動作、檢查結果,並決定下一步該做什麼,直到任務完成。實務上,這意味著將 LLM 推理層與工具呼叫、真實執行環境以及評估迴圈結合。如果你正在建構程式碼代理、研究代理或需要在任務中途適應的內部自動化系統,這通常就是你實際上正在打造的架構。
什麼是代理工作流程?
代理工作流程是 AI 系統能夠逐步推進任務,而非止步於文字生成的背後模式。與其要求模型產生一個回應並直接回傳給使用者,你讓模型在一個受控的迴圈中運作:
- 讀取目標與當前狀態。
- 規劃下一步。
- 呼叫工具或執行程式碼。
- 觀察結果。
- 評估任務是否完成。
- 如有需要則重複。
這與固定工作流程不同,在固定工作流程中,每個步驟都預先寫在程式碼裡。在固定工作流程中,你預先決定了路徑。而在代理工作流程中,模型在你提供的邊界內決定下一步要採取哪個行動。
這個區別很重要,因為許多真實的開發者任務並非線性的。程式碼代理可能需要先檢查檔案,才知道要執行哪個測試。研究代理可能需要搜尋兩次,因為第一個來源不完整。瀏覽器代理可能需要從登入失敗或頁面佈局變更中恢復。這些都是工作流程問題,但它們需要適應性。
代理工作流程與 AI 代理有何不同?
人們經常互換使用這兩個術語,但將它們區分開來更有幫助:
- 代理工作流程 是執行模式。
- AI 代理 是建立在該模式之上的產品或系統。
你可以有一個範圍狹窄的代理工作流程,僅用於分類支援工單;或者一個更廣泛的 AI 代理,協調跨多個任務的規劃、工具使用、記憶與審批檢查點。
如果你想要一個實用的規則,當你在談論架構與控制流程時,請使用 工作流程;當你在談論面向使用者的系統時,請使用 ** 代理**。
代理工作流程的核心部分是什麼?
大多數生產系統最終都會包含相同的五個部分。
1. 規劃器
規劃器將廣泛的指令轉化為下一個具體行動。有時這是一個明確的規劃步驟,輸出一個任務清單。有時它是隱式的,發生在每個呼叫工具的回合中。無論哪種方式,模型都需要足夠的上下文來決定它應該讀取、寫入、搜尋、執行還是停止。
好的規劃並不意味著為每個請求產生一個長篇大論的大綱。它意味著讓下一步行動保持清晰可讀。對於簡短任務,單步驟規劃就足夠了。對於較長的任務,例如程式碼庫重構、瀏覽器自動化或文件審查,明確的規劃可以減少無效操作。
2. 工具層
工具是工作流程與世界互動的介面。一個強大的工具層通常範圍狹窄且可預測。例如:
read_file(path)write_file(path, content)search_files(query)run_command(cmd)fetch_url(url)
小型工具更容易讓模型正確呼叫、更容易記錄,也更容易確保安全。大型的「萬能」工具起初看起來很方便,但除錯起來很困難,因為你無法判斷失敗是來自模型決策、工具實作還是其背後的外部系統。
3. 執行運行時
一旦模型決定行動,就必須有東西來執行該動作。對於任何需要寫入檔案、安裝套件、執行程式碼或開啟瀏覽器會話的工作流程,此運行時都需要隔離。
這就是沙盒的用武之地。Novita Agent Sandbox 正是為此執行層而設計:一個獨立的環境,代理動作可以在其中執行,而不會直接觸及主機系統。這就是「模型建議了一個指令」與「工作流程安全地執行了該指令」之間的區別。
4. 狀態與記憶
代理工作流程需要跨步驟的工作記憶。這通常包括:
- 對話狀態
- 工具輸出
- 中間檔案
- 執行日誌
- 暫存區或簡短計畫
沒有狀態,每個步驟都會變成無狀態的提示工程,一旦任務跨越一個以上的動作,系統就會崩潰。
5. 評估迴圈
這是許多團隊太晚加入的部分。工作流程需要一種方法來判斷某個步驟是否成功,以及任務是否完成。在程式碼工作流程中,這可能意味著測試通過。在研究工作流程中,這可能意味著答案引用了足夠可靠的來源。在瀏覽器工作流程中,這可能意味著預期的 UI 狀態是可見的。
沒有評估,「代理」往往會變成「不斷呼叫工具直到超時」。
為什麼規劃在建構代理工作流程中很重要
建構代理工作流程時最大的錯誤是假設模型應該在每次輪換中從頭開始即興發揮所有事情。
這通常會產生三個問題:
- 模型反覆存取相同的檔案或 URL
- 工具使用變得嘈雜且昂貴
- 工作流程失去清晰的停止條件
一個更好的模式是輕量級規劃加上基於實際情況的執行。讓模型決定下一個動作,但要讓它根據明確的任務、可見的當前狀態和一組小型允許的工具來做決定。這在需要的地方保留了靈活性,並在不需要的地方移除了它。
在程式碼工作流程中,規劃通常如下所示:
- 識別涉及的檔案。
- 讀取當前實作。
- 決定最小的變更。
- 進行編輯。
- 執行驗證。
- 停止或修復。
這仍然是代理式的,因為當程式碼庫出現意外時,模型可以分支。但它不是漫無目的的。
工具在代理工作流程中應如何使用?
工具使用應該是明確的、有型別的,並且是可觀察的。
如果你的模型支援函式呼叫,請使用它。Novita 的 LLM API 提供了一個與 OpenAI 相容的端點,並直接記錄了函式呼叫,這是讓模型在工具之間進行選擇的最乾淨方式,而無需依賴脆弱的字串解析。
一些規則可以使工具使用更加可靠:
- 保持工具名稱具體。
- 使用具有必填欄位的架構。
- 回傳完整的結果,包括錯誤。
- 記錄每次呼叫、引數和輸出。
- 使破壞性動作罕見且易於控制。
工具層也應反映真實的邊界。例如,不要給程式碼代理一個名為 edit_repo_and_run_tests 的巨型工具。將讀取、寫入和執行步驟分開,以便模型在出現問題時可以恢復。
為什麼程式碼執行需要沙盒?
一個從不執行任何動作的代理工作流程通常可以留在普通的應用伺服器內。一旦它開始執行 shell 指令、安裝依賴項、處理下載的檔案或瀏覽開放的網路,你就需要隔離。
沙盒化解決了兩個不同的問題:
- 安全性:生成的程式碼和工具輸出可能是錯誤的、惡意的,或者根本無法預測。
- 狀態性:多步驟任務需要一個持久的工作空間,其中檔案、套件和執行歷史可以跨輪換存活。
對許多團隊來說,第二點與第一點同樣重要。一個編輯程式碼、執行測試、修復失敗並重新執行驗證的工作流程,如果每個步驟都從一台乾淨的機器開始,是不可能實現的。
這就是為什麼實務架構通常是:
- LLM API 用於規劃和工具選擇
- 沙盒運行時 用於執行和持久化
Novita 很適合這種拆分:LLM API 充當規劃器和工具呼叫層,而 Agent Sandbox 則處理實際的執行環境。
如何評估代理工作流程?
評估必須在兩個層級進行。
步驟層級評估
上一個動作有效嗎?
範例:
- 指令是否成功退出?
- API 是否回傳了有效的 JSON?
- 預期的檔案是否已建立?
- 瀏覽器頁面是否包含目標元素?
任務層級評估
工作流程是否解決了使用者的問題?
範例:
- 程式碼變更後測試是否通過?
- 摘要是否用證據回答了研究問題?
- 自動化是否完成了交易而無需手動清理?
強大的工作流程會同時使用兩者。如果你只評估最終輸出,你就會錯過執行過程中明顯的失敗訊號。如果你只評估步驟,工作流程可能會完成一長串局部有效的動作,但仍然無法完成真正的任務。
建構代理工作流程的實務架構
以下是大多數團隊應該開始使用的架構:
- 使用者請求進入你的應用程式。
- 你的控制器將目標、狀態和可用工具發送給 LLM。
- LLM 回傳直接答案或工具呼叫。
- 你的控制器在沙盒或其他受控運行時內執行該工具。
- 工具結果被附加到對話狀態。
- 評估器檢查完成、失敗或審批關卡。
- 迴圈繼續,直到工作流程完成或受阻。
這個控制器迴圈可以很簡單。在許多情況下,一個單一的編排器程序就足夠了。你不需要在第一天就建立一個多代理系統。從一個規劃器、幾個定義明確的工具、一個沙盒化運行時和一個清晰的評估器開始。
範例:一個 Python 的代理工作流程控制器
下面的範例展示了控制迴圈的形狀。它使用 Novita 與 OpenAI 相容的 API 進行工具呼叫。執行函數需要你根據自己的運行時或沙盒來實作。
import json
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.novita.ai/openai",
api_key=os.environ["NOVITA_API_KEY"],
)
tools = [
{
"type": "function",
"function": {
"name": "read_file",
"description": "從工作空間讀取檔案",
"parameters": {
"type": "object",
"properties": {"path": {"type": "string"}},
"required": ["path"],
},
},
},
{
"type": "function",
"function": {
"name": "run_command",
"description": "在沙盒中執行 shell 指令",
"parameters": {
"type": "object",
"properties": {"cmd": {"type": "string"}},
"required": ["cmd"],
},
},
},
]
def read_file(path: str) -> str:
# 根據你自己的工作空間或沙盒檔案系統實作此功能。
raise NotImplementedError
def run_command(cmd: str) -> str:
# 根據你的沙盒運行時實作此功能。
raise NotImplementedError
dispatch = {
"read_file": read_file,
"run_command": run_command,
}
def run_workflow(task: str, model: str) -> str:
messages = [
{
"role": "system",
"content": (
"你是一個工作流程控制器。在需要時使用工具,"
"在每個動作後檢查結果,並在任務完成時停止。"
),
},
{"role": "user", "content": task},
]
while True:
response = client.chat.completions.create(
model=model,
messages=messages,
tools=tools,
tool_choice="auto",
)
message = response.choices[0].message
messages.append(message)
if not message.tool_calls:
return message.content
for call in message.tool_calls:
fn = dispatch[call.function.name]
args = json.loads(call.function.arguments)
result = fn(**args)
messages.append(
{
"role": "tool",
"tool_call_id": call.id,
"content": result,
}
)
這是有意保持最小化的。在生產環境中,你還需要加入:
- 針對暫時性錯誤的重試策略
- 超時和預算限制
- 敏感操作的人工審批
- 結構化的步驟日誌
- 在最終完成前的任務層級評估器
應該使用哪個模型作為規劃器?
對於代理工作流程,規劃器模型不僅需要原始智慧。它還需要正確的特性:
- 可靠的工具呼叫
- 穩定的長上下文行為
- 強大的指令遵循能力
- 多輪深度下的可預測延遲
如果你想在 Novita 上找一個開放權重的起點,Qwen3 Coder 30B A3B Instruct 是工作流程規劃和程式碼導向工具使用的實用選擇。Novita 目前的模型頁面列出了與 OpenAI 相容的存取、函式呼叫支援、結構化輸出支援以及 160K 託管上下文視窗。對於許多內部自動化和程式碼任務來說,這足以建構一個嚴肅的初版,然後再遷移到更大或更專門的規劃器。
正確的模型仍然取決於工作。對於廣泛的、推理密集型的工作流程,首先選擇規劃品質。對於高容量的自動化,延遲和成本可能與基準強度同樣重要。
代理工作流程中的常見失敗模式
大多數失敗並不戲劇化。它們是重複且昂貴的。
過度工具化
如果每個能力都變成它自己的遠端依賴項,工作流程花在協調上的時間會比做有用工作的時間還多。
薄弱的停止規則
如果系統永遠不知道何時「完成」為真,它就會不斷地產生下一個步驟。
糟糕的錯誤處理
如果工具回傳「失敗」之類的模糊訊息,而不是可操作的輸出,模型就無法恢復。
沒有沙盒邊界
工作流程可能在開發中運作正常,但一旦接觸到真實的檔案、憑證或外部系統,就會變得不安全。
沒有評估器
代理看起來很忙碌,但從未證明任務已正確完成。
何時不應該使用代理工作流程?
不要僅僅因為這個術語流行就建構一個。
如果符合以下情況,你可能 不需要 代理工作流程:
- 任務是一次性的生成
- 路徑是固定的且很少改變
- 傳統程式可以廉價地決定每個步驟
- 不需要工具使用或執行
例如,如果你的應用程式總是接收一個表單輸入,呼叫一個提示,然後回傳一封格式化的電子郵件,那麼一個普通的 LLM 工作流程更簡單且更好。
當環境可能讓系統感到意外,而系統仍然需要繼續運作時,代理工作流程才會發揮價值。
常見問題
代理工作流程與函式呼叫相同嗎?
不。函式呼叫是工作流程內部的一種機制。完整的工作流程還需要控制流程、狀態、執行和評估。
我需要多個代理來建構代理工作流程嗎?
不。大多數團隊應該從一個控制器迴圈和幾個工具開始。多代理設計在以後會很有用,但它們不是預設的起點。
最重要的安全控制是什麼?
對於執行程式碼或觸及外部系統的工作流程,最重要的控制是隔離的執行環境,加上狹窄的工具權限。
最簡單的生產就緒堆疊是什麼?
一個好的初版堆疊是:一個與 OpenAI 相容的 LLM API、一個小型工具註冊表、一個沙盒化運行時,以及一個能夠決定任務何時真正完成的評估器。
