構(gòu)建高性能多智能體應(yīng)用與TaoToken統(tǒng)一Key接入)
1. 先搞清楚 Agno 是什么、能做什么、適合誰Agno 是一個(gè)用 Python 寫的多智能體框架核心賣點(diǎn)就三個(gè)字快、輕、穩(wěn)。你在 GitHub 上看到的那些 awesome-llm-apps 項(xiàng)目里大量 Agent 應(yīng)用都是拿它搭的star 數(shù)已經(jīng) 34k提交頻率也高不是那種半年不更新的玩具庫。它能做的事情覆蓋很廣單個(gè) Agent 帶工具跑任務(wù)、多個(gè) Agent 組成 Team 協(xié)作、用 Workflow 編排穩(wěn)定輸出流程還能掛知識(shí)庫、記憶模塊、會(huì)話存儲(chǔ)工具層面原生支持 MCP。適合誰如果你是剛接觸 Agent 開發(fā)的新手之前只寫過簡單的 OpenAI API 調(diào)用那 Agno 的上手曲線算是平緩的——定義一個(gè) Agent 只要幾行代碼不需要你先學(xué)一套復(fù)雜的圖編排 DSL。如果你是從 LangGraph 遷過來的會(huì)發(fā)現(xiàn) Agno 在實(shí)例化開銷上明顯更省官方那個(gè) 1000 次帶工具 Agent 實(shí)例化的對(duì)比測(cè)試?yán)飼r(shí)間和內(nèi)存都占優(yōu)。如果你是要做多智能體協(xié)作鏈路的Team 機(jī)制把 Leader 和 Member 的職責(zé)分得很清楚不用自己手寫調(diào)度邏輯。但這里有個(gè)現(xiàn)實(shí)問題不管框架多好用模型調(diào)用這一層你總得配。Agno 支持 OpenAILike 這種兼容接口意味著你可以把任意兼容 OpenAI 協(xié)議的服務(wù)接進(jìn)來。我這次的做法是用 TaoToken 的統(tǒng)一 Key 作為模型通道一個(gè) Key 覆蓋多個(gè)模型省得在 Agno 里為每個(gè)模型維護(hù)一套 base_url 和 api_key。下面從環(huán)境初始化開始一步步把單 Agent、帶存儲(chǔ)的會(huì)話、帶工具的 Agent、再到 Team 協(xié)作鏈路全部跑通每一段都給可復(fù)制的配置和預(yù)期輸出。先說清楚本文的驗(yàn)證目標(biāo)跑通一個(gè)「新聞 Agent 天氣 Agent」的 TeamLeader 根據(jù)用戶問題自動(dòng)分派任務(wù)最終返回聚合結(jié)果。中間會(huì)經(jīng)過單 Agent 冒煙測(cè)試、會(huì)話存儲(chǔ)驗(yàn)證、工具調(diào)用驗(yàn)證三個(gè)關(guān)卡任何一關(guān)卡住都能在排錯(cuò)章節(jié)找到對(duì)應(yīng)報(bào)錯(cuò)。2. TaoToken 前置準(zhǔn)備統(tǒng)一 Key 與模型通道配置在寫 Agno 代碼之前先把模型通道準(zhǔn)備好。TaoToken 的角色是給你一個(gè)統(tǒng)一的 API 入口和 KeyAgno 這邊只需要按 OpenAILike 的方式填 base_url、api_key、model id 三個(gè)值就行。這一步不涉及任何復(fù)雜配置但順序別搞反先拿 Key再確認(rèn)模型 ID最后寫進(jìn)代碼。第一步打開官網(wǎng) https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注冊(cè)并登錄進(jìn)入控制臺(tái)??刂婆_(tái)里找到 API Keys 頁面路徑是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentconsole 點(diǎn)創(chuàng)建新 Key復(fù)制出來保存好。這個(gè) Key 就是后面所有配置里的api_key值格式通常是一串以固定前綴開頭的字符串別弄丟頁面關(guān)閉后不一定能再次完整查看。第二步確認(rèn)你要用的模型 ID。Agno 的 OpenAILike 需要傳id參數(shù)這個(gè) id 必須和服務(wù)端支持的模型名完全一致。你可以在模型對(duì)話頁面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chat 里先手動(dòng)發(fā)一條消息驗(yàn)證模型可用頁面上會(huì)顯示當(dāng)前可選的模型列表。選一個(gè)你打算長期用的比如通用的對(duì)話模型或者代碼能力強(qiáng)的模型把它的 ID 記下來。本文示例里我用一個(gè)通用對(duì)話模型你替換成自己賬號(hào)下可用的即可。第三步確認(rèn) API 基礎(chǔ)地址。TaoToken 的 API 入口是 https://taotoken.net/api 注意這里不帶任何查詢參數(shù)直接作為 base_url 使用。Agno 的 OpenAILike 內(nèi)部會(huì)在這個(gè) base_url 后面拼/chat/completions所以你不要自己再加/v1之類的后綴填https://taotoken.net/api就行。這一點(diǎn)很容易踩坑后面排錯(cuò)章節(jié)會(huì)專門講。把這三個(gè)值整理成一張對(duì)照表寫代碼時(shí)直接對(duì)照填配置項(xiàng)值說明base_urlhttps://taotoken.net/api不帶 /v1不帶查詢參數(shù)api_key控制臺(tái)創(chuàng)建的 Key以實(shí)際復(fù)制為準(zhǔn)model id模型對(duì)話頁確認(rèn)的 ID必須與服務(wù)端一致注意Key 不要硬編碼進(jìn)提交到 Git 的代碼里本文示例為了直觀直接寫在代碼中你實(shí)際項(xiàng)目里請(qǐng)用環(huán)境變量或.env文件讀取。如果你后續(xù)打算長期跑編碼類 Agent 或者多智能體流水線可以順帶看一下 Coding Plan 頁面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_plan 它面向的是持續(xù)編碼和 Agent 場(chǎng)景的用量方案和本文的入門驗(yàn)證不沖突先跑通再考慮。3. 可復(fù)制配置環(huán)境初始化與 Agent 定義片段這一節(jié)是全文的核心操作區(qū)所有代碼都可以直接復(fù)制運(yùn)行。先建虛擬環(huán)境再裝依賴然后寫模型配置文件最后逐層往上搭 Agent 和 Team。3.1 環(huán)境初始化與依賴安裝建議用 Python 3.10 以上版本Agno 對(duì)異步和類型標(biāo)注用得比較多版本太低容易出兼容問題。命令如下python -m venv agno-env source agno-env/bin/activate pip install -U agno openai python-dotenvWindows 下激活命令換成agno-env\Scripts\activate。裝完之后驗(yàn)證一下python -c import agno; print(agno.__version__)能打印出版本號(hào)就說明裝好了。如果報(bào)ModuleNotFoundError檢查是不是虛擬環(huán)境沒激活或者 pip 裝到了全局環(huán)境。3.2 模型配置文件統(tǒng)一 Key 接入新建一個(gè)model_config.py把 TaoToken 的統(tǒng)一 Key 通道封裝成一個(gè)可復(fù)用的模型對(duì)象。這樣后面所有 Agent 和 Team 都導(dǎo)入同一個(gè)對(duì)象改模型只改一處import os from dotenv import load_dotenv from agno.models.openai import OpenAILike load_dotenv() TAOTOKEN_API_KEY os.getenv(TAOTOKEN_API_KEY, sk-你的Key) TAOTOKEN_BASE_URL https://taotoken.net/api MODEL_ID os.getenv(TAOTOKEN_MODEL_ID, 你的模型ID) open_ai_like_model OpenAILike( idMODEL_ID, base_urlTAOTOKEN_BASE_URL, api_keyTAOTOKEN_API_KEY, )配套的.env文件TAOTOKEN_API_KEYsk-你的Key TAOTOKEN_MODEL_ID你的模型ID這里三個(gè)參數(shù)必須齊全id是模型 IDbase_url是https://taotoken.net/apiapi_key是控制臺(tái)拿到的 Key。少任何一個(gè)都會(huì)在請(qǐng)求階段報(bào)錯(cuò)具體報(bào)錯(cuò)對(duì)照見第 5 節(jié)。3.3 單 Agent 冒煙測(cè)試新建single_agent.py先驗(yàn)證最小可用鏈路from agno.agent import Agent from model_config import open_ai_like_model agent Agent( modelopen_ai_like_model, description你是一個(gè)簡潔的中文助手, markdownTrue, ) agent.print_response(用兩句話介紹你自己, streamTrue)運(yùn)行python single_agent.py預(yù)期看到流式輸出兩句話的自我介紹。這一步通了說明 Key、base_url、模型 ID 三者都對(duì)后面再往上加存儲(chǔ)和工具。3.4 帶會(huì)話存儲(chǔ)的 Agent 配置會(huì)話存儲(chǔ)用 SQLite 最省事不用額外起數(shù)據(jù)庫服務(wù)。新建agent_with_db.pyfrom agno.agent import Agent from agno.db.sqlite import SqliteDb from model_config import open_ai_like_model db SqliteDb(db_filetmp/agno_session.db, session_tableagno_session) agent Agent( description你是一個(gè)小助手, modelopen_ai_like_model, dbdb, add_history_to_contextTrue, num_history_runs2, ) agent.print_response(我叫小林記住我的名字, user_idu-001, session_ids-001) agent.print_response(我叫什么名字, user_idu-001, session_ids-001)關(guān)鍵參數(shù)兩個(gè)add_history_to_contextTrue讓歷史消息進(jìn)入上下文num_history_runs2控制帶幾輪歷史。第二次提問時(shí) Agent 應(yīng)該能答出「小林」這就是會(huì)話存儲(chǔ)生效的證據(jù)。tmp目錄不存在的話先mkdir tmp否則 SQLite 建庫會(huì)報(bào)路徑錯(cuò)誤。3.5 帶工具的 Agent 配置工具用自定義函數(shù)最直觀也方便你理解工具描述是怎么傳給模型的。新建agent_with_tool.pyfrom agno.agent import Agent from model_config import open_ai_like_model def get_weather(city: str) - str: 查詢指定城市的天氣。 Args: city(str): 城市名稱。 return f{city} 今天晴氣溫 22 到 28 度微風(fēng)。 agent Agent( modelopen_ai_like_model, tools[get_weather], description你是一個(gè)天氣助手, markdownTrue, debug_modeTrue, ) agent.print_response(杭州今天天氣怎么樣, streamTrue)debug_modeTrue會(huì)把編譯后的系統(tǒng)提示詞和工具調(diào)用日志打出來你能看到模型是怎么決定調(diào)用get_weather的。函數(shù) docstring 里的 Args 描述很重要模型靠它判斷參數(shù)含義寫清楚能顯著降低調(diào)用失敗率。3.6 Team 多智能體協(xié)作配置最后把兩個(gè) Agent 組成 Team新建team_demo.pyfrom agno.agent import Agent from agno.team import Team from agno.utils.pprint import pprint_run_response from model_config import open_ai_like_model def get_news(topic: str) - str: 獲取指定話題的最新新聞。 Args: topic(str): 新聞話題。 return f關(guān)于 {topic} 的最新消息某科技公司發(fā)布了新一代開源框架。 def get_weather(city: str) - str: 查詢指定城市的天氣。 Args: city(str): 城市名稱。 return f{city} 今天晴氣溫 22 到 28 度微風(fēng)。 news_agent Agent( modelopen_ai_like_model, roleNews agent, tools[get_news], description負(fù)責(zé)獲取最新新聞, ) weather_agent Agent( modelopen_ai_like_model, roleWeather agent, tools[get_weather], description負(fù)責(zé)查詢未來三天天氣, ) team Team( modelopen_ai_like_model, nameNews and Weather Team, members[news_agent, weather_agent], ) result team.run(input杭州今天天氣怎么樣, debug_modeTrue) pprint_run_response(result)這段配置里Team的model是給 Leader 用的負(fù)責(zé)判斷把任務(wù)分給哪個(gè) Member每個(gè) Member 的role和description是 Leader 做路由決策的依據(jù)寫清楚比寫花哨更重要。運(yùn)行后預(yù)期看到 Leader 把「杭州天氣」這個(gè)任務(wù)分派給weather_agent最終輸出天氣結(jié)果。4. 驗(yàn)證請(qǐng)求與成功結(jié)果從單 Agent 到 Team 鏈路配置寫完不算完得逐層驗(yàn)證。我按「單 Agent → 會(huì)話 → 工具 → Team」的順序走一遍每一層給出你該看到的輸出特征對(duì)不上就停下來排查別急著往上疊。第一層單 Agent 冒煙。運(yùn)行single_agent.py終端應(yīng)該流式吐出兩句話內(nèi)容大意是「我是一個(gè)基于大模型的助手可以回答問題、協(xié)助寫作」。如果輸出為空或者報(bào) 401直接跳到第 5 節(jié)看認(rèn)證類報(bào)錯(cuò)。如果輸出是亂碼或者截?cái)鄼z查streamTrue下終端編碼Windows 可以臨時(shí)chcp 65001。第二層會(huì)話存儲(chǔ)。運(yùn)行agent_with_db.py第一次提問后tmp/agno_session.db文件應(yīng)該被創(chuàng)建出來用sqlite3 tmp/agno_session.db .tables能看到agno_session表。第二次提問的輸出里應(yīng)該出現(xiàn)「小林」這個(gè)名字。如果第二次答不出名字檢查session_id和user_id兩次是否一致以及add_history_to_context是否為 True。第三層工具調(diào)用。運(yùn)行agent_with_tool.py因?yàn)殚_了debug_modeTrue你會(huì)先看到一段系統(tǒng)提示詞日志里面有工具名get_weather和參數(shù)說明然后看到模型返回的工具調(diào)用請(qǐng)求參數(shù)是{city: 杭州}接著工具返回天氣字符串最后模型組織成自然語言回答。預(yù)期最終輸出類似「杭州今天晴氣溫 22 到 28 度微風(fēng)」。如果模型沒調(diào)工具而是直接編了個(gè)天氣說明工具描述不夠清晰或者模型沒理解把 docstring 寫得更具體再試。第四層Team 協(xié)作。運(yùn)行team_demo.pydebug_modeTrue下你能看到 Leader 的系統(tǒng)提示詞里列出了兩個(gè) Member 的 ID、role 和工具列表。預(yù)期日志順序是Leader 分析問題 → 決定委派給weather_agent→weather_agent調(diào)用get_weather→ 返回結(jié)果給 Leader → Leader 匯總輸出。最終pprint_run_response打印的結(jié)果里應(yīng)該包含杭州天氣信息且不包含新聞內(nèi)容說明路由正確。再補(bǔ)一個(gè)組合問題的驗(yàn)證把team.run的輸入改成「杭州天氣怎么樣順便看看有什么科技新聞」預(yù)期 Leader 會(huì)同時(shí)或依次委派給兩個(gè) Member最終輸出里天氣和新聞都有。這一步能驗(yàn)證多 Member 協(xié)作是否真的生效而不是只走了單條分支。如果你想把驗(yàn)證過程做成可重復(fù)的腳本可以在每個(gè)文件末尾加斷言比如檢查輸出字符串里是否包含關(guān)鍵詞。這樣每次改配置后跑一遍比肉眼看輸出可靠。驗(yàn)證通過后這套配置就可以作為你后續(xù)項(xiàng)目的骨架換模型只改model_config.py加 Agent 只加 Member。5. 本篇常見錯(cuò)排查401、local proxy failed、reading choices、OAuth這一節(jié)按真實(shí)報(bào)錯(cuò)來每個(gè)報(bào)錯(cuò)給出觸發(fā)場(chǎng)景和修復(fù)動(dòng)作。你遇到問題時(shí)先對(duì)號(hào)入座別盲目改代碼。401 Unauthorized / invalid api key。最常見原因是api_key不對(duì)。檢查三處.env里的 Key 是否完整復(fù)制有沒有多余空格或換行、代碼里os.getenv的變量名是否和.env一致、Key 是否已經(jīng)在控制臺(tái)被刪除或過期。修復(fù)動(dòng)作是重新去 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentconsole 創(chuàng)建一個(gè)新 Key 替換。注意 Key 只在創(chuàng)建時(shí)完整顯示一次復(fù)制時(shí)別漏字符。local proxy failed / connection refused。這個(gè)報(bào)錯(cuò)通常出現(xiàn)在base_url寫錯(cuò)或者網(wǎng)絡(luò)出口配置有問題時(shí)。先確認(rèn)base_url是https://taotoken.net/api沒有多余路徑、沒有/v1、沒有尾部斜杠。如果你本地配了系統(tǒng)級(jí)網(wǎng)絡(luò)設(shè)置檢查它是否影響了 Python 的請(qǐng)求最直接的辦法是在干凈終端里用curl -I https://taotoken.net/api看能否通。另外檢查是不是把base_url寫成了帶查詢參數(shù)的完整 URLOpenAILike 不接受這種形式。Error reading choices / choices 字段為空。這個(gè)報(bào)錯(cuò)說明請(qǐng)求發(fā)出去了、服務(wù)端也回了但返回體結(jié)構(gòu)不符合 OpenAI 兼容格式或者模型 ID 不存在導(dǎo)致返回了錯(cuò)誤結(jié)構(gòu)。先確認(rèn)MODEL_ID和模型對(duì)話頁顯示的完全一致大小寫、連字符都別錯(cuò)。再檢查是不是把base_url多加了/v1導(dǎo)致實(shí)際請(qǐng)求路徑變成/api/v1/chat/completions服務(wù)端返回 404 頁面而不是 JSON。修復(fù)后重跑單 Agent 冒煙測(cè)試確認(rèn)。OAuth / authentication flow 相關(guān)報(bào)錯(cuò)。如果你在 Agno 里用了某些需要 OAuth 的工具或 MCP 服務(wù)可能會(huì)看到這類提示。本文的模型通道走的是 API Key不涉及 OAuth如果你確實(shí)要接 OAuth 類工具先把它從tools列表里摘掉確認(rèn)模型鏈路通了再單獨(dú)接。排查順序永遠(yuǎn)是先隔離模型層再查工具層。Team 路由錯(cuò)誤任務(wù)分給了錯(cuò)誤的 Member。這不是報(bào)錯(cuò)是行為不符合預(yù)期。原因通常是 Member 的role和description寫得太模糊Leader 判斷不了。修復(fù)動(dòng)作是把 role 寫成明確的職責(zé)短語description 里寫清楚「負(fù)責(zé)什么、不負(fù)責(zé)什么」工具 docstring 也同步改清楚。改完開debug_modeTrue看 Leader 的系統(tǒng)提示詞確認(rèn) Member 信息被正確注入。SQLite 報(bào) unable to open database file。tmp目錄不存在。先mkdir -p tmp再跑。如果你在 Windows 上路徑分隔符用/也能被 SQLite 接受但目錄必須真實(shí)存在。流式輸出卡住或只輸出一半。檢查streamTrue時(shí)是否在異步環(huán)境里用了同步方法或者終端緩沖導(dǎo)致看起來卡住??梢韵雀某煞橇魇絪treamFalse確認(rèn)結(jié)果完整再切回流式。另外print_response和run的返回結(jié)構(gòu)不同別混用。提示排錯(cuò)時(shí)把debug_modeTrue打開日志里能看到完整的請(qǐng)求參數(shù)和響應(yīng)結(jié)構(gòu)比猜快得多。定位到具體層之后再關(guān)掉避免日志刷屏。6. 下一步怎么走從跑通到長期使用的接入路徑跑通上面這套鏈路之后你手里已經(jīng)有一個(gè)可復(fù)用的骨架統(tǒng)一 Key 的模型配置、單 Agent、帶存儲(chǔ)的會(huì)話、帶工具的 Agent、Team 協(xié)作。接下來往哪個(gè)方向走取決于你的實(shí)際場(chǎng)景。如果你要繼續(xù)做模型調(diào)用層的驗(yàn)證和調(diào)試比如換模型對(duì)比輸出質(zhì)量、測(cè)試不同參數(shù)下的表現(xiàn)直接去模型對(duì)話頁面 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chat 手動(dòng)試比改代碼快。確認(rèn)某個(gè)模型適合你的場(chǎng)景后再把它的 ID 寫回model_config.py。如果你要把這套東西接到自己的項(xiàng)目里重點(diǎn)看接入文檔 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdoc 里面把 base_url、認(rèn)證方式、請(qǐng)求格式講清楚了和本文的配置能對(duì)上。Key 管理統(tǒng)一在 API Keys 頁面 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentconsole 做建議給不同項(xiàng)目建不同的 Key方便單獨(dú)吊銷。如果你打算長期跑編碼類 Agent 或者多智能體流水線比如讓 Team 持續(xù)處理任務(wù)、接 CI 流程那 Coding Plan 頁面 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_plan 是更匹配的用量方案可以先了解再?zèng)Q定是否切換。最后給一個(gè)實(shí)操建議把本文的model_config.py作為你所有 Agno 項(xiàng)目的公共模塊Agent 和 Team 只導(dǎo)入模型對(duì)象不重復(fù)寫 base_url 和 Key。這樣以后換模型、換 Key、加備用通道都只改一個(gè)文件。我試過在三個(gè)小項(xiàng)目里這么干維護(hù)成本明顯低。跑通之后別停在示例上把get_weather換成你真實(shí)要調(diào)的工具把 Team 的 Member 換成你業(yè)務(wù)里的角色這套骨架就能直接長成你的應(yīng)用。