毫無疑問,上下文工程的優化,仍然是 Agent 創業公司在新一年都在「卷」的重點。
在實際落地開發中,上下文信息的質量,很大程度上決定了 Agent 的表現。
Manus 的首席科學家季逸超在之前訪談中提到過一個觀點:
初創公司真的應該盡可能長時間地依賴通用模型和上下文工程,而不是過早地構建專用模型,也包括微調。上下文工程是應用層和模型層之間最清晰、最實用的邊界。
做好上下文工程,開發者能夠在不觸及模型底層權重的前提下,靈活駕馭模型,同時還能適應快速變化的產品需求。
最近,Cursor 也發表了一篇文章《Dynamic context discovery》,分享了他們是怎么做上下文管理的。
結合 Manus、Cursor 這兩家 Agent 領域頭部團隊的思路,我們整理了如何做好上下文工程的一些關鍵要點。
Cursor 原文:https://cursor.com/cn/blog/dynamic-context-discovery
此前 Founder Park 分享的文章
??關注 Founder Park,最及時最干貨的創業分享
超 19000 人的「AI 產品市集」社群!不錯過每一款有價值的 AI 應用。
邀請從業者、開發人員和創業者,飛書掃碼加群:
進群后,你有機會得到:
最新、最值得關注的 AI 新品資訊;
不定期贈送熱門新品的邀請碼、會員碼;
最精準的AI產品曝光渠道
01「上下文縮減」是最直接有效的策略
在 Agent 的構建過程中,會發現一個現象:上下文會持續增長,并且是以一種非常特殊的方式增長。
Agent 每調用一次工具,就會返回一個工具的觀測結果,這個結果會被追加到聊天記錄中。隨著時間的推移,消息列表會越來越長,導致 Agent 在運行時消息數量出現無限制的爆炸性增長。
Manus 之前提到,典型的任務大約需要調用 50 次工具。Anthropic 也提到過類似的情況,生產環境中的 Agent 可能會進行長達數百輪的對話。
上下文長度的持續增長,會導致推理性能斷崖式的下跌。業內叫做「上下文腐爛」(Context Rot),具體表現是:推理變慢、質量下降、甚至開始無意義地重復。
如何解決?業內目前共識的一個方法是「上下文卸載(Context Offloading)」,核心思路是別把所有東西都硬塞進 Agent 的短期記憶里,把它卸載出去。放到上下文窗口之外,但在需要時,又能被精確地檢索回來。
將信息轉移到文件系統中,是目前生產級 Agent 中主流、最 Work 的一種做法。
Cursor:萬物皆可文件化
Cursor 把「卸載」這個思路,發揮到了極致。用文件作為基礎單元,將冗長的工具結果、終端會話、聊天記錄全部轉化成文件。
Cursor 提到,
我們不確定未來 LLM 工具的最佳接口是什么。但文件是一個簡單、強大的基礎單元,比發明一套新抽象要安全得多。
基于這個思路,Cursor 提出了「動態上下文發現」(Dynamic Context Discovery)模式。核心是,別急著把信息塞給模型,而是讓模型在需要的時候自己去找。
Cursor 把這套模式用到了他們的多個實際場景中:
將冗長的工具結果轉化為文件
工具調用,特別是 Shell 命令或第三方 MCP(模型上下文協議),經常返回巨大的 JSON 響應,瞬間就能撐爆上下文。目前的編程 Agent 通常采取的簡單粗暴做法是:直接截斷過長的 Shell 命令或 MCP 結果,但很可能會丟失最關鍵的信息。
Cursor 的做法是,將這些輸出直接寫入到一個文件,然后在上下文中只告訴 Agent:「結果在 output.log 里,你自己去看。」Agent 可以先用 tail 命令查看文件末尾,如果需要更多細節,再讀取整個文件。
在「總結」階段引用聊天記錄
當模型的上下文窗口被填滿,Cursor 會觸發一個「總結」步驟,給 Agent 騰出一個新的上下文窗口,其中包含之前工作的摘要。
但 Agent 的知識會在這個過程中「退化」,因為「總結」本質上是對上下文的一種有損壓縮。 Cursor 把完整的聊天歷史記錄也看做是一個文件。當觸發總結時,Agent 會拿到一份摘要,以及一個指向「歷史記錄文件」的引用。如果 Agent 意識到摘要中缺少某些它需要的細節,它就可以通過搜索這份歷史記錄文件來找回這些信息。
![]()
將所有集成終端的會話視為文件
在 Cursor 中,不再需要手動復制粘貼滿屏的終端報錯信息,會自動將集成終端的所有會話輸出同步到本地文件系統。 提問「為什么我的命令失敗了?」時,Agent 能直接定位問題,甚至可以使用 grep 這樣的命令,在長篇的服務器日志中只搜索相關的錯誤行。這種做法模仿了 CLI Agent 的體驗,擁有之前的 Shell 輸出作為上下文,但不同的是,它是動態發現,不是被靜態注入。
Manus :一套結構化的可逆、縮減系統
對比 Cursor「簡單粗暴」的解決思路,Manus 的做法是,把「上下文縮減」設計成了一套有明確觸發機制、分階段執行的結構化流程。
首先,Manus 的系統會持續監控上下文長度,設定一個遠低于模型硬件極限的「腐爛前閾值」(Pre-rot Threshold)。
季逸超:你的模型有一個硬性的上下文限制,比如說 100 萬個 Token,這在今天是相當普遍的。但實際上,大多數模型在遠低于這個值時性能就開始下降,通常可能在 20 萬個 Token 左右,你會開始看到我們所說的「上下文腐爛」,比如重復、推理變慢、質量下降等。 所以,通過大量的評估,識別出那個「腐爛前」的閾值非常重要,通常是 12.8 萬到 20 萬個 Token,并將其作為觸發上下文縮減的條件。
當信號被觸發后,系統會啟動第一階段的操作:
第一步:緊湊化(Compaction)
這是一種無損、可逆的縮減。核心是,剝離掉任何能從外部狀態(比如文件系統)重建的信息。
舉個例子,Agent 調用了一個向文件寫入內容的工具,這個操作在歷史記錄中可能包含 path 和 content 兩個字段。一旦執行成功,那個可能極其冗長的 content 字段就可以被安全地從上下文中剝離,只保留 path。
信息并沒有丟失,它只是被「外部化」了。如果 Agent 在 10 步之后需要再次讀取該文件,它憑借保留的 path 就能輕易將其檢索回來。
Manus 提到,這種可逆性是非常關鍵的,因為你永遠不知道哪個過去的動作會成為未來的關鍵。
通常情況下,緊湊化只會用作最早的 50% 的歷史記錄,來保留最新的、完整的工具調用作為模型學習的范例(Few-shot Examples)。
但緊湊化收益有限。多輪操作后,上下文削減的收益變得微乎其微時,系統會啟動第二階段:
第二步:摘要化(Summarization)
這是一種有損、但帶保險的壓縮。把它當做最后手段,在執行時需要極其謹慎。
它的「保險」在于:在生成摘要之前,系統會更激進地將整個摘要前的完整上下文,轉儲(Dump)到一個文本或日志文件中。 相當于給歷史創建了一個完整的快照存檔。如果模型足夠聰明,它甚至能用 grep 或 glob 自己去這個日志里撈數據。
季逸超:緊湊化是可逆的,而摘要化不是。兩者都減少了上下文長度,但它們的行為方式非常不同。
在進行摘要化時,總是會使用完整版本的數據,不是緊湊版本。
摘要化依然會保留最后幾次完整的工具調用記錄。 這能讓模型清楚地知道自己從哪中斷,能平滑地繼續工作,保持風格和語氣的連貫性。
兩個步驟下來,通過「緊湊化」(Compaction)剝離可重建信息,以及在「摘要化」(Summarization)之前,將完整的上下文轉儲(Dump)到日志文件中。實現上下文縮減。
02給工具搭建一套靈活的行動空間
當 Agent 能力逐步增強,配備的工具集也越來越豐富。
如果將所有工具的冗長描述,都放到上下文窗口中,會帶來兩個問題:
一是出現上下文混淆(Context Confusion)的情況,工具太多,模型直接懵掉。可能會調用錯誤的工具,甚至是幻覺出根本不存在的工具。
二是最直接的 Token 浪費,大多數工具,在絕大多數時候根本不會被用到。如果,還使用了多個 MCP 服務器,情況會變得更糟。
工具過載的問題怎么解決?一個核心思路是:動態發現,讓 Agent 自己去找要調用哪些工具。
Cursor:把工具說明書,全部文件化
Cursor 的策略,更簡單、粗暴。把所有 MCP 工具、Agent Skills 的詳細定義,全部都同步到文件夾里,讓 Agent 在需要時自己去查閱。
在 Cursor 的框架中,分成了索引層和發現層。
索引層,Agent 的系統提示詞(System Prompt)里只包含一小部分靜態信息,比如 MCP 工具或 Agent Skills 的名稱列表。
這些工具和技能的詳細描述、參數定義、使用方法,則被全部同步到一個本地文件夾中。當模型需要時,Agent 會像一個聰明的程序員一樣,進入發現層,用 grep 或語義搜索,主動去文件夾里查找它需要的工具的詳細信息,然后拉取到上下文中來處理。
Cursor 做了一次 A/B 測試,結果發現,對于調用了 MCP 工具的運行任務,這種策略把Token 的總消耗降低了 46.9%。
![]()
同時,Cursor 提到,這種全部文件化的方式,還解鎖了一個意想不到的能力:向 Agent 傳達工具的狀態。
例如,以前如果一個 MCP 服務器需要重新認證,Agent 可能會直接「忘記」這些工具的存在。但現在,Agent 可以主動發病、告知用戶去重新認證。
Manus:設計了一套分層的行動空間
Manus 認為,常見的方法對工具描述進行動態的 RAG,不可行。 因為動態加載工具定義,會「干掉」KV 緩存,且歷史記錄里的舊調用會成為陷阱。
季逸超:目前一個常見的方法是對工具描述進行動態的 RAG,比如,根據當前任務或狀態按需加載工具。 但會導致兩個問題:首先,由于工具定義位于上下文的開頭,每次變動都會導致你的 KV 緩存重置;最重要的是,模型過去對那些已被移除的工具的調用記錄仍然存在于上下文中,這可能會誤導模型去調用無效的工具或使用無效的參數。
為了解決這個問題,Manus 設計了一套分層行動空間。把 Agent 的能力劃分為三個層次:函數調用、沙盒工具、軟件包和 API。
第一層:原子函數調用(Function Calling)
核心層,只包含極少數固定的、正交的原子函數,比如:讀寫文件、執行 shell 命令、在文件和互聯網中搜索。因為這層是固定的,所以對 KV 緩存友好,且功能邊界清晰,不會導致混淆。
第二層:沙盒工具(Sandbox Tools)
卸載層。Manus 將絕大多數工具,格式轉換器、語音識別工具,甚至 MCP 調用本身(通過一個 MCP CLI 命令行工具),都作為預裝軟件放在一個定制的 Linux 虛擬機沙箱里。 Agent 不在上下文中「看到」這些工具的詳細定義,更像是一個真正的開發者,通過第一層的 shell 命令來動態地與它們交互。比如,它可以用 ls /bin 來查看有哪些可用的工具,或者用 mcp_cli --help 來學習如何使用 MCP 命令行工具。
第三層:軟件包與API(Packages & APIs)
代碼層。對于需要大量內存計算或者需要與復雜第三方服務交互的任務,允許 Agent 編寫并執行 Python 腳本。比如,分析一整年的股票數據,Agent 不會把原始數據加載到上下文中,而是會寫一個腳本去完成計算,只把摘要結果返回。
季逸超:在這一層,Manus 可以編寫 Python 腳本來調用預先授權的 API 或自定義軟件包。例如,Manus 可能會使用一個 3D 設計庫進行建模,或者調用一個金融 API 來獲取市場數據。實際上,我們已經代表用戶購買了所有這些 API 并支付了費用,這都包含在訂閱里。 所以,我們基本上在 Manus 中預裝了大量的 API 密鑰,Manus 可以用這些密鑰訪問 API。我認為這對于需要大量內存計算,但又不需要將所有數據都推送到模型上下文的任務來說是完美的。
這套思路,和 CodeAct *論文類似。
代碼是可組合的,可以在一步內做很多事。但它同樣不是模式安全的,在代碼上做約束解碼非常非常困難。所以我們認為你應該為這些功能找到合適的場景。對我們來說,所有能在一個編譯器或解釋器運行時內處理的事情,我們都用代碼來做;否則,我們就用沙箱工具或函數調用。
CodeAct *:《Executable Code Actions Elicit Better LLM Agents》:
https://arxiv.org/pdf/2402.01030
Manus 這套分層設計非常優雅,而且高效。從模型的角度看,無論想使用第二層還是第三層的復雜工具,最終都會通過 L1 的那幾個原子函數執行。這種接口設計,對模型極度簡潔,且緩存穩定。
03多 Agent 協作,
需要反復使用模式、結構化輸出
多個 Agent 之間如何協作,也是個難題。
Cognition 之前在博客中提到:不要濫用多 Agent 設置,因為當你有很多 Agent 時,它們之間的信息同步會成為一場噩夢。
怎么利用多 Agent,實現「上下文隔離」,讓每個子 Agent 都有自己獨立的上下文窗口,從而實現關注點分離。是一個核心問題。
Manus 的解決思路是,借鑒 Go 語言:不要通過共享內存來通信,而是通過通信來共享內存。
把這句話里的「內存」替換為「上下文」,就是兩種截然不同的 Agent 協作模式。
兩種 Agent 協作模式
任務委托模式:「通過通信」實現隔離
這是經典的主-子 Agent(Master-Sub-agent)設置。主 Agent 將一個任務封裝成一條簡短、清晰的指令,然后發送給子 Agent。子 Agent 的上下文是完全獨立的,從零開始,只包含這條指令。
簡單來說,主 Agent 發任務,子 Agent 交結果,中間過程免打擾。
這個模式,適用于「過程不重要,只關心結果」的任務。舉個例子,主 Agent 需要在一個大型代碼庫中搜索特定的代碼片段。它只需要委托子 Agent:「在 A 項目中找到所有調用了 some_function 的地方」,然后等待返回結果列表即可。主 Agent 不關心子 Agent 是如何使用 grep 或其他工具完成搜索的。
在內部,Manus 將這種模式叫做「Agent 即工具」。從主 Agent 視角,它只是調用了 advanced_search 函數,但背后實際上是另一個擁有獨立工作流的子 Agent 在執行。
信息同步模式:「通過共享上下文」實現協作
但對于更復雜、需要完整歷史記錄的場景,簡單的任務委托是遠遠不夠的。
Manus 的思路是,通過共享上下文來實現協作。子 Agent 被創建時,能夠看到主 Agent完整的先前上下文,包括所有的歷史工具調用和觀察。但這個子 Agent 擁有自己獨立的系統提示詞和新的行動空間。
這種模式,更適用于高度依賴歷史信息、需要綜合分析的任務。比如,在進行一項深度研究任務時,最終的研究報告需要綜合大量的中間搜索結果和筆記。
如果使用第一種通信模式,主 Agent 需要將所有中間產物寫入文件,再讓子 Agent 去一一讀取,這會造成巨大的延遲和額外的 Token 消耗。在這種情況下,直接讓子 Agent 繼承完整的上下文反而會更高效。
但 Manus 也提到,共享上下文的模式成本是相當昂貴的。因為每個子 Agent 啟動時都需要 Prefill 一個非常大的輸入,并且因為系統提示詞不同,無法復用主 Agent 的 KV 緩存,所以必須支付全價。
所以,需要根據任務的性質,靈活地在這兩種模式中間進行選擇。
多 Agent 通信,發信息不難,難的是收結果
多 Agent 通信的一個難點是「接收」,如何從多個并行工作的子 Agent 那里,獲得結構一致、內容準確的輸出?
Manus 設計了一套內部代號叫做「Agent 化的 MapReduce」的系統。簡單來說,
共享沙箱
每個 Manus 會話都在一個完整的虛擬機沙箱中運行。當主 Agent 創建子 Agent 時,共享同一個沙箱。這意味著,共享同一個文件系統,信息的傳遞可以簡單到只傳遞不同的文件路徑,解決了輸入信息同步的問題。
輸出模式(Schema)
這是關鍵。主 Agent 在創建子 Agent 之前,必須先定義一個輸出的 Schema。這個模式就是一份強制執行的 API 合同,規定了子 Agent 最終必須返回什么樣的數據結構。
約束解碼
子 Agent 有一個專用工具 submit_result。Manus 使用約束解碼(Constrained Decoding)技術,強制子 Agent 提交的結果,必須嚴格符合主 Agent 定義的 Schema。
這套設計的核心思路是,無論是做摘要還是 Agent 間通信,都反復使用模式和結構化輸出作為一種「契約」,來保證信息以結構化、完整的方式傳遞。
04最后,聊聊兩家的設計哲學
最后,回到原點,聊聊這兩家的上下文工程設計哲學。
Cursor 的「Dynamic Context Discovery」,強調:少即是多。Cursor 認為,在最開始提供給模型的細節越少,效果反而越好,因為能讓 Agent 更輕松地自行抓取相關的上下文。
Manus 的思路是:「少構建,多理解」,避免上下文的過度工程化。上下文工程的目標是讓模型的工作變得更簡單,而不是更難。
季逸超:回顧 Manus 發布以來的六七個月,我們見過的最大的飛躍,不是來自增加了更多花哨的上下文管理層或巧妙的檢索技巧,它們都來自于簡化,來自于移除不必要的技巧,以及對模型多一點的信任。 每一次我們簡化架構,系統都會變得更快、更穩定、更智能。上下文工程的目標是讓模型的工作變得更簡單,而不是更難。
兩家的實踐大方向都是,從「如何把更多信息塞進上下文」,變成「怎么給 Agent 創建一個信息豐富、易于探索的外部環境」。
引用寶玉老師的一句話:未來,隨著基模能力的提升,把主動權交給模型會是一個趨勢。
![]()
轉載原創文章請添加微信:founderparker
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.