iT邦幫忙

2026 iThome 鐵人賽

DAY 23
0
AI Engineering

一天一個 PR,讓我告訴你嵌入式開發的殘酷:如何為 AI Agent 建立可信的工程閉環系列 第 23

Day 23 - 昨天才踩過的坑,換一隻 Agent 又從頭問:工程經驗到底存在哪裡?

  • 分享至 

  • xImage
  •  

系列說明 >> 本系列大部分 PR 來自私人或公司專案,部分程式碼、環境設定與實作細節不便公開。

我只能保證文中提到的 PR 與問題皆為真實案例,但會經過必要的匿名化與內容調整。

本系列主要分享問題如何被發現、背後的思考方式,以及解法如何形成,不會深入討論完整實作與部署細節,敬請見諒。

Today’s Change

  • Base Repo: paulshaclaw

  • Change Ref: PR #43-feat(stage2): complete memory importer MVP

  • Issue: Agent、Session 與 CLI 一換,前一輪累積的工程脈絡通常只剩在聊天記錄、暫存檔或人的腦中。即使 PR、Skill 與文件都存在,下一個 Agent 也未必知道該去哪裡找,更無法確認某段內容來自哪個 Tool、哪次 Session、哪個 Project 與哪份原始 Payload。

  • Root Cause: Claude、Codex、Copilot 各自產生不同形狀的 Session/Transcript,但當時沒有統一的 Capture 與 Importer Boundary。工程經驗沒有一條固定入口被持久化,也沒有穩定的 Session Identity、Archive 與 Provenance 可供後續整理。

  • Solution: 完成 Stage 2 Memory Importer MVP:由各 CLI Hook 捕捉 Session Event,Installer 負責接線,Importer 統一解析、Routing、Archive 並保存 Provenance;Codex 同一 Session 的多次 Capture 改用 Per-event Unique Filename,避免 Queue Payload 互相覆寫。Review 後也補上 Repo Root 外的 Dry-run Import 與 Override Path 空白拒絕。

  • Evidence: Memory Test Suite 與 stage2_integration_check.sh 通過;PR 同時保留 Full Repo Test 中兩個與本變更無關的既有 Monitor/Service Failure。這些證據支持 Session Capture、Archive 與 Provenance 通道已成立;它不代表 Transcript 已經變成可重用 Knowledge,更不代表下一隻 Agent 已經讀過或採用其中經驗。


D22 才剛收工,下一隻 Agent 就把同一題重新開機

上一篇最後,Cortex 的五個 Runtime Package 終於搬完。

舊 Manager 關了,Thin Shim 也只剩轉送責任。

然後另一隻 Agent 看著刪除清單問:

「舊 Package 為什麼不能先留著相容?」

我把手放回鍵盤,準備從兩套 State Owner、舊 Timer、Cutover Window 開始再講一次。

打到一半,忽然覺得這個場面不只眼熟。

前面我們也遇過:

Agent 說工作做完了
→ D17 才發現 Completion Lifecycle 還沒完成

新 Repo 已經能啟動
→ D22 才發現舊 Runtime Authority 還沒退役

表面上一個在講 Agent,一個在講 Repo。

骨子裡都是:

某個局部能跑,不等於整條工程責任已經收完。

再往前翻,還有另一種:

D18:Ready 與 Fanout 各自解析一份 Plan
D22:新舊 Manager 都可能修改同一份 State

名字不同,最後都在問:

同一個 Fact,到底誰才是 Authority?

最直接的則是 D20。

feature-delivery-pipeline 明明早就寫成 Skill,換一隻 Agent,Phase 還是可以被它自行縮掉。

老Go看我翻完前面的紀錄。

「所以你不是遇到二十二個不同問題。」

「是幾個老問題一直換衣服回來。」

……聽起來更省事了。

因為衣服每次都不一樣,我也每次都重新付一次學費。


規則明明寫過,為什麼還是要靠我記得去哪裡翻?

這些經驗其實沒有完全消失。

它們散在:

聊天記錄
PR Body
Issue Comment
Skill
Design Doc
測試與 Evidence

問題是,下一隻 Agent 不會因為「某個地方存在一份文件」,就自動知道:

  • 這次碰到的是不是同型問題。
  • 哪一份紀錄仍然有效。
  • 當初的判斷是推測,還是已經有 Runtime Evidence。
  • 那段內容屬於哪個 Repo、哪次 Session、哪個 Agent Tool。

小re問:

「你現在要保存的是一句結論,還是結論從哪裡來?」

如果只留一句:

One authority per fact

它很像一張好看的標語。

但真的出事時,我還是得回頭找:

是哪次 Ready / Fanout 分歧?
哪一份 Plan 被 Pin?
哪個 Service 還沒 Disable?
最後靠什麼 Evidence 才確認?

所以這裡講的 Engineering Memory,不是讓 Agent 記得我喜歡哪種命名。

它是把能跨 Agent 重用的工程經驗,連同來源一起保留下來。

但在談搜尋、推薦、排序以前,先有一個更基本的問題:

Session 結束後,原始經驗到底有沒有被留下?

Target


Memory 的第一步不是「想起來」,是先別讓 Session 消失

當時 Claude、Codex、Copilot 都有自己的 Session 形狀。

