# 为什么你的 AI 编码智能体会产生文件路径幻觉

Canonical source: https://maguyva.ai/zh-hans/blog/why-ai-coding-agents-hallucinate-file-paths

License: text under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/); code samples under [MIT-0](https://opensource.org/license/mit-0); the Maguyva name, logos, brand assets and other code are not covered. Details: [maguyva.ai/license](https://maguyva.ai/license).

Date: 2026-08-14 · Author: Maguyva Team

> 当 AI 编码智能体没有仓库的真实地图时，就会编造文件路径。本文说明这为何发生，以及扎根依据如何带来更少的幻觉编辑。

破绽不是一个写错的函数体。而是一次自信满满的编辑，针对一个不存在的文件，或者一个存在但并非实现该行为的文件。

你要求修复会话过期问题。智能体打开了 `src/auth/session.ts`。这条路径看起来合理。但它也是错的。真正的处理函数在 `apps/api/src/middleware/expiry.ts` 里，两次重构之前被重命名过。智能体没有对你撒谎。它是用训练先验加上上下文窗口里已经有的内容，补全了一个路径形状的字符串。

这是真实仓库中常见的失败模式。模型会写代码。失误在于选错了写代码的地方。

## 为什么智能体会编造路径

编码智能体是一个带工具的下一个 token 预测模型。当你说“修一下会话过期”时，它必须先指定一个文件，才能读取或修补任何东西。如果它还没有一张有依据的地图，它就会从以下来源构造一条路径：

1. 它在其他仓库里见过的命名约定。`src/auth/session.ts` 是一种常见形态。
2. 已经出现在对话里的文件，那可能是你上周粘贴过的文件，而不是现在真正重要的文件。
3. 它碰巧运行过的目录列表，在大型代码树上是不完整的。
4. 指令文件。`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`）。有依据的答案会带着文件路径和行号返回，方便你对照眼前的代码树来评判。

[文档](/zh-hans/docs) 描述了最短路径：先免费开始，索引一个你已经了解的仓库，连接客户端，然后问一个你能核实的问题。

## 一个改变第一次编辑的循环

你不需要一套新的工作流信条。你需要的是在第一次落笔之前多加一步。

1. 问一个你已经能评判的问题。“哪段代码处理登录和会话过期”比“修一下认证”更好。
2. 要求引用。文件路径和行号，而不是“认证模块”的一段摘要。
3. 打开被引用的文件。跟着符号走。确认你即将触碰的依赖关系。
4. 只有到那时，才让智能体去打补丁。

如果第二步没有返回任何有用的东西，智能体就没有资格临时编造一条路径。它要么再搜索一次，要么由你来指路。正是这一道关卡，产生了更少的幻觉编辑。模型还是同一个模型。变了的是地图。

指令文件依然重要。保留它们。用它们来记录约定、审查规则，以及不该触碰的东西。不要要求它们充当索引。一个列出三个重要目录的 `CLAUDE.md`，在一次包拆分之后的那一周就会过时。而一张可查询的地图，会随着仓库的更新而更新。

一个相关的失败是“几乎对”的文件：当行为其实在 `auth-client.ts` 里时，智能体却打开了 `auth.ts`；或者补丁打在了一个生成的文件上，而不是源文件；或者因为名字匹配，编辑了 `packages/legacy` 里的那份拷贝。引用不会让这些错误变得不可能发生。它们只是让这些错误在 diff 落地之前变得可见。

## 一张地图不会为你修复的东西

对自己得到的东西保持清醒。一张有依据的地图不会让每一次编辑都变得正确——你的智能体依然可能在完全正确的文件里写出一个糟糕的补丁。如果你的代码库依赖动态派发、反射或猴子补丁，一些符号查找返回的结果会比你希望的更单薄，因为运行时的间接性对任何静态索引都会造成这种效果。而如果你在期待一个百分比——“幻觉路径减少了 X%”——你在这里找不到，因为除了你自己，没有人能为你的仓库诚实地测出这个数字。

你可以期待的东西范围更窄，也更有用：智能体不再用一条猜测出来的路径来开始它的编辑。这第一步会扎根于一张真实的地图，而更少的幻觉编辑正是由此而来。引用之后的一切——阅读 diff、判断补丁——依然是你的工作，和以往一样。

这个测试几乎不花你什么成本：索引一个你已经了解的仓库，问一个你能核实的问题。从一条曾经让你吃过亏的路径开始。如果引用错了，你会立刻看出来。如果对了，你智能体的下一次编辑就有了一个更好的落脚点。

`// it doesn't know the file. it knows how to find it.`
