AI 编码 Agent 会话状态:七态分类法与测试清单

一个 AI 编码 Agent 的会话监控应该区分七种运行状态:inactiverunningwaiting_for_usercompletedblockedstalledunknown。事件、文件、进程、hooks 和通知是这些状态的证据,它们本身不是状态

本文为会话监控定义一套与服务商无关的分类法,面向开发者工具的维护者、对比编码 Agent 工作流的研究者,以及编写运维指引的团队。目标不是把 Claude Code、Codex 或别的工具说成一模一样,而是让「运行中」「在等用户」「卡住」这类说法变得可测试

监控应该说明现有证据当下支持什么,而不该把安静、文件活动或者一个旧的完成标记变成确定性

范围与观测单位

观测单位是一个本地的编码 Agent 会话或线程。服务商层面的角标可以汇总多个会话,但不该抹掉它们的身份。每一次观测至少需要:服务商、稳定的会话键、观测时间,以及最近一次相关活动的时间

这套分类法描述的是运行状态。它不判断生成的代码是否正确、测试是否通过,也不判断任务在项目管理意义上是否完成

七种主状态

状态最低证据它证明不了什么
inactive没有关于活跃回合的新鲜证据会话是被有意关掉的
running与当前回合绑定的新鲜的开始、进展、工具调用或流式活动正在产出有用的工作
waiting_for_user一次新鲜且明确的授权、征询、澄清,或其它必须由用户完成的动作请求用户没有在别处已经回答过
completed当前回合有一个终止事件,且之后没有活动把它取代代码是对的,或者整件事已经做完
blocked一个明确的认证、额度、策略、服务商或执行失败,阻止了正常继续这个失败是永久的
stalled回合此前在运行,随后超过了一个写明的静默阈值,期间没有终止或受阻事件进程崩溃了,或者无法恢复
unknown证据缺失、互相矛盾、不受支持,或者旧到不足以支撑别的状态什么都没在发生

completedwaiting_for_user 在面向用户时可能都被处理成「轮到你了」,但在证据模型里必须保持区分。一个表示回合结束了,另一个表示 Agent 明确要求输入才能继续

把修饰词挡在主状态之外

产品常常因为把原因、置信度、新鲜度和呈现方式混在一起,造出太多状态。把它们当成修饰词:

  • 原因:授权、征询、认证、限流、API 错误、进程退出,或静默超时
  • 新鲜度:观测时刻该语义事件的年龄
  • 置信度:明确、推断,或兜底
  • 注意力:无、告知、需要用户动作,或紧急恢复
  • 回合身份:让去重成为可能的那个事件键或回合键
  • 来源:生命周期 hook、结构化会话记录、进程信号、文件系统元数据,或启发式

这样分开之后,界面可以说「受阻:认证」,而不必把每一种失败原因都做成一个新的顶层状态

证据的优先级

当信号互相矛盾时,采用属于当前回合的、最具体的新鲜证据。一个可行的优先顺序是:

  1. 与当前回合绑定的明确语义事件,比如一次授权请求、一个终止事件,或一个结构化的服务商错误
  2. 之后出现的、把更早事件取代掉的用户或 Agent 活动
  3. 相互关联的进程与会话活动
  4. 在拿不到语义时间戳时,退而使用文件修改时间
  5. 基于静默的推断 —— 它可以支撑 stalled,但永远支撑不了 completed

顺序是要紧的。一个新鲜的完成事件应该压过稍旧的进程采样;之后出现的用户提示应该撤销那次完成;文件修改时间不该仅仅因为之后有记账动作碰过文件,就压过一个结构化错误

会话状态的证据与任务完成的证据解决的是相邻的问题。Manazir Ali 的 Operating Standard for Harness-Based Agents 把同一套纪律延伸到完成声明上:在相信一句「做完了」之前,先要拿到提交哈希、测试输出和退出码这类实物

参考状态迁移模型

observe(session, now):
  evidence = newest_semantic_evidence(session)

  if evidence is missing or contradictory:
      return unknown
  if explicit_blocker_is_fresh(evidence):
      return blocked(reason=evidence.reason)
  if explicit_user_action_is_fresh(evidence):
      return waiting_for_user(reason=evidence.reason)
  if terminal_event_is_fresh(evidence)
     and not superseded_by_later_activity(evidence):
      return completed(turn=evidence.turn_key)
  if execution_activity_is_fresh(evidence):
      return running
  if previously_running(session)
     and silence_exceeds_documented_threshold(session):
      return stalled(confidence="inferred")
  return inactive

这个模型需要两条过期策略:一条给活跃证据,一条给注意力。一个旧的完成回合不该在周末之后还把用户叫回来;卡住状态同样要老化掉,而不是变成一条永恒的警告

评估清单

一个监控不会因为认得出顺利路径上的完成字符串就算稳健。至少用这些测试来评估它:

  1. 新回合:新的一轮进入 running,不继承上一轮的终止状态
  2. 重复观测:同一个事件被处理两次,但只产生一条通知
  3. 取代:之后出现的用户提示撤销更早的 completedwaiting_for_user
  4. 明确输入:授权与征询请求要与普通完成区分开
  5. 服务商错误:一个长得像终止的错误信封变成 blocked,而不是 completed
  6. 静默:缺少活动可以变成 stalled,但永远不能变成一次编造出来的成功
  7. 重启恢复:重启监控后,能从持久证据重建当前状态
  8. 多会话:一个已完成的线程不会盖住另一个还在跑的线程
  9. 时钟偏移:畸形或未来的时间戳退化到一个写明的兜底方案
  10. 写到一半:被截断的记录变成 unknown 或者重试,不会把状态引擎搞崩
  11. 过期:旧的终止与卡住状态回到 inactive
  12. 隐私:测试要核实原始会话内容在哪里被读取、被保留、被传输

四个评估层级

层级能力需要的证明
L0 展示显示服务商或进程是否存在当前的进程/会话发现
L1 认事件认得出开始、输入、完成和明确失败事件每家受支持服务商的结构化样本
L2 认回合跟踪身份、新鲜度、取代关系与去重状态迁移测试与重复事件测试
L3 可运维重启后能恢复、能处理多个会话、让过期的注意力老化、写明隐私边界重启、多会话、畸形输入、过期与数据流测试

这些层级是累积的。它们描述的是证据质量,不是产品质量。一个定位清楚的 L1 工具可以很有用,它只需要避免去做 L3 的声称

实现说明

Agent Island 在 Claude Code、Codex、Antigravity、Grok 和 Cursor 上应用了这套模型的本地版本。它读取机器上本来就存在的会话产物,把面向用户的状态集合保持得很小,并且不把会话数据上传到 Agent Island 的服务。当前稳定版本是 v1.7.1

想深入看其中一次迁移,见 为什么完成事件不等于会话状态。想看埋点方式的取舍,见 Claude Code hooks 与常驻会话监控。想横向对比这个品类,用 Agent Island 对比中心。产品的数据边界写在 隐私页

建议引用方式与更新策略

建议引用:Tristan Tang,「AI Coding Agent Session State Taxonomy and Evaluation Checklist」,Agent Island,2026 年 7 月 20 日,https://agent-island.dev/blog/ai-coding-agent-session-state-taxonomy/

本资源按发布日期与修改日期版本化。只有当某个状态在受支持的证据来源上无法再被一致地测试时,定义才会改变。服务商特有的事件名属于实现说明,不属于与服务商无关的定义部分