用pi agent时会出现一条指令卡很久的现象,可能有哪些原因呢?

先说结论:pi 里「一条指令卡很久」基本不是单点问题,而是 agent loop、工具执行、provider 流、扩展钩子这几层里某一层没返回。按「CPU 有没有在动 → 卡在哪个工具 → 最小环境能不能复现」三步走,多数情况能定位到具体那一层。 一、先分清是「没卡」还是「真卡」 有时候纯粹是慢:Opus 这类模型本来思考就长,本地小模型(有人用 gemma 12b)会反复触发压缩,表现就是长时间不冒字。也有人反馈「有时候是视觉上的卡,有时候只是思考更久,有时候是真卡」,这三种在 UI 上长得一模一样。 区分办法:另开终端看 pi 进程的 CPU。或者有流式 token 偶尔还在来,说明活着;CPU 接近 0 又长时间一个字不出,基本是在等 IO(网络流或者子进程)。 二、工具层挂住(最常见的真卡) 最关键的一条:pi 原生 bash 工具没有默认超时。有人专门写扩展来补,原话就是 native bash tool has no default timeout — a hanging command blocks the agent forever。所以只要 agent 跑了一条永不退出的命令,这一轮就无限期等下去,不是「慢」,是永远等不到。 会被挂住的是那批直接开 /dev/tty 或者 loop 到被杀的命令:vi/vim/nvim/nano/emacs、top(除非 batch 模式)、watch、fzf/peco、bun repl 和 deno repl、git rebase -i(没设 sequence editor 时 git 回落到 vi)。反直觉的是 python、node、irb、sqlite3、less、man、ssh 这些在 pi 的环境里(stdin 是 /dev/null、stdout 不是 TTY)会自己退出——之所以要强调,是因为按常识猜很容易猜错方向。 对应两个现成的护栏:@lukeramsden/pi-prevent-stuck 专门拦上面这批(只拦在 pi 那个环境下实测会挂的),@cad0p/pi-bash-timeout 给 bash 补 120 秒默认超时,超了显示 Command timed out after N seconds。 工具层的其他坑:write 工具写大文件会超时(有人报 LM Studio + qwen 下 5 分钟);MCP server 或扩展卡在启动/握手,整个 turn 会停在工具调用之前,一点进度都不给;主 agent 静默等 subagent 结果的时候,界面上也常常什么都不显示。 三、模型 / provider 层 流卡住没有 idle 超时:社区 issue 报过一个 pi-native transport 的坑——响应头回来了但事件不来,因为没设 stream idle / first-event timeout,就一直挂着。@narumitw/pi-retry 这类扩展的做法是起一个 stall watchdog,卡住就重试。 会话中途切 provider 会把 loop 挂死:官方仓库 #3258 记录得很具体,会话里从 GLM-5.1 切到 Gemini(或反向),之后 RPC 完全无响应,看不到 error 也收不到回复,切回原来的 provider 也救不回来,只能重启进程。所以别在会话中途换。 配额和限流:Reddit 那帖里好几个人对上了——用 OpenCode 免费额度那类模型会静默挂住,换成本地模型跑同一个会话就正常;还有人就是 quota 用尽。特征是没有任何报错,纯不动。 自动重试和自动压缩阶段:pi 的长任务不只是一个开关,底层是 agent loop 的多轮工具调用,外面还叠了后处理驱动循环(自动重试、自动压缩)。这些阶段界面上可能长时间没有新内容,本地模型上还有人反馈「每次 compaction 之后 agent 就不往下做了」。这块想细看可以搜《Pi Agent 长任务处理:从工具超时到会话恢复的六层机制》,讲得比我这里细。 四、扩展 / Skill / 上下文层 扩展自身的 bug:有人就是自己写的扩展在某些边界情况下死循环,表现是 CPU 常驻 100%(原话 near 100% cpu pinned)。 扩展装太多:多个来源都把「扩展多」列为诱因,官方那帖的建议是用「禁用 skills、extensions、不带 context」起一遍看还挂不挂。 agents.md 或它引用的 markdown 坏掉:那个 Reddit 楼主修好 agents.md 之后就正常了,原因是里面引用了一个旧文件导致挂在解析上。但评论里也有人反驳说这其实是 provider 问题——两种都真实存在,所以别只往一个方向查。 还有一种「假卡」:agent 其实已经答完了,界面一直显示 working,要等超时或者手动停才恢复(multica #2188 报的就是这个,用 hook agent_end 的扩展能绕开)。这种跟你发的那条指令完全无关,是 harness 状态同步的问题。 五、给你的排查顺序 1)看 CPU 和有没有流式输出,把「在算」和「在等」分开。 2)Esc 中止这一轮(pi 里 Esc 是中止,中止时会连带处理命令派生的子进程)。看它停在哪一步工具调用,那一步基本就是元凶。 3)最小环境复现:临时禁用 extensions / skills / MCP,再换个 provider 试。换 provider 就不挂 → provider 问题;只有挂上某个扩展才复现 → 那个扩展的问题。 4)确认是模型侧响应不来,就装 stall watchdog / 重试类扩展;确认是命令类,就装 bash 超时和 prevent-stuck。这类卡本来就是「知道它会发生,就别让它无限期挂着」。 5)如果这轮会话已经切过 provider、fork 过、或者压缩过好几轮,直接开新会话通常比抢救旧会话划算。 如果你能说一下卡的时候具体是什么状态(有没有流式输出、走到了哪一步、用的哪个 provider、装了什么扩展),我可以帮你缩到更窄的范围。