有的從 Transcript 讀,有的從 History 讀;事件欄位、Session ID、檔案位置也不一樣。

如果每個工具各寫一套後續流程,最後很容易變成:

Claude 記得一種格式
Codex 記得另一種
Copilot 再補第三種

等我要查「這段經驗從哪裡來」,三邊又各有答案。

PR #43 做的第一件事,因此不是讓 Memory 變聰明。

而是先建立 Capture:由 Hook 把 Session Event 交進固定入口,再由 Importer 持久化 Session、來源與識別資訊。

流程大概是:

Claude / Codex / Copilot
        ↓ Hook Capture
Queue Payload
        ↓ Importer
Session Archive + Provenance

這裡的 Queue Payload,就是 Hook 先放進待處理區的原始 Session Event。

Importer Provenance 則記錄它來自哪個 Tool、哪次 Session、哪個 Project,以及對應哪份 Archived Payload。

這份 Captured Session Archive:

  • 由各 CLI Hook 與 Importer 產生。
  • 後續交給 Atomizer、Debug 或 Replay 使用。
  • 保存的是原始 Session 與來源鏈。
  • 不是已經整理好的 Atomic Knowledge,也不是這次工作成功或失敗的 Outcome。

小bu看完流程,覺得有點樸素。

「所以現在只是先把聊天收進來?」

對。

先不要急著替聊天加上「知識」兩個字。

至少這次它不會在 Session 一關掉後,只剩我記得大概講過什麼。

Target


同一個 Codex Session 多存一次,前一份竟然會被蓋掉

Capture 接起來後,很快出現一個很實際的問題。

Codex 同一個 Session 可能不只產生一次 Capture Event。

如果 Queue Filename 只使用 Session Identity,第二次寫入時就可能直接蓋掉第一次。

結果會變成:

Session 看起來有 Archive
→ 但中間某次 Event 已經消失
→ Provenance 還能指到一個檔案
→ 只是那個檔案不是原本那份

這種狀況最麻煩的地方,是它不像 File Not Found 那麼乾脆。

檔案還在。

名字也對。

只有歷史被悄悄換過。

所以 PR #43 把 Queue Item 改成 Per-event Unique Filename:同一 Session 的不同 Capture 各自留下,不再互相覆寫。

小re沒有問「最後有沒有檔案」。

它問的是:

「每一次 Capture,還能不能對回它自己的原始 Payload?」

這才是 Importer 該守的東西。

Memory 如果連自己的來源都會被後一筆覆蓋,後面不管蒸餾得多漂亮,都只是把錯的歷史整理得很整齊。

Target


Review 又補了兩個不太像 Memory、其實很像 Boundary 的洞

第一版完成後,Review 還補了兩件事。

一個是 Stage 2 Integration 的 Dry-run,必須能從 Repo Root 以外執行。

因為真正的 Hook 不會每次都剛好站在 paulshaclaw 根目錄等你。

如果測試只有在 Repo Root 才能 Import,驗到的比較像:

我站的位置很正確。

不是部署後的 Capture 真的可用。

另一個是 Installer 的 Memory/Config Override Path,遇到空白要直接拒絕。

這不是因為路徑有空白天生邪惡。

而是當 Installer、Shell 與 Hook 對路徑的拆法不一致時,最後很可能出現兩個不同 Root,然後每一邊都覺得自己有成功寫入。

前面才剛把雙 Authority 關掉,我沒有很想讓 Memory 用路徑解析再養一組。

老Go看著這兩個 Follow-up。

「你本來想存經驗。」

「結果第一天先學到,連存放經驗的地址都不能靠大家自行理解。」

非常合理。

也非常符合本系列一路走來的運氣。

Target


今天只是把學費收據留下,還沒整理成教材

PR #43 最後跑過 Memory Test Suite 與 Stage 2 Integration Check。

它能支持的主張是:

  • 不同 Agent CLI 的 Session 有統一 Capture/Importer 入口。
  • Session Archive 能保留來源與 Provenance。
  • 同一 Codex Session 的多次 Capture 不再互相覆寫。
  • Importer 不必站在 Repo Root 才能工作。

它不能支持:

下一隻 Agent 已經能在碰到相似問題時,立刻找回正確教訓。

因為現在留下來的,仍然可能是一整段很長的 Transcript。

裡面有真正的決策,也有走錯的路、Command Output、閒聊、重複嘗試,以及當時還沒被推翻的猜測。

老Go把剛才那批 Archive 看了一眼。

「收據沒有丟,很好。」

「但你總不能叫下一隻 Agent 先把二十二天的收據全部讀完。」

嗯。

Memory 的入口有了。

下一個問題是,怎麼把一整段 Session,拆成下一隻 Agent 真正有機會讀得下去的工程知識。

下一篇,對話全存下來了,為什麼還是不能直接當 Memory?

Have a nice day.


上一篇
Day 22 - 新 Repo 明明能跑,怎麼還有一半住在舊家?:Cortex 正式拆分
下一篇
Day 24 - 對話我全存了,下一隻 Agent 還是讀不完:Transcript 為什麼不能直接當 Memory?
系列文
一天一個 PR,讓我告訴你嵌入式開發的殘酷:如何為 AI Agent 建立可信的工程閉環28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言