AI Agent 系列 · 第 1 篇 / 全 3 篇

AI Agent - 開篇:這個系列要做什麼

這個系列要做什麼

過去一年多,我的工作重心變成幫公司把 AI Agent 接進既有系統:

接內部 API、接資料庫、接那些十年前寫的、沒有文件的老服務。

過程中查資料常常很挫折,網路上的文章不是太淺(Hello World 呼叫一次 API 就結束),就是太玄(名詞飛來飛去,落地的程式碼一行都沒有)。

所以跟當年寫 Nchan 系列一樣,我打算把踩過的坑和整理過的解法完整記錄下來。

為什麼要自己打造 Agent

先回答最常被問的問題:都有 ChatGPT / Copilot 了,為什麼要自己寫?

因為現成產品在幾種情況下會直接卡死。

第一種是資料流向要能控制。有人會說,接 OpenAI 或 Claude 的 API,資料一樣是送到別人的伺服器上,沒錯。但自己寫 Agent,你能決定送出去的是什麼:敏感欄位先遮罩、個資先去識別化;合規要求高的,可以改接 Azure OpenAI 或 AWS Bedrock 這類留在自家雲租戶裡的服務;真的不行,還能落地端跑開源模型。用現成產品,整段對話原文直接送出去,這些你都沒得選。

第二種是流程長在你家。「幫我查這張單的物流狀態,異常的話開工單並通知值班」,這句話背後是四個內部系統。現成產品不認識你的系統,也永遠不會認識。

還有成本問題。按人頭訂閱的產品,用量一大帳單就失控。自己接 API 才能挑模型、控 token,算得出每一次呼叫花多少錢。

Agent 其實就是一個 for 迴圈

先講清楚 Agent 到底是什麼。

扣掉行銷名詞,核心長這樣:

for {
    resp := llm.Chat(messages, tools)

    if resp.ToolCalls == nil {
        return resp.Text // 沒有工具要呼叫,回答完成
    }

    for _, call := range resp.ToolCalls {
        result := execute(call)                  // 真正去查資料庫、打 API
        messages = append(messages, result.Msg)  // 把結果塞回對話
    }
}

模型決定要用什麼工具,你去執行,把結果還給模型,直到它說好了。

這個迴圈本身沒什麼難的,難的是細節:

  • tools 要怎麼定義,模型才不會亂用?
  • execute 失敗的時候,要重試還是換條路?
  • messages 塞爆 context window 之前,要丟掉什麼、留下什麼?
  • 改了 prompt 之後,怎麼知道 Agent 是變聰明還是變笨?

這幾個問題每一個都夠寫一篇,這也就是這個系列的內容。

系列規劃

大綱如下,寫完一篇勾一篇,順序可能會調整:

  • 開篇:這個系列要做什麼(本篇)
  • Agent 的基本迴圈:LLM + Tool Use 從零寫一次
  • Tool 的定義與設計:讓模型好好用你的工具
  • 錯誤處理:工具壞掉時 Agent 該怎麼辦
  • Context 管理:對話太長之後的取捨
  • 記憶與狀態:跨對話的 Agent 長什麼樣
  • RAG 與知識庫:把內部文件餵進去
  • 多 Agent 協作:什麼時候該拆、什麼時候是過度設計
  • 評測:怎麼知道 Agent 變好還是變笨
  • 部署與成本:模型選擇、token 帳單、降級策略
  • 實戰:把 Agent 接進一個真實的老系統

這個系列的慣例

這個領域迭代速度很快,每篇文章都會標注當時使用的模型與 SDK 版本。半年後如果照做不能動,留言跟我說,我盡量補註。

程式碼以 Go 為主,概念是通用的,用 Python 的人換個語法就能照做。完整範例會放在 GitHub,文章裡只貼關鍵片段。

沒踩過的坑不寫,沒上過線的架構不推薦。

下一篇就從那個 for 迴圈開始,把它真的寫出來。

留言