Cursor Agent 转了二十七分钟:活干完了,对话框还在转
真慢、假慢,以及我怎么把 Agent 从乱探索里拽回来
事情是这样的。
新博客想扩一下顶栏导航:相册、日志、歌单,保持现在的极简风,顺带照顾移动端。按理说这是个「读顶栏组件 → 加三个入口 → 复用现有汉堡菜单」的小活。丢给 Cursor Agent 之后,我去倒了杯水,回来一看——
Worked for 27m 18s.
文件改动已经出来了:Edited 6 files, +338 -11,结论也写了「做法」。可对话框还在那转,像加班到深夜还不肯交钥匙的同事。
我第一反应:是不是又卡死了?第二反应:加三个导航入口至于跑半小时?第三反应:emmm,先别急着重装,这锅说不定能拆成两半。
先分清:是真慢,还是假转#
后来对照社区反馈和自己这边的现象,这种「结果已经落地、UI 还在转」大致分两种:
| 类型 | 你会看到什么 | 本质 |
|---|---|---|
| 真慢 | Worked for 27m,探索了很多文件,diff 胖得离谱 | 工具轮次多、搜索面大、命令拖后腿 |
| 假慢 | 磁盘上的文件早就改好了,聊天还在 Planning / Editing | 流已经结束,客户端状态机没收到结束事件 |
我这次两边都沾一点:活确实干重了(真慢),收尾时 UI 又跟不上(假慢)。
假慢这事儿挺像业务里那种经典 bug——接口都 200 了,按钮还在 loading。副作用发生了,本地 isRunning 没跟完成信号对齐。Reload Window、开新聊天、Cmd+Q 重开,往往能把这层「假死」清掉。官方也承认过:后端 turn 已经成功,客户端就是没登记结束。
但如果你每次任务都动辄十几二十分钟,只靠 Reload 治标不治本。得往 Agent 执行管线里挖。
Agent 为啥会把小活干成大活#
可以把 Agent 想成带工具的 ReAct 循环:
用户意图 → 选工具 → 读/搜 → 再推理 → 再改 → … → 最终回复每多一轮,你都在付账:
- LLM 再想一遍、再选一次工具
- 上下文越堆越长(历史对话 + 文件内容)
- 磁盘读写、全库搜索、Shell 命令
- 流式通道上的 token 和工具事件
我那次需求本质是「扩导航」,结果变成:桌面入口 + 移动端菜单 + 样式对齐 + 多文件联动,一口气 +338。不是 Vite 编译慢,是搜索空间和改动面失控了。
前端同学面试时要是被问「为什么 Agent IDE 有时特别慢」,可以这么答:
墙钟时间 ≈ 探索深度 × 工具轮次 × 上下文长度 × 流式链路质量。
UI 假转则是另一层:完成事件和本地运行态不同步。优化优先剪枝和稳网络,Rule / Skill 只能约束行为,修不了客户端状态机的 bug。
对话框转圈背后的前端原理#
Agent 面板本质是挂在 SSE / WebSocket 上的流式状态机,大概长这样:
idle → streaming → tool_running → streaming → … → completed转圈绑定的是客户端本地状态,不是「工作区文件有没有改完」。常见翻车点:
- 传输层半断开:VPN / 公司代理对长连接静默掐流,后端写完了,客户端收不到
done - 事件丢了或乱序:工具结果到了,
turn_complete没到,UI 停在 Planning - 长对话状态膨胀:消息树太大,重渲染和状态合并变慢,看起来像「卡一下才刷完」
- 子 Agent 僵尸卡片:活干完了,Working 面板还挂着 Starting up
我这边还有个更扎心的证据:往 Cursor 设置里写 User Rule 时,请求 api2.cursor.sh 的证书居然变成了 *.toolbox.bluelabellabs.io。这是典型的 HTTPS 中间人 / 残留代理。短请求或许还能糊弄过去,Agent 那种十几分钟的长流,最容易被拖成「后台在干活、前台在发呆」。
所以网络排查别只跑内置 Diagnostics(它偏短连接,容易误报健康):
- 关 VPN,Cmd+Q 彻底退出再开
- Settings → Network → HTTP Compatibility Mode 试 HTTP/1.1
settings.json里可加"cursor.general.disableHttp2": true- macOS 系统设置里清掉已经卸掉的 VPN 配置残留
我怎么把它拽回来的#
假转靠 Reload / 新聊天急救。真慢靠收窄输入 + 约束行为。
提问时就把刀磨快#
别再丢一句「帮我扩下导航,顺便看看移动端」。改成:
只改顶栏导航:增加 相册 / 日志 / 歌单 三个入口。参考现有 @Header.tsx,保持极简风格。移动端用现有汉堡菜单扩展,不要重构布局,不要改其他页面。改完直接给结果,不要额外跑测试 / 构建。@ 文件等于给算法一个明确起点,比让它自己 Explore 半个仓库香太多。
能拆就拆:第一轮只加桌面三项,第二轮再补移动端。长对话越往后越容易又慢又卡,独立小任务尽量新开 chat。
写一条始终生效的 Rule#
Skills / Hooks 治不了假 loading,但能挡住「无意义探索、默认跑 build、顺手重构」这类范围膨胀。我落了一条 alwaysApply 的规则,核心就几句:
- 用户
@了路径,就优先只读这些,禁止无必要全库广搜 - 小改动最多先读 3~5 个相关文件就动手,别动不动开一堆子 Agent
- 严格按明确范围改,不顺手重构、不补无关文档
- 不默认跑 build / test / lint / typecheck / dev server
- Shell 设超时,别挂着
tail -f空等 - 能一次改完就少来回试错;收尾用短结论,别长篇复盘空转
文件放在 ~/.cursor/rules/agent-speed.mdc。若新对话没吃到,再把同样内容贴进 Cursor Settings → Rules → User Rules。
面试题版收束(顺便当笔记)#
题: Cursor 一类 Agent IDE 里,改几个导航入口要跑二十多分钟;文件改完了对话框还在转。请从执行管线和前端实时同步两边讲原理,并给优化手段。
答的骨架:
- 先分类:真慢(探索 / diff / 命令) vs 假慢(流结束了 UI 状态没对齐)
- Agent 侧:ReAct + 工具调用;成本随轮次和上下文线性(甚至更差)上涨;小需求大 diff = 改动面失控
- 客户端侧:流式状态机;
isRunning依赖完成事件;代理 MITM、HTTP2、长对话都是高发区 - 优化分层:输入剪枝(
@、拆任务、短对话)→ 策略约束(Rule)→ 运行时(少子 Agent、命令超时)→ 传输(直连、清代理)→ 产品兜底(Reload / 新 Chat)
一句话:Agent 慢看搜索和轮次,UI 假转看完成信号;Rule 管行为,网络管长流,Reload 管客户端犯病。
下次再看见对话框转个没完,先看 diff 在不在,再决定是骂网络还是骂自己 prompt 写得太宽。活干完了还在转,未必是你不够勤快——也可能是状态机比你更固执。