:從零搭建可運行 Agent 的完整路徑)
身邊不少做開發(fā)的朋友最近都在問同一個問題AI Agent 到底該怎么入門看了很多概念文章腦子里裝滿了 ReAct、Function Calling、多智能體協(xié)作這些詞但真讓自己動手搭一個又不知道從哪下手。我特別理解這種感覺因為我自己也是從那個階段過來的——文檔看了一堆Demo 跑不起來跑起來了又不知道能拿來干嘛。這篇內(nèi)容就是寫給這個階段的人看的。我不打算再重復(fù)一遍“Agent 是什么”的定義而是把從零搭一個能跑起來的 Agent 的完整路徑拆開講清楚需要哪些前置知識、核心機(jī)制到底怎么運轉(zhuǎn)、第一個練手項目選什么、代碼怎么寫、跑起來之后會遇到哪些坑。不管你是剛接觸這個方向的開發(fā)者還是已經(jīng)用過一些大模型 API 想往 Agent 方向深入的人都能從里面找到可以直接上手的東西。1. 先把認(rèn)知擺正Agent 不是更聰明的聊天機(jī)器人1.1 大多數(shù)人入門時踩的第一個認(rèn)知坑我見過太多人一開始就把 Agent 理解成“加了記憶的 ChatGPT”然后花大量時間研究怎么讓對話更連貫、怎么存歷史記錄。方向從一開始就偏了。聊天機(jī)器人的本質(zhì)是輸入文本、輸出文本它的能力邊界就是模型本身的知識和推理能力。而 Agent 的本質(zhì)是輸入目標(biāo)、輸出結(jié)果中間它自己決定要做什么、用什么工具、做幾步。這個差別聽起來簡單但它決定了你整個技術(shù)棧的選擇。舉個具體的例子。你讓聊天機(jī)器人“幫我查一下明天北京的天氣”它可能會告訴你“我無法獲取實時天氣信息”。但你讓 Agent 做同樣的事它會自己去調(diào)用天氣 API把結(jié)果拿回來整理成一句話給你。前者是“說”后者是“做”。這個“做”的能力才是 Agent 的核心價值。所以入門 Agent 的第一件事不是去學(xué)什么高級框架而是想清楚你要讓它“做”什么這個“做”的動作對應(yīng)的是哪個工具或 API想不清楚這一點后面學(xué)再多技術(shù)都是空中樓閣。1.2 Agent 的最小構(gòu)成三個部件缺一不可拋開那些花哨的概念一個能跑起來的 Agent 最小構(gòu)成其實就三塊大腦LLM負(fù)責(zé)理解目標(biāo)、拆解任務(wù)、決定下一步動作。它是決策中心不直接干活。手腳Tools真正執(zhí)行動作的模塊比如搜索、計算、讀寫文件、調(diào)用 API。LLM 決定“做什么”Tools 負(fù)責(zé)“怎么做”。循環(huán)Loop把大腦和手腳串起來的機(jī)制。Agent 不是一次決策就結(jié)束而是“思考→行動→觀察結(jié)果→再思考”這樣循環(huán)直到任務(wù)完成或達(dá)到終止條件。這三塊里新手最容易忽略的是循環(huán)。很多人寫 Agent 就是調(diào)一次模型、拿一次結(jié)果就結(jié)束了那本質(zhì)上還是個聊天機(jī)器人。真正的 Agent 必須有循環(huán)因為一次決策往往不夠——模型需要看到工具返回的結(jié)果才能決定下一步。我用一個生活化的類比幫你記住這個結(jié)構(gòu)Agent 就像一個剛?cè)肼毜膶嵙?xí)生。LLM 是他的腦子Tools 是他能用的辦公設(shè)備電腦、電話、打印機(jī)Loop 是他“接到任務(wù)→嘗試→看反饋→調(diào)整→再嘗試”的工作方式。你不可能指望實習(xí)生看一眼任務(wù)就完美交付Agent 也一樣循環(huán)是它逼近正確答案的手段。1.3 什么場景適合用 Agent什么場景別硬上這是我想特別強(qiáng)調(diào)的一點因為現(xiàn)在有種風(fēng)氣是“萬物皆可 Agent”結(jié)果很多簡單任務(wù)被搞得極其復(fù)雜。適合 Agent 的場景通常有三個特征任務(wù)步驟不固定沒法寫死流程、需要外部信息或操作模型自己搞不定、對過程容錯有一定容忍度允許試錯。比如“幫我調(diào)研某個話題并整理成報告”“根據(jù)我的需求篩選合適的房源”“自動處理一批格式混亂的數(shù)據(jù)”這些都很適合。反過來如果任務(wù)流程是固定的、確定性的比如“每天定時把 A 表的數(shù)據(jù)同步到 B 表”那你寫個腳本就行了用 Agent 反而是殺雞用牛刀還引入了不確定性。我自己的判斷標(biāo)準(zhǔn)很簡單如果這個任務(wù)的步驟能用 if-else 寫清楚就別用 Agent。提示入門階段最容易犯的錯是拿 Agent 去做確定性任務(wù)然后被它的不穩(wěn)定性折磨。先選一個真正需要“靈活決策”的場景你才能體會到 Agent 的價值。2. 動手前的技術(shù)準(zhǔn)備別急著寫代碼2.1 你需要具備的最低編程基礎(chǔ)我不建議完全零編程基礎(chǔ)的人直接上手 Agent因為調(diào)試過程會讓你非常痛苦。但你也不需要多深的功底能看懂和寫出下面這些就夠了Python 基礎(chǔ)函數(shù)、類、字典、列表、異常處理。Agent 開發(fā) 90% 的場景用 Python生態(tài)最全。HTTP 請求知道怎么用 requests 庫發(fā) GET/POST 請求因為大部分工具本質(zhì)就是調(diào) API。JSON 處理Agent 和模型之間、Agent 和工具之間傳數(shù)據(jù)基本都用 JSON得能熟練解析和構(gòu)造。異步基礎(chǔ)可選但推薦如果要做多工具并行調(diào)用async/await 會用到但入門階段可以先不碰。如果你這些還不熟我的建議是先花一周補(bǔ)一下 Python 和 HTTP 請求再回來搞 Agent。磨刀不誤砍柴工這個投入絕對值得。2.2 模型接口的選擇穩(wěn)定比強(qiáng)大更重要入門階段選模型我的核心建議是優(yōu)先選調(diào)用穩(wěn)定、文檔清晰、有免費額度的而不是一味追求最強(qiáng)模型。原因很實際。你入門時寫的代碼大概率會有各種 bug如果模型接口本身還不穩(wěn)定你根本分不清是自己的問題還是接口的問題。我早期就吃過這個虧用一個響應(yīng)時快時慢的接口調(diào)試排查了半天才發(fā)現(xiàn)是接口的問題白白浪費一晚上。具體選擇上國內(nèi)有幾家主流廠商都提供了兼容 OpenAI 格式的接口這意味著你可以用同一套代碼切換不同的模型。這個兼容性非常重要我強(qiáng)烈建議你入門時就用 OpenAI 格式的 SDK 來寫這樣以后換模型只需要改 base_url 和 api_key代碼幾乎不用動。# 用 OpenAI 兼容格式調(diào)用換模型只改這兩行 from openai import OpenAI client OpenAI( api_keyyour-api-key, base_urlhttps://your-provider.com/v1 # 換成對應(yīng)廠商的地址 ) response client.chat.completions.create( modelyour-model-name, messages[{role: user, content: 你好}] )這段代碼看著簡單但它是你后面所有 Agent 邏輯的基礎(chǔ)。把它跑通確認(rèn)能正常拿到返回再往下走。2.3 開發(fā)環(huán)境與調(diào)試工具的準(zhǔn)備環(huán)境這塊不用搞太復(fù)雜但有幾個東西我建議一開始就配好虛擬環(huán)境用 venv 或 conda 建一個獨立環(huán)境Agent 項目依賴容易沖突隔離一下省心。日志系統(tǒng)這是重中之重。Agent 的執(zhí)行過程是黑盒你必須把每一步的輸入輸出都打出來否則出了問題根本沒法排查。我習(xí)慣用 Python 的 logging 模塊把模型的思考、工具調(diào)用、返回結(jié)果都記下來。一個能看 JSON 的工具Agent 的數(shù)據(jù)流全是 JSON有個格式化查看的工具能省很多眼力。關(guān)于日志我要多說一句。很多人入門時圖省事用 print結(jié)果調(diào)試復(fù)雜 Agent 時滿屏輸出根本看不清。從一開始就用結(jié)構(gòu)化日志把每步的步驟編號、類型、內(nèi)容都標(biāo)清楚這個習(xí)慣能幫你省下大量排查時間。3. 拆解 Agent 的核心運轉(zhuǎn)機(jī)制3.1 ReAct 模式Agent 思考的基本節(jié)奏ReAct 是 Reasoning Acting 的縮寫是目前絕大多數(shù) Agent 的底層運轉(zhuǎn)模式。它的核心思想是讓模型在“思考”和“行動”之間交替進(jìn)行。具體流程是這樣的模型先輸出一段思考Thought說明它打算做什么然后輸出一個行動Action比如調(diào)用某個工具系統(tǒng)執(zhí)行這個工具把結(jié)果Observation返回給模型模型看到結(jié)果后再進(jìn)行下一輪思考。如此循環(huán)。我用一個查天氣的例子把這個流程走一遍你就能看明白用戶目標(biāo)幫我看看北京今天適不適合出門跑步 第1輪 Thought: 我需要先獲取北京今天的天氣信息 Action: get_weather(city北京) Observation: 北京今天晴氣溫 18-26 度空氣質(zhì)量良風(fēng)力 2 級 第2輪 Thought: 天氣不錯溫度適宜空氣質(zhì)量良適合跑步 Action: 無需更多工具直接回答 最終回答北京今天天氣很好18-26 度晴天空氣質(zhì)量良非常適合出門跑步??吹?jīng)]模型不是一次性給出答案的而是先決定“我需要天氣數(shù)據(jù)”拿到數(shù)據(jù)后再判斷“適不適合跑步”。這個“先行動、再基于結(jié)果推理”的過程就是 ReAct 的精髓。理解這個模式后你寫 Agent 的思路就清晰了你要做的是給模型提供工具然后設(shè)計一個循環(huán)讓它能反復(fù)“思考-行動-觀察”直到它認(rèn)為可以給出最終答案。3.2 Function Calling讓模型學(xué)會“調(diào)用工具”Function Calling 是讓 Agent 能真正干活的關(guān)鍵技術(shù)。簡單說就是你用結(jié)構(gòu)化的方式告訴模型“我這里有哪些工具可用每個工具需要什么參數(shù)”模型在需要時會返回一個結(jié)構(gòu)化的調(diào)用請求而不是普通文本。這個機(jī)制的價值在于模型輸出的不再是“我建議你查一下天氣”這種廢話而是明確的{name: get_weather, arguments: {city: 北京}}你的代碼可以直接解析并執(zhí)行。定義一個工具的格式大概長這樣tools [ { type: function, function: { name: get_weather, description: 查詢指定城市的實時天氣, parameters: { type: object, properties: { city: { type: string, description: 城市名稱如北京、上海 } }, required: [city] } } } ]這里有個新手常忽略的細(xì)節(jié)description 寫得好不好直接決定模型會不會正確使用這個工具。我見過有人把 description 寫成“查詢天氣”結(jié)果模型經(jīng)常傳錯參數(shù)或者在不該調(diào)用的時候調(diào)用。把 description 寫清楚——說明這個工具干什么、什么時候用、參數(shù)是什么格式——能大幅提升調(diào)用準(zhǔn)確率。3.3 循環(huán)控制什么時候該停什么時候該繼續(xù)循環(huán)控制是 Agent 里最容易被低估的部分。如果不設(shè)好終止條件Agent 可能陷入死循環(huán)反復(fù)調(diào)用同一個工具或者一直“思考”不給答案。我一般會設(shè)三重保險最大輪次限制比如最多循環(huán) 10 輪超過就強(qiáng)制結(jié)束并返回當(dāng)前結(jié)果。這是防止死循環(huán)的硬性兜底。模型主動終止當(dāng)模型認(rèn)為任務(wù)完成時它不再返回工具調(diào)用而是直接返回文本答案循環(huán)自然結(jié)束。異常終止工具調(diào)用連續(xù)失敗、或者返回結(jié)果明顯異常時主動中斷并報錯。max_iterations 10 for i in range(max_iterations): response call_model(messages, tools) # 模型不再調(diào)用工具說明它要給出最終答案了 if not response.tool_calls: return response.content # 執(zhí)行工具調(diào)用 for tool_call in response.tool_calls: result execute_tool(tool_call) messages.append({role: tool, content: result}) # 超過最大輪次強(qiáng)制結(jié)束 return 任務(wù)執(zhí)行超過最大輪次限制已中斷這段邏輯看著簡單但它是 Agent 能穩(wěn)定運行的基礎(chǔ)。我建議你入門時就把這個循環(huán)框架搭好后面所有 Agent 都是在這個骨架上加?xùn)|西。4. 第一個練手項目從最簡單的開始4.1 為什么選“天氣日程”這個組合入門項目我強(qiáng)烈推薦做“天氣查詢 日程建議”這個組合。原因有幾個第一它足夠簡單只需要兩個工具代碼量小你能快速跑通全流程。第二它天然需要多步推理——先查天氣再結(jié)合日程給建議能讓你完整體驗 ReAct 循環(huán)。第三天氣 API 和日程數(shù)據(jù)都容易獲取不用折騰復(fù)雜的鑒權(quán)。更重要的是這個項目能讓你把前面講的所有概念都實踐一遍定義工具、寫循環(huán)、處理工具返回、讓模型基于結(jié)果推理。跑通它你就掌握了 Agent 的核心骨架。4.2 工具函數(shù)的實現(xiàn)細(xì)節(jié)先寫兩個工具函數(shù)。天氣這個我用一個模擬函數(shù)代替真實 API方便你直接跑import json def get_weather(city: str) - str: 查詢城市天氣這里用模擬數(shù)據(jù)演示 mock_data { 北京: {condition: 晴, temp: 18-26, aqi: 良}, 上海: {condition: 多云, temp: 20-28, aqi: 優(yōu)}, } data mock_data.get(city, {condition: 未知, temp: 未知, aqi: 未知}) return json.dumps(data, ensure_asciiFalse) def get_schedule(date: str) - str: 查詢指定日期的日程安排 mock_schedule { 今天: [10:00 團(tuán)隊會議, 15:00 客戶溝通], 明天: [全天外出] } return json.dumps(mock_schedule.get(date, []), ensure_asciiFalse)注意工具函數(shù)的返回值我統(tǒng)一用了 JSON 字符串。這是個好習(xí)慣因為結(jié)構(gòu)化數(shù)據(jù)模型更容易理解也方便你后續(xù)擴(kuò)展。另外ensure_asciiFalse保證中文正常顯示不然會變成一堆轉(zhuǎn)義字符。4.3 把工具注冊給模型并跑通完整循環(huán)接下來把工具定義和循環(huán)邏輯拼起來tools [ { type: function, function: { name: get_weather, description: 查詢指定城市的實時天氣返回天氣狀況、溫度和空氣質(zhì)量, parameters: { type: object, properties: { city: {type: string, description: 城市名稱} }, required: [city] } } }, { type: function, function: { name: get_schedule, description: 查詢指定日期的日程安排日期可以是今天或明天, parameters: { type: object, properties: { date: {type: string, description: 日期如今天、明天} }, required: [date] } } } ] tool_map {get_weather: get_weather, get_schedule: get_schedule} def run_agent(user_input: str): messages [ {role: system, content: 你是一個生活助手可以查詢天氣和日程幫用戶做決策。}, {role: user, content: user_input} ] for i in range(10): response client.chat.completions.create( modelyour-model-name, messagesmessages, toolstools ) msg response.choices[0].message if not msg.tool_calls: return msg.content messages.append(msg) for tc in msg.tool_calls: func tool_map[tc.function.name] args json.loads(tc.function.arguments) result func(**args) messages.append({ role: tool, tool_call_id: tc.id, content: result }) return 超過最大輪次跑起來之后你輸入“今天適合出門嗎”就能看到 Agent 先查天氣、再查日程最后綜合給出建議。這個過程里你可以把 messages 打印出來完整看到模型的每一步思考這對理解 Agent 運轉(zhuǎn)非常有幫助。4.4 跑通之后可以做的三個擴(kuò)展第一個項目跑通后別急著換更復(fù)雜的場景先在這個基礎(chǔ)上做幾個擴(kuò)展把基本功練扎實加一個工具比如加個“查空氣質(zhì)量”或“查交通狀況”的工具體會多工具場景下模型如何選擇。加錯誤處理讓工具函數(shù)在參數(shù)錯誤時返回明確的錯誤信息觀察模型如何根據(jù)錯誤調(diào)整。加日志把每輪的 Thought、Action、Observation 都記下來形成完整的執(zhí)行軌跡。這三個擴(kuò)展做完你對 Agent 的理解會從“知道”變成“會用”。我自己的經(jīng)驗是第一個項目多花點時間打磨比急著做十個項目收獲更大。5. 進(jìn)階路上繞不開的幾個坑5.1 工具描述寫不好模型就亂調(diào)用這是新手最高頻的問題。模型決定調(diào)不調(diào)用工具、調(diào)用哪個、傳什么參數(shù)全靠你寫的 description。描述模糊模型就瞎猜。我總結(jié)了幾條寫 description 的經(jīng)驗說清楚工具做什么、什么時候用、參數(shù)什么格式、有什么限制。比如“查詢天氣”這種描述就太籠統(tǒng)改成“查詢指定城市的實時天氣包括天氣狀況、溫度區(qū)間和空氣質(zhì)量適用于需要了解當(dāng)前天氣的場景”就清楚多了。還有一個技巧如果某個工具容易和另一個混淆在描述里明確區(qū)分。比如你有“查當(dāng)前天氣”和“查未來天氣”兩個工具就要在描述里寫清楚各自適用場景否則模型經(jīng)常選錯。5.2 上下文爆炸多輪循環(huán)后 token 超限Agent 每循環(huán)一輪messages 就變長一截。跑個十幾輪token 很容易就超了模型的上下文限制然后報錯。解決思路有幾個。最簡單的是限制最大輪次從源頭控制長度。進(jìn)階一點的是做上下文壓縮把早期的工具返回結(jié)果精簡掉只保留關(guān)鍵信息。還有一種做法是把中間結(jié)果存到外部messages 里只放引用。我入門時最常用的還是限制輪次加精簡工具返回。工具返回別一股腦全塞進(jìn)去只返回模型決策需要的關(guān)鍵字段能省不少 token。5.3 模型“幻覺”調(diào)用不存在的工具有時候模型會調(diào)用一個你根本沒定義的工具或者參數(shù)格式完全不對。這在模型能力較弱或描述不清時特別常見。應(yīng)對方法是在執(zhí)行工具前做校驗檢查工具名是否在 tool_map 里參數(shù)是否符合預(yù)期格式。如果不符合把錯誤信息返回給模型讓它重新決策。這個“校驗-反饋-重試”的機(jī)制能大幅提升 Agent 的健壯性。def safe_execute(tool_name, args): if tool_name not in tool_map: return f錯誤工具 {tool_name} 不存在可用工具{list(tool_map.keys())} try: return tool_map[tool_name](**args) except Exception as e: return f錯誤工具執(zhí)行失敗 - {str(e)}把錯誤信息返回給模型它下一輪往往就能自我糾正。這個設(shè)計思路很重要不要假設(shè)模型永遠(yuǎn)正確而是給它糾錯的機(jī)會。5.4 調(diào)試?yán)щyAgent 是黑盒怎么辦Agent 最讓人頭疼的就是調(diào)試。它不像普通函數(shù)輸入輸出一目了然。Agent 中間經(jīng)過多輪推理和工具調(diào)用出問題時你根本不知道哪一步錯了。我的辦法是全程記錄執(zhí)行軌跡。每一輪的模型輸入、模型輸出、工具調(diào)用、工具返回全部記下來。然后出問題時把軌跡從頭到尾看一遍基本都能定位到問題環(huán)節(jié)。另外我建議分步驗證。先單獨測每個工具函數(shù)能不能正常工作再測模型能不能正確選擇工具最后測整個循環(huán)。這樣出問題時能快速縮小范圍不用在整條鏈路上瞎找。6. 從練手到實用下一步往哪走6.1 什么時候該引入框架第一個項目手寫循環(huán)完全沒問題但當(dāng)你開始做更復(fù)雜的 Agent 時手寫會越來越吃力。這時候可以考慮引入框架比如 LangChain、LlamaIndex 這些。但我的建議是先手寫至少兩個完整的 Agent再考慮用框架。因為框架幫你封裝了很多細(xì)節(jié)如果你不理解底層機(jī)制出了問題根本不知道怎么排查。手寫過的經(jīng)驗?zāi)茏屇阌每蚣軙r心里有底知道每一步在干什么。判斷該用框架的信號很簡單當(dāng)你發(fā)現(xiàn)自己反復(fù)在寫同樣的循環(huán)邏輯、工具注冊邏輯、上下文管理邏輯時就該考慮用框架來減少重復(fù)勞動了。6.2 多智能體協(xié)作的入門理解當(dāng)你單個 Agent 玩熟了可能會接觸到多智能體協(xié)作的概念。簡單說就是讓多個 Agent 分工合作比如一個負(fù)責(zé)規(guī)劃、一個負(fù)責(zé)執(zhí)行、一個負(fù)責(zé)審核。入門階段不用急著上手多智能體但可以理解它的核心思想把復(fù)雜任務(wù)拆給不同角色的 Agent每個 Agent 專注自己擅長的部分。這其實和人類團(tuán)隊協(xié)作是一個道理一個人什么都干容易顧此失彼分工明確效率更高。真要嘗試的話從兩個 Agent 的簡單協(xié)作開始比如一個負(fù)責(zé)收集信息、一個負(fù)責(zé)整理輸出跑通了再往上加。6.3 持續(xù)學(xué)習(xí)的方向建議Agent 這個方向變化很快但有些底層能力是長期有價值的值得持續(xù)投入提示詞工程怎么把指令寫清楚讓模型穩(wěn)定輸出你想要的結(jié)果這個能力永遠(yuǎn)有用。工具設(shè)計怎么設(shè)計工具的粒度和接口讓模型好用、好組合這是 Agent 效果的關(guān)鍵。評估方法怎么衡量一個 Agent 好不好用怎么系統(tǒng)性地發(fā)現(xiàn)和修復(fù)問題這是從玩具到產(chǎn)品的分水嶺。我自己的學(xué)習(xí)習(xí)慣是每學(xué)一個新概念就動手寫個小 Demo 驗證一下。看十篇文章不如跑通一個例子Agent 這個方向尤其如此它的很多坑只有親手踩過才記得住。最后分享一個我踩過的坑我一開始總想著一步到位設(shè)計一個能處理各種任務(wù)的“萬能 Agent”結(jié)果越寫越復(fù)雜最后哪個任務(wù)都做不好。后來我改成一次只解決一個具體問題把單個場景做扎實反而進(jìn)步快得多。Agent 入門窄而深比寬而淺重要得多。