Agent demo 影片很迷人,但把它放上線,第一個壞掉的通常不是 LLM。
過去一年,LangGraph、CrewAI、AutoGen、OpenAI Agents SDK 這類框架陸續成熟,社群把焦點放在「讓多個 Agent 互相協作」這件事上。但真正接過生產案的工程師會發現:模型本身的幻覺反而是相對好處理的部分,難的是它周圍那一圈工具、狀態、重試與權限控制。
真正會在凌晨叫醒你的不是模型
把 Agent 拆開看,它其實是三件事疊在一起:一個會講話的 LLM、一組它能呼叫的工具(function calling 或 MCP),以及一個記住「現在做到哪」的狀態機。Demo 之所以順,是因為工具往往只有兩三個、狀態淺、輸入乾淨。
上了線就不一樣了。舉個例子,假設一家電商想做客服 Agent,工具清單可能包括查訂單、查物流、開退款單、查促銷規則、寄信通知。這時會冒出一堆「模型沒錯,但系統爆了」的狀況:
- 工具回傳格式偶爾有 null,Agent 把 null 當字串塞進下一個工具參數,整條鏈炸掉。
- 使用者中途改主意,Agent 還記得三輪前的舊意圖,回覆牛頭不對馬嘴。
- LLM 在重試時又呼叫了一次「開退款單」,因為它不知道前一次其實已經成功。
- 工具呼叫被 rate limit 擋下,框架的預設行為是直接拋例外,而不是退讓重試。
這些都不是 prompt 寫得好就能解的,是標準的分散式系統問題,只是換了個 LLM 的外殼。
上線前該先想清楚的幾件事
如果你正在評估要不要把 Agent 放進產品,我們的經驗法則是:先把下面幾題答出來,再決定要不要動工。
第一,工具呼叫要不要 idempotent? 任何會「改變外部狀態」的工具——開單、扣款、寄信——都應該設計成可重複呼叫不會出事的形式,例如帶 client-side request id。LLM 一定會重試,這是設計前提,不是 bug。
第二,狀態存在哪? 把整段對話塞 context window 是 demo 寫法。正式系統需要一個明確的 state store,能夠 checkpoint、能 rollback、能讓人工接手。LangGraph 的 checkpointer、Temporal、甚至自己刻一張 Postgres 表都可以,重點是有一個「事實來源」,不是 LLM 的記憶。
第三,誰來決定停止? Agent 最危險的就是它會自己決定要不要再 loop 一次。沒有最大步數、沒有預算上限、沒有 human-in-the-loop 的退出條件,就等著看 token 帳單。
第四,觀測性怎麼做? 傳統 APM 看不懂 Agent。最起碼要把每一次 LLM 呼叫、每一個工具的輸入輸出、每一次決策的理由都記下來,並且可以用 trace id 串起來。Langfuse、LangSmith、Arize 都是選項,自己包一層 OpenTelemetry 也行。
下面是一個示意的最小骨架,講的是「工具呼叫要帶 request id」這個概念:
# 示意:實際接 API 請參考各框架官方文件
def call_refund_tool(order_id: str, request_id: str):
# 後端用 request_id 做去重,重複呼叫只會回上次結果
return refund_api.post(
order_id=order_id,
idempotency_key=request_id,
)
看起來很普通,但這一行 idempotency_key 就是 Agent 上線後睡得著覺的關鍵。
我們的觀察
Agent 不是「更聰明的 chatbot」,它本質上是一個由 LLM 驅動的工作流引擎。判斷一個團隊是不是真的把 Agent 做穩了,不要看它 demo 多炫,看它如何處理工具失敗、如何重試、如何讓人類介入。把這幾題答清楚之前,先別急著鋪太多 Agent 上去;答清楚之後,你會發現框架選哪一個其實沒那麼重要。
