MadoHub Docs

Agent 检测

MadoHub 如何识别正在运行的 AI Agent 并追踪其状态。

MadoHub 会实时监控终端输出,识别当前运行的是哪个 AI Agent,以及它处于什么状态。这个能力支撑了图块标题栏上的可视化指示器,以及路由连接的触发逻辑。

支持的 Agent

Claude Code

通过终端输出中的 Unicode 标记进行检测:

标记含义
❯ (U+2770)Claude Code 提示符
✽ (U+273D)思考/加载指示器
⏺ (U+23FA)工具使用指示器

同时也会匹配输出中的字面字符串 "Claude Code"。

OpenAI Codex CLI

通过以下模式进行检测:

  • OpenAI Codex — 品牌行
  • codex> — TUI 提示符
  • openai/codex — 包引用
  • codex v[0-9] — 版本字符串
  • > _ OpenAI Codex — 启动横幅
  • codex --dangerously — 沙箱绕过标志(不区分大小写)
  • codex ... fast — 快速模型调用(不区分大小写)
  • gpt-[0-9.]+ x?high — 模型信息

Amp 和 OpenCode

Amp 和 OpenCode 同样被识别为 Agent 类型,但不是通过上述前端终端文本探测器识别的——该探测器只能分类 Claude Code、Codex 和通用 shell。Amp 和 OpenCode 会话是单独识别的:由后端的进程树扫描来完成,它会遍历终端的子进程,查找它们对应的可执行文件。

通用 shell

如果没有检测到任何 Agent 标记,终端会被当作标准 shell 会话处理。

Agent 状态

MadoHub 为每个终端追踪七种状态:

状态检测方式可视效果
Working状态栏中出现 "esc to interrupt",或出现带省略号的 ✽/⏺绿色脉冲边框
Idle状态栏中出现 "? for shortcuts"无指示器
Waiting出现 "Allow once" / "Allow always" / "Deny" / "Do you want to proceed?" / "(y/n)" / "requires approval" 对话框橙色边框
Stopped通过终端抓取检测到完成关键词(存在歧义——任务可能成功结束,也可能没有)红色指示器
Completed确认成功结束,从 Agent 自身的 JSONL/DB 会话日志中解析得出(例如 Codex 的 task_complete)绿色指示器
Failed确认失败,从 Agent 自身的 JSONL/DB 会话日志中解析得出(例如 Codex 的 turn_aborted / error)红色指示器
Exited底层 PTY 进程已消失(终态)灰色/暗淡指示器

每个状态都带有 stateSource 标记,取值为 pty-scrape 或 jsonl-watcher,让 UI(以及任何路由逻辑)能够区分"仅凭终端实时抓取推测出的结果"和"通过读取 Agent 自身会话记录确认的结论"。"Stopped" 始终是 pty-scrape,本质上具有歧义;"Completed" 和 "Failed" 来自 jsonl-watcher,被视为权威结果。

完成检测

MadoHub 判断 Agent 是否完成任务,靠的是匹配一种形状(shape),而不是固定的关键词列表:行首的加载符号,紧跟一个大写开头的过去式动词,再紧跟 " for " 和一段时长。

正则表达式模式:

/(?:^\s*[✶✽✳✢·∗*]\s*([A-Z][a-zé]+(?:ed|t))|\b(Saut[ée]*d|Cogitated))\s+for\s+(?:\d+\s*[hm]\s*)*\d+\s*[hms]\b/

Claude Code 在不同版本之间会轮换使用不同的动词(Worked、Churned、Sautéed、Cogitated 等),所以动词本身是故意不做穷举的——匹配依赖的是形状本身。一个真实的匹配示例:

✽ Worked for 2m 30s

行首的符号锚点(✶✽✳✢·∗* 之一)正是用来避免把普通文本(例如 "Retried for 3s")误判为完成的关键所在。Sautéed 和 Cogitated 之所以还留在该模式中,仅仅是作为没有符号锚点的旧版兜底方案,用来兼容早于符号锚定格式的老版本 CLI 输出。

当检测到完成状态时,Agent 状态会变为 "stopped",并且任何已连接的路由触发器都可能随之触发。

On this page