观察运行
以人类身份通过 Viewer 监控运行中的工作流程,或以 Agent 身份通过 JSON 监控。
工作流程的编写、执行、观察与审批都以命令形式提供 --json 输出,因此驱动 Kilin 的既可以是终端前
的人,也可以是监督其委派工作的外层 Agent 运行时。非交互式安装需要显式指定提供方,例如
kilin skills link --providers agents。Viewer 仍是面向人类的检查界面,外层 Agent 可以通过
--json 启动并监管其附着式 CLI 进程。
┌─────────────────────────────────────────────────────────────────┐
│ OUTER AGENT RUNTIME │
│ a person at a terminal · or Codex / Claude Code / a script │
└─────────────────────────────────────────────────────────────────┘
│ ▲
│ create kilin workflow init │ monitor runs list · runs show
│ update edit WORKFLOW.yaml │ track runs wait --json
│ start kilin run · kilin trigger │ inspect kilin ui
│ decide runs approve · runs reject │
▼ │
┌─────────────────────────────────────────────────────────────────┐
│ KILIN │
│ validate → compile → immutable revision → execute │
│ SQLite history · captured logs · JSONL event stream │
└─────────────────────────────────────────────────────────────────┘
│ ▲
│ spawns provider subprocesses │ results · logs · decisions
▼ │
┌─────────────────────────────────────────────────────────────────┐
│ INNER WORKFLOW — one run │
│ │
│ analyze ──▶ implement ──▶ [approval] ──▶ verify │
│ read_only workspace_write barrier read_only │
│ Claude Code Codex Codex │
└─────────────────────────────────────────────────────────────────┘外层运行时始终位于运行之外。它无法伸手干预正在执行的节点,对 WORKFLOW.yaml 的任何修改也无法
改变本次运行所执行的内容,因为 Kilin 在第一个节点启动前就已记录了不可变修订。
下面两种视图读取的是同一份本地 SQLite 历史,谁都不是对方的简化版本。
以人类身份
为正在运行的工作流程打开 Viewer:
kilin ui change-review --cwd /absolute/path/to/projectViewer 只绑定数字形式的 127.0.0.1,端口由操作系统选择。它展示已编译的图、随时间变化的节点状态、
该工作流程标识与工作目录下最新的 50 次运行、血缘关系、审批元数据、失败信息、有界的捕获输出,
以及 Decision Packet。
加载时,Viewer 会打开最相关的已存储运行——优先是等待审批的运行,其次是正在运行的运行,最后是 最新完成的运行——并选中最能解释运行状态的节点。没有已存储运行时,它保持当前定义视图。所选运行、 节点、输出流与渲染/原始视图会保存在 URL 哈希中,重新加载后即可恢复原位。
顶栏提供 Refresh 控件,它会立即请求当前状态并重置轮询退避。当捕获的输出流加载失败时, 输出面板会提供 Retry 控件以再次请求该输出流,Refresh 也会再次请求它。当图高于容纳它的区域时, 工作流程状态旁会出现 Expand 控件,它会提高高度上限,让分支较多的工作流程更少需要滚动; 该选择会在轮询期间保留,直到你再次收起。
Refresh 旁边,在浏览器支持通知时会出现一个通知控件。授予权限后,当某次运行在其标签页处于隐藏状态 时开始等待审批,Viewer 会提醒你——它会为该次运行发出一条通知,点击它即可回到那里。隐藏的标签页 不会停止轮询,而是降到十五秒的较低频率,因此你在别处时到达的审批仍会被捕捉到;切回该标签页会立即 轮询一次并恢复正常频率。
选中某个节点时,图会滚动到该节点,因此大型工作流程中位于可见区域下方或侧边的节点无需你手动滚动 即可进入视野。
循环节点的卡片始终保留 loop 字样,并在某次迭代开始后补上迭代进度 loop · 2/3;在此之前
保留上限 loop · up to 3。选中它会把卡片
展开为一个容器,画出最新已开始迭代的循环体流水线——各循环体节点及其状态、revise 反馈边与 pass
出口——选中某个循环体节点即可查看该次执行的证据。若选中的是更早迭代中的执行,则改为绘制那次迭代。
只有一个循环节点的工作流程会以展开状态打开。
Loop iterations 面板会列出每一次已记录的迭代,并在首次迭代之前先给出循环体的节点名。
当运行停在审批节点时,Viewer 会显示受保护的 Approve 与 Reject 按钮,并同时给出等价的 CLI 命令。
可选的备注是多行输入框:Enter 只会换行,只有 Approve 或 Reject 才会提交。
正在运行的运行还会在等价的 kilin runs cancel 命令旁提供 Cancel run 按钮。这两项就是它全部的状态
变更面,且是一个封闭集合:它不能编辑工作流程、启动 provider 运行,也不能调度任务。加上 --no-open
可只打印启动 URL 而不打开浏览器;请把该 URL 视作凭据。
不使用浏览器时,同一份历史也可以用文本查看:
kilin runs list
kilin runs show <run-id>以 Agent 身份
内置运行 skill 会先验证当前可见的 package;当请求者的浏览器可访问同一个 loopback 时,它会将
kilin ui <id> --cwd <directory> --no-open --json 作为受管理的附着式进程启动,并直接返回
viewer.started URL。无论 run 成功还是失败,Viewer 都会保持运行,直到被停止或外层 Agent
会话结束。如果 Agent 在另一台机器上运行或无法保留该进程,它会使用请求者的本地项目路径返回
手动命令,不会声称远程 127.0.0.1 URL 可访问。只有本地 Viewer 能访问同一份 Kilin 数据时,
它才会显示相同的历史记录。
kilin run --json 以每行一个 JSON 对象的形式流式输出。每个事件都带有 outputVersion: 1 和 type:
run.started · node.started · node.finished · approval.requested
approval.resolved · run.finished · error不必轮询,直接阻塞等待运行下一次需要关注或进入终态:
kilin runs wait <run-id> --json控制方可以在第二个本地进程中记录决策,同时运行仍附着在第一个进程上,因此无需抓取终端输出:
kilin runs approve <run-id> <approval-node-id> --actor agent
kilin runs cancel <run-id>停止附着的 kilin run 进程本身也会停止该运行。SIGINT、SIGTERM 和 SIGHUP 都通过同一条取消路径,
因此监督进程、容器停止、CI 取消或关闭终端都会终止提供方进程树,而不是让它变成孤儿进程,命令以 130
退出。如果某次运行被直接杀死且无法清理,下一个在该目录中工作的命令(包括再次执行 kilin run)
会在开始之前结束它遗留的进程。
失败会携带稳定的错误码 —— NODE_TIMEOUT、LOOP_LIMIT_REACHED、APPROVAL_REJECTED 等 ——
因此监督方 Agent 可以基于错误码分支,而不必解析散文。runs list、runs show 和 workflow validate
同样接受 --json。
监控不会暴露的内容
声明的运行参数被刻意排除在生命周期事件、runs list、runs show 和 Viewer 之外。循环迭代按迭代分组,
但不会暴露参数、反馈、决策选项或结果值。
捕获的 stdout、stderr 和结果保留为数据目录下的私有本地文件,而不是事件载荷。关于这些历史可能包含 什么,参见信任边界;完整的参数面参见命令参考。