為什麼你的 AI 編碼代理會產生檔案路徑幻覺
> 當 AI 編碼代理沒有儲存庫的真實地圖時,就會編造檔案路徑。本文說明這為何發生,以及紮根依據如何帶來更少的幻覺編輯。
破綻不是一個寫錯的函式體。而是一次自信滿滿的編輯,針對一個不存在的檔案,或者一個存在但並非實作該行為的檔案。
你要求修復工作階段過期問題。代理開啟了 src/auth/session.ts。這條路徑看起來合理。但它也是錯的。真正的處理函式在 apps/api/src/middleware/expiry.ts 裡,兩次重構之前被重新命名過。代理沒有對你撒謊。它是用訓練先驗加上上下文視窗裡已經有的內容,補全了一個路徑形狀的字串。
這是真實儲存庫中常見的失敗模式。模型會寫程式碼。失誤在於選錯了寫程式碼的地方。
為什麼代理會編造路徑
編碼代理是一個帶工具的下一個 token 預測模型。當你說「修一下工作階段過期」時,它必須先指定一個檔案,才能讀取或修補任何東西。如果它還沒有一張有依據的地圖,它就會從以下來源拼湊出一條路徑:
- 它在其他儲存庫裡見過的命名慣例。
src/auth/session.ts是一種常見形態。 - 已經出現在對話裡的檔案,那可能是你上週貼上過的檔案,而不是現在真正重要的檔案。
- 它碰巧執行過的目錄清單,在大型程式碼樹上是不完整的。
- 指令檔案。
CLAUDE.md和AGENTS.md告訴代理該如何表現。它們不是符號、呼叫端或當前路徑的活索引。
這些來源沒有一個是今天這個儲存庫的地圖。模型填補空白的方式,和它填補任何空白的方式一樣:用一個高機率的延續。這個延續常常看起來像一條真實的路徑。有時那個檔案確實存在,而且就在正確檔案旁邊。有時它曾經存在於上個月已合併的一個分支上。有時它從來就不存在。
如果代理從未搜尋過正確的字串,grep 在這裡救不了你。代理猜了一條路徑,然後讀了那條路徑傳回的內容,然後編輯了它。第一個錯誤的步驟是路徑,不是補丁。
讀檔案也不等於找到正確的檔案。Claude Code、Cursor、Codex 以及類似的工具,可以開啟你指向的任何東西。問題在於,它們能否在編輯之前,可靠地找到正確的檔案、重要的符號、依賴關係、測試,以及影響範圍。沒有地圖的檔案存取,依然是從猜測開始的。
錯誤檔案的編輯是一個檢索問題
把編造出來的路徑當作一次檢索失敗來處理,而不是當作性格缺陷。
如果代理在被允許編輯之前必須傳回 path/file.ext:line,會發生兩件事。第一,你可以開啟這條引用,在十秒內拒絕這次工作。第二,代理必須去查詢某個真正瞭解這棵程式碼樹的東西。
這就是程式碼庫上下文層的工作。僅靠語意搜尋是不夠的。一個「聽起來像工作階段過期」的片段,依然可能落在一個已廢棄的套件裡。當你知道字串時,你還需要精確文字;當你知道名字時,你需要符號查詢;當你知道形狀時,你需要結構化搜尋;當你需要呼叫端和影響範圍時,你需要依賴圖。
Maguyva 就是為相容 MCP 的編碼代理提供的這一層。它不是編輯器。Claude Code、Cursor、Codex CLI、VS Code、Windsurf 以及其他 MCP 用戶端,都留在它們原本的位置。代理在觸碰任何一行程式碼之前,先查詢一張排序過的地圖。
這個主張刻意保持謙遜:更少的幻覺編輯。Maguyva 並不會剝奪模型猜測的能力。它改變的是預設的第一步,從「編造一條看似合理的路徑」變成「請求排序過、帶引用的位置」。
一份有依據的答案是什麼樣子
對「工作階段過期在哪裡處理」這個問題,一個有用的答案不是一段話。而是一份簡短的位置清單:
apps/api/src/middleware/expiry.ts:48- 處理函式apps/web/src/lib/auth-client.ts:112- 呼叫端apps/api/tests/expiry.test.ts:20- 如果這次改動出錯就會失敗的測試
你可以開啟這些行。如果錯了,你就停下。如果對了,代理就可以編輯。重點在於驗證,而不是一句口號。
Maguyva 提供 11 個面向客戶的 MCP 工具,涵蓋搜尋、符號、依賴分析、檔案檢索、儲存庫上下文和確定性實用工作流程。四種檢索模式(語意、結構、圖/依賴和文字)融合成排序結果;符號查詢是一個獨立的 MCP 工具(find_symbol)。有依據的答案會附上檔案路徑和行號傳回,方便你對照眼前的程式碼樹來評判。
文件 描述了最短路徑:先免費開始,索引一個你已經瞭解的儲存庫,連接用戶端,然後問一個你能核實的問題。
一個改變第一次編輯的迴圈
你不需要一套新的工作流程信條。你需要的是在第一次落筆之前多加一步。
- 問一個你已經能評判的問題。「哪段程式碼處理登入和工作階段過期」比「修一下認證」更好。
- 要求引用。檔案路徑和行號,而不是「認證模組」的一段摘要。
- 開啟被引用的檔案。跟著符號走。確認你即將觸碰的依賴關係。
- 只有到那時,才讓代理去打補丁。
如果第二步沒有傳回任何有用的東西,代理就沒有資格臨時編造一條路徑。它要麼再搜尋一次,要麼由你來指路。正是這一道關卡,產生了更少的幻覺編輯。模型還是同一個模型。變了的是地圖。
指令檔案依然重要。保留它們。用它們來記錄慣例、審查規則,以及不該觸碰的東西。不要要求它們充當索引。一個列出三個重要目錄的 CLAUDE.md,在一次套件拆分之後的那一週就會過時。而一張可查詢的地圖,會隨著儲存庫的更新而更新。
一個相關的失敗是「幾乎對」的檔案:當行為其實在 auth-client.ts 裡時,代理卻開啟了 auth.ts;或者補丁打在了一個生成的檔案上,而不是原始檔;或者因為名字匹配,編輯了 packages/legacy 裡的那份複製。引用不會讓這些錯誤變得不可能發生。它們只是讓這些錯誤在 diff 落地之前變得可見。
一張地圖不會為你修復的東西
對自己得到的東西保持清醒。一張有依據的地圖不會讓每一次編輯都變得正確——你的代理依然可能在完全正確的檔案裡寫出一個糟糕的補丁。如果你的程式碼庫依賴動態派發、反射或猴子補丁,一些符號查詢傳回的結果會比你希望的更單薄,因為執行時的間接性對任何靜態索引都會造成這種效果。而如果你在期待一個百分比——「幻覺路徑減少了 X%」——你在這裡找不到,因為除了你自己,沒有人能為你的儲存庫誠實地測出這個數字。
你可以期待的東西範圍更窄,也更有用:代理不再用一條猜測出來的路徑來開始它的編輯。這第一步會紮根於一張真實的地圖,而更少的幻覺編輯正是由此而來。引用之後的一切——閱讀 diff、判斷補丁——依然是你的工作,和以往一樣。
這個測試幾乎不花你什麼成本:索引一個你已經瞭解的儲存庫,問一個你能核實的問題。從一條曾經讓你吃過虧的路徑開始。如果引用錯了,你會立刻看出來。如果對了,你代理的下一次編輯就有了一個更好的落腳點。
// it doesn't know the file. it knows how to find it.
延伸閱讀
更多來自 Maguyva 開發日誌的內容
在沒有本地索引器的情況下,給 AI 代理大型儲存庫的上下文_
如何在不在膝上型電腦上執行本地索引器的情況下,從雲端為編碼代理提供一張大型儲存庫的可查詢地圖。
會隨行的上下文_
Cursor 的索引器在 Cursor 裡非常出色。Maguyva 是同一個代理可以從其他編輯器、CLI 和 CI 中查詢的託管 MCP 地圖。
先地圖,後審查_
在編碼代理動筆之前,先讓它紮根於一張儲存庫地圖。之後再讓 Greptile 審查這個提取要求。這是互補的搭檔,不是替代關係。