:第一次實現(xiàn)——先做一個最小 Agent)
發(fā)布時間2026-09-1標簽AI Agent工程實踐MVP最小實現(xiàn)架構(gòu)畫得再漂亮也只是紙上的東西。上一篇我畫了四個節(jié)點Task Router、Planner、Analyzer、Reviewer。聽起來很完整對吧但我決定一個都不實現(xiàn)。這一篇我只寫最窄的一條通路用戶問 → 調(diào)一個工具 → 讀結(jié)果 → 回答。原因很簡單我想看看這個最小可跑的版本到底會怎么死。系列導航上一篇AI Agent 工程實踐38從需求到 Agent 架構(gòu)——為什么需要這些節(jié)點下一篇AI Agent 工程實踐40第一次失敗——Agent 為什么會做錯問題背景這是第五階段的第四篇也是第一次真正寫代碼。很多人會犯一個錯架構(gòu)圖里畫了四個節(jié)點就非得把四個都寫出來才罷休。但我的經(jīng)驗是——先做一個故意很蠢的最小版本讓它跑起來然后用它去暴露問題。這個最小版本有個學名叫 MVPMinimum Viable Product但在這里它的意義不是證明能跑而是用最快的速度暴露它會怎么死。為什么暴露死亡這么重要因為 Agent 項目最大的風險不是寫不出來而是寫了很多但里面的假設全是錯的。你架構(gòu)圖里畫的 Planner、Reviewer可能根本解決不了真實問題——而這些問題只有讓最小版本跑起來、撞上真實問句才會顯現(xiàn)。所以我這一篇砍掉 Task Router、砍掉 Planner、砍掉 Reviewer只保留一個 LLM 兩個工具grep 和 read_file讓整條鏈路能跑通。錯誤嘗試我差點犯了兩個反方向的錯。第一個錯想一步到位。想把四個節(jié)點、六個工具、Memory、評估集全部寫完再跑。結(jié)果就是寫了一個月一行能跑的代碼都沒有還積累了一堆我以為對的假設。這一堆以為對的假設是最貴的。比如我以為LLM 會自己選對工具直到真實跑起來才發(fā)現(xiàn)它經(jīng)常選錯我以為讀到文件就能定位 bug直到真實跑起來才發(fā)現(xiàn)它會編造不存在的函數(shù)。這些假設只有讓代碼真的跑起來才會被證偽——而一步到位的寫法讓你把所有假設都攢到最后一起爆。第二個錯覺得太簡單不值得跑。一個 LLM 兩個工具這有什么好跑的 但我告訴你恰恰是這個最簡單的版本暴露了后面整整十篇要解決的問題。你只有真的跑起來才能看到它選錯工具、讀錯文件、憑空編造結(jié)論的樣子。兩個錯誤殊途同歸都推遲了第一次看到真實失敗的時間點。這里我要特別強調(diào)一個心態(tài)在 Agent 開發(fā)里先跑起來的優(yōu)先級高于架構(gòu)正確。因為 Agent 的行為極度依賴真實執(zhí)行環(huán)境你畫在紙上的架構(gòu)有一半會在第一次真實運行時被推翻。與其花一個月搭一個看起來正確的架構(gòu)不如花兩天搭一個一定能跑的最小版然后用真實失敗去修正架構(gòu)。關(guān)鍵觀察所以這篇的核心動作就一個用最短的路徑讓 Agent 第一次真正跑起來然后誠實地記錄它為什么不能直接上線。最小版本長這樣沒有任何花哨的東西。一個循環(huán)LLM 決定調(diào)工具 → 工具執(zhí)行 → 結(jié)果塞回上下文 → LLM 繼續(xù)直到它覺得該回答了。核心洞察MVP 的意義不是證明能跑而是用最快的速度暴露它會怎么死。這個最小版的價值不在于它能做什么而在于它把Agent 運行的每一個環(huán)節(jié)都攤開在你面前LLM 決策、工具選擇、參數(shù)傳遞、結(jié)果解析、終止判斷——每一個環(huán)節(jié)都可能出問題而這些問題只有最小版能讓你一個一個看清楚。最終方案100 行的最小 Agent下面是 Repo Doctor v0 的完整實現(xiàn)用 Python 手寫一個 tool-calling loop不依賴任何框架就是為了看清每一環(huán)# repo_doctor/v0/main.py —— 最小可跑版本約 100 行 import subprocess, json from openai import OpenAI client OpenAI(base_urlhttps://api.deepseek.com, api_key...) SYSTEM 你是倉庫診斷助手。你可以調(diào)用工具來調(diào)查代碼庫。 可用工具 - grep(keyword): 在倉庫中搜索關(guān)鍵字返回匹配的文件和行 - read_file(path): 讀取指定文件內(nèi)容 調(diào)查充分后直接輸出結(jié)論。 TOOLS [ {type: function, function: { name: grep, description: 在倉庫中搜索關(guān)鍵字返回匹配的文件和行, parameters: {type: object, properties: { keyword: {type: string}}, required: [keyword]}}}, {type: function, function: { name: read_file, description: 讀取指定文件內(nèi)容, parameters: {type: object, properties: { path: {type: string}}, required: [path]}}}, ] def call_tool(name, args, repo): if name grep: r subprocess.run([grep, -rn, args[keyword], repo], capture_outputTrue, textTrue, timeout10) return r.stdout[:3000] or (無匹配) if name read_file: with open(f{repo}/{args[path]}, encodingutf-8, errorsignore) as f: return f.read()[:3000] return (未知工具) def run_agent(query, repo, max_steps6): messages [{role: system, content: SYSTEM}, {role: user, content: f倉庫路徑 {repo}問題{query}}] for _ in range(max_steps): resp client.chat.completions.create( modeldeepseek-chat, messagesmessages, toolsTOOLS) msg resp.choices[0].message if msg.tool_calls: messages.append(msg) for tc in msg.tool_calls: result call_tool(tc.function.name, json.loads(tc.function.arguments), repo) messages.append({role: tool, tool_call_id: tc.id, content: result}) else: return msg.content return 達到最大步數(shù)仍未完成 if __name__ __main__: print(run_agent(這個項目里支付相關(guān)的邏輯在哪, /path/to/hello-agents))跑一次輸出大概長這樣結(jié)論支付相關(guān)邏輯在 payment.py 中核心函數(shù)是 payment_process() 它負責訂單支付和回調(diào)處理。建議查看該函數(shù)附近的 payment_callback()。這一版能跑。但先別急著高興我們仔細看這個結(jié)論——它有一個致命的問題payment_process()這個函數(shù)倉庫里根本不存在。它是 Agent 編出來的。下一篇會專門解剖這個失敗。在進入為什么不能上線之前先把這 100 行代碼的每個關(guān)鍵環(huán)節(jié)點一遍你就知道最小版到底暴露了哪些環(huán)節(jié)代碼片段環(huán)節(jié)潛在問題最小版就埋著SYSTEMTOOLS提示與工具描述工具描述含糊LLM 會選錯工具第 41 篇修call_tool工具執(zhí)行參數(shù)不校驗、結(jié)果截斷 3000 字符第 44 篇修for _ in range(max_steps)終止控制最大 6 步可能沒查完就?;驘獾?41 篇修messages.append上下文管理無限增長長任務爆上下文第 45 篇修r(nóng)eturn msg.content輸出結(jié)論無證據(jù)校驗幻覺直接進答案第 40、42 篇修這段 100 行代碼每一行都對應著后面一篇要解決的問題。這就是最小版的價值——它不是最終產(chǎn)品的閹割版而是問題清單的具象化。架構(gòu)圖 / 流程圖把上面代碼的執(zhí)行流程畫出來你會看到它的樸素看著很正常對吧但問題就藏在最后一步——那個payment_process()到底存不存在Agent 根本沒驗證。第二張圖這個循環(huán)的隱患標注版發(fā)布提示可用 draw.io 重畫成正式圖與 Mermaid 圖形成雙圖組合用戶問句 │ ▼ ┌────────────┐ ① 工具描述含糊 → 可能選錯工具40/41 篇 │ Agent(LLM) │──────────────────────────────┐ └─────┬──────┘ │ │ ② 參數(shù)不校驗 → 可能傳錯參數(shù)41 篇 │ ▼ │ ┌────────────┐ ③ 結(jié)果截斷 3000 字符 │ │ call_tool │ 可能丟關(guān)鍵信息44 篇 │ └─────┬──────┘ │ │ ④ 結(jié)果塞回上下文無校驗 │ ▼ │ ┌────────────┐ ⑤ 結(jié)論無證據(jù)檢查 │ │ Agent(LLM) │ 幻覺直接進答案40/42 篇 │ └─────┬──────┘ │ │ ⑥ 輸出結(jié)論 │ ▼ │ 答案 ?───────────────────────────────────┘ payment_process() 可能是編的這張圖把最小版的每一個薄弱環(huán)節(jié)都標了出來。后面整整十篇就是逐個把這些隱患標注換成已修復。為什么不能直接上線這一版跑通了但我把它能跑和能上線分得很清。下面這張清單就是我故意留的技術(shù)債也是后面整整十一篇的伏筆#技術(shù)債后果后面哪篇解決1沒有 Task Router三種任務混在一起該定位時去解釋472沒有 Planner查夠了沒全憑感覺草率下結(jié)論 / 燒 Token40、413工具描述太模糊參數(shù)沒約束選錯工具、傳錯參數(shù)41、424沒有 Reviewer結(jié)論無證據(jù)鏈幻覺成災payment_process()可能不存在40、425沒有 State調(diào)查過程不記錄無法回溯為什么這樣想426沒有評估集改完好壞不知道越改越玄學437上下文無上限讀文件會撐爆長文件直接溢出44、498出錯就死無兜底工具報錯整個流程崩449無法復現(xiàn)模型/Prompt/工具都沒鎖版本同一個問題兩次答案不同4510沒有成本/延遲監(jiān)控燒多少 Token 全靠猜46這一篇的價值就是把上面這十個坑提前擺在明面上。它們不是以后可能會出問題而是現(xiàn)在就已經(jīng)埋下了只等真實問句來引爆。設計權(quán)衡候選方案優(yōu)點缺點為什么不選一步到位寫完整架構(gòu)一次成型一個月跑不起來積累一堆未驗證假設推遲了看到真實失敗的時間用 LangGraph 框架搭省事、規(guī)范掩蓋底層細節(jié)出了問題看不懂先手寫 loop看清每一環(huán)100 行手寫最小版快、透明、暴露問題功能殘缺最快暴露它會怎么死關(guān)于為什么不用 LangGraph值得單獨說不是 LangGraph 不好而是在這個階段你需要的不是框架的便利而是對每一環(huán)的可見性。手寫 loop你能精確看到LLM 這次調(diào)了什么工具、傳了什么參數(shù)、工具回了什么。等這套東西你想清楚了第 49 篇再談要不要換成框架。常見誤區(qū)FAQQ1MVP 越少越好是不是連工具都只留一個最少兩個。一個工具比如只留 read_file無法暴露工具選擇這個環(huán)節(jié)的問題——而工具選錯恰恰是 Agent 最常見的失敗之一第 40 篇的 Tool Selection Error。Q2為什么不用 LangGraph 搭 MVP對初學者來說框架會掩蓋每一環(huán)發(fā)生了什么。手寫 100 行 loop你被迫面對工具調(diào)用、參數(shù)解析、結(jié)果回填這些最底層的問題——這些問題在框架里被封裝了你直到出 bug 才知道它們存在。Q3這 100 行代碼最后會被扔掉嗎不會全扔。它的工具調(diào)用循環(huán)骨架會被保留后續(xù)的 Task Router、Planner、Reviewer 都是在這個骨架上加節(jié)點而不是推倒重來。MVP 不是一次性用品是后續(xù)版本的可運行的基線。Q4怎么判斷 MVP夠了一個簡單標準它能完整跑完一次端到端任務哪怕結(jié)果錯誤。能跑 會錯就是最好的 MVP 狀態(tài)——因為下一步就是去解剖它怎么錯的第 40 篇。總結(jié)? 先做最小可跑版本故意砍掉所有高級節(jié)點。? 100 行手寫 loop就是為了看清每一環(huán)。? 這 100 行里每一行都對應一篇后續(xù)要解決的問題。? 這一版能跑但埋了 10 個技術(shù)債。? 鐵律MVP 的意義不是證明能跑而是最快暴露它會怎么死。? 下一篇讓這個最小版跑真實案例看它第一次做錯。參考資料OpenAI Function Calling 文檔 → 為什么引用tool-calling loop 的 API 用法是這 100 行的基礎?!禩he Pragmatic Programmer》tracer bullet 概念 → 為什么引用先打通一條最小鏈路再擴展正是本篇的方法論來源。系列導航上一篇AI Agent 工程實踐38從需求到 Agent 架構(gòu)——為什么需要這些節(jié)點下一篇AI Agent 工程實踐40第一次失敗——Agent 為什么會做錯本文是 [AI Agent 工程實踐] 系列的第 39 篇。