在打造 DoDone 時,有個問題我花的時間比想像中還多:如何在聊天視窗中把對話上下文往前帶。當你開發 AI agent 類產品,起初很容易用簡單的想法處理這件事:把每一則先前訊息都放進上下文不就好?
模型的上下文視窗還在變大。成千上萬的 tokens,現在甚至有支援百萬的模型。所以看起來最好的方法似乎是把使用者的對話盡可能多地餵給模型。但我在打造 DoDone 時得出的結論有些不同。
AI 的記憶重點不是能塞進多少,而是決定現在需要記住什麼。
處理長對話最直覺的方式
像 Claude Code 與 Hermes 這類代理會使用一種稱為壓縮(compaction)的技術來維持長期任務。Anthropic 也把壓縮描述為管理長期運行代理上下文的核心方法。當對話變長時,不是保留每一則舊訊息,而是總結出重要的部分,並在最近的交互旁建立新的上下文。Claude Code 同樣會壓縮舊訊息與工作,同時保留關鍵的設計決策、未解的問題與實作細節。
Hermes 的實作更具體:它不是以訊息數量來壓縮,而是以 token 預算為基準。當目前 API 呼叫中實際使用的提示 token 達到上下文視窗設定比例時,壓縮會自動啟動。預設門檻為 50%,而對於視窗小於 512K 的模型,門檻會提高到至少 75%,以避免過早壓縮。部分較新的訊息會以原文保留,而中段則被摘要化。
這是一個非常合理的結構。當單一目標長時間進行時特別適合——一個程式開發任務、一條研究線索。但 DoDone 遇到的是稍微不同的問題。
為什麼 DoDone 不會一直把整個對話餵給模型
DoDone 是一個虛擬辦公室,AI 同事在這裡工作。它不只是某一個 AI 與某一個主題深談好幾小時。使用者可能先跟行銷同事討論,接著把工作交給開發,在專案頻道開會,然後把後續交回給特定同事——隔天又來找那位同事。
換句話說,DoDone 裡的聊天不只是個對話視窗。它是工作發生的介面。這個差別改變了上下文設計。如果你隨著對話變長不斷把每則過往訊息傳給模型,你能記住很多東西——但同時會出現三個問題。
第一個是成本。每次請求時,LLM 都會重新讀取上下文。對話越長,就越會重複傳送相同的訊息。尤其在擁有非常大視窗的模型上,如果壓縮發生得太晚,整個會話的成本會急遽上升。就連 Hermes 也有討論:在 1M 的模型且預設 50% 閾值下,第一次壓縮可能要到 500K 代幣才會觸發。
第二個是速度。更多輸入代幣代表模型要處理更多資訊。沒必要讓它重新讀取與當前問題無關的數週前對話。
但我最重視的是第三點:上下文污染。
更多上下文並不總是更好
在解釋上下文工程時,Anthropic 指出即便有長上下文,相關性與上下文污染仍然是問題。這是一個重要觀點。擁有百萬 token 的視窗並不代表把它塞滿就是最佳狀態。
假設使用者與行銷同事有這樣一系列對話:上週是新服務的品牌設計、幾天前是 Instagram 廣告文案、昨天是產品的定價策略,今天則要求新聞稿。技術上你可以把所有東西都交給模型。但如果今天的工作是寫新聞稿,把數週前逐字來回編輯 Instagram 文案的對話也拖進來,真的有幫助嗎?它只會讓與當前任務無關的資訊有機會干擾模型的判斷。
所以從一開始,DoDone 關心的不是「要包含多少對話」,而是「要完整保留多近期的對話」。
DoDone 的做法 — 近期清晰聚焦、較舊內容壓縮
目前 DoDone 將最近 8 個任務保留為詳細上下文。同事對話的大致詳細上下文預算約為 20K 字元,主頻道約為 16K 字元。最後 8 個任務的細節會盡量完整保留;更久之前的內容則會被壓縮成滾動摘要,將較早的上下文帶到後面。
簡化來說,結構是這樣:過去的任務 1–12 變成滾動摘要,近期的任務 13–20 保持詳細上下文,而你現在正在做的事就是當前任務。
關鍵是舊的對話不會被刪除,而是降低解析度。最近的回合會以高解析度記住,較舊的以低解析度。這我覺得很接近人類記憶的運作。我們不會對一週前的對話逐句記得,但重要的上下文會保留:例如「我們把那個專案定價為 $29」、「我們選擇獨立創業者為目標客群」、「接下來的任務是做落地頁」。我判斷長時間的 AI 對話以相同結構會更自然。
但摘要也有侷限
當然,滾動摘要不是萬靈丹。摘要是壓縮,而你壓縮越多,勢必會失去越多細節。而且當 20、30 或 50 個任務堆進同一個對話時,另一個問題就會出現:使用者是否還在做同一件事會變得不清楚。
你可能一開始討論行銷策略,中間做了首頁,接著討論招募,然後又開始創作內容。技術上這些可以都維持在同一會話裡連在一起。但「技術上可行」和「良好 UX」是兩碼事。所以 DoDone 最近加入了一個小而有趣的機制。
AI 會率先說:「試試看開始一個新的對話」
當目前會話中的任務達到 20 個時,DoDone 會先提醒使用者。此時剛好是最近 8 個詳細任務加上大約 12 個被折疊進滾動摘要的內容累積到一起。那一刻會出現這則訊息:
💡 這段對話變得相當長。如果主題已經改變,我建議開始新會話 — 回應會更精準且 AI 成本會下降。如果你想繼續,之前的流程仍會以摘要保留。
重要的是這不會強制結束會話。若你是在繼續同一個專案,就繼續下去。但若主題已經轉變,開新會話會好得多 — 即便如此,先前你需要的流程仍會透過摘要上下文保留。最終,決定權還是在使用者手上。
在哪裡顯示該通知也很重要
我不只靠訊息數量來觸發長對話提醒。DoDone 在兩個地方都會檢查這件事。
第一個時機是任務指令到達的那一刻。無論是同事的 1:1、主頻道、全員頻道、會議追蹤或專案,只要收到指令後,系統會非同步檢查會話長度。如果條件成立,通知會自然顯示在使用者剛發出的指令下方。
第二個時機是使用者進入頻道的那一刻。當你在辦公室點選同事開啟聊天,或進入專案頻道時,系統會檢查目前會話的狀態。如果已經足夠長,你甚至在發送新訊息前就能看到通知。而在同一會話內只會提示一次;開始新會話後才會再次符合觸發條件。這是很小的 UX 設計,但在 agent 類產品裡,這類細節非常重要。
在 AI 代理系統中,記憶與上下文不是同一件事
在我打造 DoDone 的過程中,有一件事越來越清晰:記憶與上下文不該被視為相同的東西。
記憶是同事長期需要知道的東西:使用者偏好、公司資訊、工作方式、反覆性的規則、過去專案中決議的重要事實。這些資訊可能在幾天或幾個月後才會用到。上下文則不同——它更接近現在完成任務所需的工作記憶:最近的請求、正在編輯的檔案、剛決定的內容、現在要解的問題。若試圖把兩者塞進聊天歷史,系統很快就會變得沈重。
所以我認為一個好的代理系統會有好幾層記憶:當前任務(現在正在做的事)、近期上下文(最近幾次的詳細互動)、滾動摘要(過去工作的壓縮流)以及長期記憶(無論會話如何都必須保留的事實與規則)。模型的上下文視窗只是組裝當下所需那幾層資訊的空間。
上下文視窗越大,上下文工程就越重要
這裡有個諷刺:過去當上下文視窗很小時,開發者只能裁減資訊。隨著視窗擴大到 128K、200K、1M,我們現在能塞進更多內容。但這又帶來新問題:你必須決定哪些不該包含。
一個好的 AI 代理不見得是那個能記住一切的。現在需要的是能清晰記住當下、適當壓縮過往、把重要的移到長期記憶,並在主題改變時建立新工作區的 AI。最後,你在打造一個代理時越來越常做的,不是提示工程,而是情境工程。
核心問題也在改變。以前問的是「我們要告訴模型什麼?」現在更像是「就這個時刻,模型實際需要知道多少?」
這正是我在打造 DoDone 時花最多時間的部分。不是讓 AI 記住越多,而是讓它在正確時機記住正確的事。我相信未來決定 AI agent 品質的差異,就會在這裡產生。
— Seungwon Go,打造 DoDone 的獨立創業者