Docs: usage guide for dispatching work through Plane (routing, labels, replies, cancel, phone app notes)
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
Plane 看板驱动的通用 agent 调度服务:在 Plane 建工作项并指派给某个终端,agentd 在该终端起对应的 CLI agent(Codex / Claude Code / 脚本)执行,把结果贴回工作项并流转状态。调度是确定性代码;模型只出现在执行器和总指挥里。
|
||||
|
||||
- 使用说明(在 Plane 上怎么派活、回答、取消,标签和默认值):`docs/usage.md`
|
||||
- 设计:`docs/design.md`(架构、契约、失败策略、配置、阶段)
|
||||
- 首个租户:GWENT 项目(看板 https://plane.kappiee.com/kappiee/projects/79cb5a60-aa4f-4138-9864-1dd70426e665/issues/ )
|
||||
- 凭据全部经 Agent Vault 注入内存,仓库和配置里只有键名。
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
# 使用说明:在 Plane 上派活给各机器上的 agent
|
||||
|
||||
核对依据:`agentd/core.py`、`agentd/webhook.py`、`config/agentd.yaml`、LXC 上的实际状态、Plane GWENT 项目的标签和成员(2026-10-22)。代码或配置改了要同步改这里。
|
||||
|
||||
## 1. 派单需要的字段
|
||||
- **必填**:状态设为 `Todo`,指派人里至少有一个终端账号(`window10` 或 `oregon`)。标题加描述就是任务书,原样进入 prompt。标签可选,模块与调度无关。
|
||||
- 有多个指派人时,按 Plane 返回的顺序,第一个能对上终端的账号生效(`core.py` 的 `route()`)。所以"kappiee + window10"会派到 win10。
|
||||
- **只指派 `kappiee`、指派 `mac`(暂无终端)或不指派**:`route()` 返回空,这一项被静默跳过。Plane 上不会有任何评论,只在 `heartbeat.json` 的 `skipped` 里记一条 `no route for assignee kappiee`,`agentd.log` 里在原因第一次出现时记一行。
|
||||
- 只有 `Todo` 状态的项会被拾起(`pick()`)。Backlog、Waiting、Review 永远不会自动执行。唯一例外是处于 In Progress、等待临时性重试的项。
|
||||
|
||||
## 2. 终端、执行器和默认值
|
||||
|
||||
| Plane 指派人 | 终端 | 执行器 | 默认模型 / effort / 档位 | 运行目录(日志和输出) |
|
||||
|---|---|---|---|---|
|
||||
| `window10` | win10(Warpgate + Windows 计划任务) | codex(`codex exec`,`workspace-write`) | `gpt-6.1-sol` / `medium` / `fast` | `C:\…\gwent\runtime\agentd\<run_id>\`(`prompt.md run.ps1 events.jsonl last.md stderr.txt exit.txt`) |
|
||||
| `oregon` | oregon(Warpgate + `setsid nohup`) | claude-code(`claude -p --permission-mode acceptEdits`) | `sonnet` / (不传 effort)/ — | `/home/ubuntu/.gwent-board/agentd-runs/<run_id>/`(`out.json` 等) |
|
||||
| `kappiee` / `mac` / 无人 | 不派 | — | — | — |
|
||||
|
||||
- 两个终端的并发都是 1,按终端计数,跨项目共享。
|
||||
- win10 设了 `busy_processes: [codex]`:agentd 自己在 win10 上没有在途运行、却发现有 `codex.exe` 在跑时,不派单(`busy_process codex (… not started by agentd)`)。
|
||||
- oregon 的运行直接在 `/home/ubuntu/Documents/wjj/project/gwent` 里改文件。这正是指挥所用的 checkout。
|
||||
|
||||
## 3. 代码里实际生效的标签
|
||||
Plane 里目前只建了 4 个标签:`model:astra`、`model:sol`、`effort:high`、`needs-game`。其余前缀的标签要先在 Plane 里建出来才能挂上。
|
||||
|
||||
| 标签 | 效果(`route()`) |
|
||||
|---|---|
|
||||
| `model:astra` | 改用 gpt-6-astra,effort high(来自 by_label 配置) |
|
||||
| `model:sol` | 改用 gpt-6.1-sol,tier fast |
|
||||
| `model:<x>`(其他任意) | 模型名原样改成 x,例如 oregon 上的 `model:opus`。模型名与执行器相关:`model:astra` 挂在 oregon 的项上会让 claude 失败 |
|
||||
| `effort:<x>` | 只对 codex 生效。claude 的命令模板里没有 `{effort}`,所以被忽略 |
|
||||
| `tier:<x>` / `tier:none` | 只对 codex 生效,改档位或去掉档位参数 |
|
||||
| `needs-game` | 串行组 `game`:同组同时只跑一项;env 类失败会暂停整组,直到该项离开 Waiting。**`needs-*` 不是通用前缀**,只有配置里写了的才生效 |
|
||||
| `exec:<executor>` | 要求同名执行器存在且终端支持。现在每个终端只有一个执行器,例如 `exec:codex` 挂在 oregon 上只会得到 `executor codex not available` 跳过,等于没用 |
|
||||
| `cap:<x>` | 终端的 `capabilities` 里必须有 x。win10 有 `[android, game]`,oregon 没有,不满足就跳过 |
|
||||
| `budget:2h` / `budget:90m` | 覆盖超时时间,默认 4 h |
|
||||
|
||||
多个标签按顺序处理,后面的覆盖前面的。
|
||||
|
||||
## 4. 一轮的完整流程
|
||||
1. **触发**:Plane 的工作区级 webhook(`issue` 和 `issue_comment` 事件)约 1 s 内送到 `http://10.77.10.249:8790/plane`。
|
||||
- 接收端用 HMAC 校验签名,只认 GWENT 项目,其他项目返回 202 忽略。
|
||||
- 等 3 s,把这期间的投递合并成一次 tick。tick 跑的就是 cron 脚本。
|
||||
- tick 运行中又来投递时,结束后再补跑一次。锁被占用(退出码 75)时每 15 s 重试,最多 2 min。
|
||||
- 兜底:cron 每 2 分钟一次 tick,同一把 `cron.lock`。
|
||||
- agentd 自己回帖、改状态也会产生投递,所以每个有动作的 tick 后面都会多一次空 tick(实测 11.1 s)。
|
||||
2. **tick 的步骤**:先 poll 所有在途运行(每次中继调用约 10 s),再按编号从小到大挑 Todo 项。依次检查:中继是否通、并发槽位、串行组、busy 进程。
|
||||
- 启动前先把 `launching` 标记落盘,防止重复启动。
|
||||
- 启动后把项改为 In Progress 并指派给终端账号,以终端账号发评论 `[worker] 第 k 轮开始:codex / gpt-6-astra / high @ win10,新线程,run=GW-26-1。`
|
||||
3. **实测耗时**(runbook 记录和 LXC 的 webhook.log):
|
||||
- 建项到投递约 1 s,再加 3 s 合并窗口。
|
||||
- **win10 启动的那次 tick 91.4 s**(GW-26:建项 01:25:14,开工评论 01:26:49)。
|
||||
- oregon 启动的 tick 约 72 s。
|
||||
- 空 tick 4.6–4.8 s。
|
||||
- 瓶颈在中继调用(PAD-12),与触发方式无关。
|
||||
4. **结束时**:以终端账号回帖。
|
||||
- 第一行是 `[codex] 第 k 轮结束(exit=…,run=…,终端 win10,日志 <运行目录>)`,下面是 agent 的最后消息原文(`<pre>` 包裹,超过 6000 字截断,并注明全文所在路径)。
|
||||
- 再按最后消息首行的标签流转(`transition()`):
|
||||
|
||||
| 首行 | 状态 / 指派人 |
|
||||
|---|---|
|
||||
| `[review]` | Review,指派 `oregon`(reviewer) |
|
||||
| `[question]` / `[blocked]` | Waiting,指派 `oregon`(answerer) |
|
||||
| `[progress]` | 回到 Todo,留在原终端,下一 tick 续同一线程。连续 12 轮后转 Waiting |
|
||||
| 没有标签但 exit=0 | 按 review 处理,并注明"未按协议标注首行" |
|
||||
|
||||
注意:Waiting 和 Review 都指派给 **oregon,不是 kappiee**。没有任何东西会自动处理这两个状态,由指挥(或你)介入。
|
||||
5. **失败**:回帖 `[worker] 第 k 轮失败:类型=crash|timeout|env|logic,run,exit,重试 n/3。…` 并附上最后一帧输出。
|
||||
- 临时性错误(stderr 尾部匹配超时、429、5xx、连接被拒等)自动重试,退避 2/5/10 min,续原线程,状态保持 In Progress。
|
||||
- 续线程那一轮出现非临时性失败时,立即在新线程重跑一次,并附交接摘要。
|
||||
- 其余情况转 Waiting,指派 oregon。超时会先 kill 进程树。逻辑类失败永不自动重试。
|
||||
|
||||
## 5. 回答问题和续跑
|
||||
1. 在项上发评论回答,开头不要写 `[worker]`,这类评论永远会被跳过。
|
||||
2. **把状态改回 Todo,并把指派人改回原终端**(例如 `window10`)。这一步是坑:如果指派人还是 oregon 就改 Todo,会派给 oregon 的 Claude。因为终端或执行器变了,会**重建线程**并附交接摘要。
|
||||
3. 同一终端、同一执行器、线程续了不到 8 轮时,走 `codex exec resume` 或 `claude --resume`,只发送上次之后的新评论(按评论 ID 判断)。
|
||||
4. 单发评论只会触发一次空 tick,**不会**让 agent 动起来,必须改回 Todo。运行期间发的评论,跑着的那一轮看不到,下一轮才带上。
|
||||
|
||||
## 6. 取消和停止
|
||||
- **把运行中的项移出 In Progress**(改成 Waiting、Backlog、Cancelled 都可以)。下一 tick 会 kill 进程树,回帖 `[worker] 运行已取消:工作项状态被改为 X(run=…)`,释放槽位和串行组,保留线程 ID(`cancel()`)。
|
||||
- 如果移到的是 **Todo**:同一 tick 里先取消,再立刻按新一轮重新派发(续原线程),相当于"带上新评论重启"。
|
||||
- 运行已经结束时(`exit.txt` 已写)再移动:结果照常回帖,但不再改状态,也不重试。
|
||||
- 暂停整个终端:把它的 `concurrency` 设为 0(需要改配置,不能在 Plane 里操作)。
|
||||
|
||||
## 7. 日志和状态的位置(LXC)
|
||||
- `/var/log/plane-agentd/{agentd.log, cron.log, webhook.log}`
|
||||
- `/var/lib/plane-agentd/{agentd-state.json, heartbeat.json}`:heartbeat 里有 `skipped` 及原因、`inflight`、`down`。
|
||||
- 健康检查:`GET http://10.77.10.249:8790/healthz`
|
||||
- 任务产出本身在终端的 repo 里,gwent 的惯例是 win10 的 `runtime/edits/GW-k/`。
|
||||
|
||||
|
||||
## 8. 用手机试一下(冒烟测试,5 步)
|
||||
1. GWENT 新建工作项,标题 `冒烟 oregon 往返`。描述:`只回复一行 [review] ok;不要读写或修改任何文件,不要运行命令。` oregon 的 Claude 是 acceptEdits,并且在指挥用的 checkout 里运行,所以这句必须写。
|
||||
2. 指派人**只选 oregon**,不加标签(默认 sonnet),状态设为 **Todo**。
|
||||
3. 约 1–1.5 分钟后:状态变成 In Progress,出现 oregon 发的评论 `[worker] 第 1 轮开始:claude-code / sonnet @ oregon,新线程,run=GW-n-1。`
|
||||
4. 再过约 1–3 分钟(历次冒烟 1.5–3 min):出现评论 `[claude-code] 第 1 轮结束(exit=0 …)` 加 `[review] ok`,状态变为 Review、指派 oregon。
|
||||
5. 可选,测续线程:评论 `请只回复 [review] ok 2`,状态改回 Todo(指派保持 oregon)。开始评论会写"续线程 xxxx",结束后回 `[review] ok 2`。最后手动改成 Done。
|
||||
- 超过 3 分钟没动静:看 heartbeat 的 `skipped`,常见原因是 oregon 槽位被占,或指派人不对。
|
||||
|
||||
## 9. 通知和手机 App(2026-10-22 核实)
|
||||
- Plane 官方手机 App 可以登录自建的 Commercial 版(选 "Self hosted sign in",填 `https://plane.kappiee.com`)。plane.kappiee.com 只对内网和 tailnet 开放,手机要开 Tailscale。
|
||||
- **自建实例没有手机推送**:Plane 文档原文 "Push notifications are currently available only for Plane Cloud users."(docs.plane.so/devices/mobile)。App 里只能在收件箱看到通知。
|
||||
- 收件箱只收你被指派、被 @、创建或订阅的项。Waiting 和 Review 现在都指派给 oregon,不会进你的收件箱。需要你处理的项,由指挥改成指派 kappiee 或 @你。
|
||||
- 真正推到手机要走外部渠道:给 Plane 配 SMTP 发邮件,或用 ntfy 之类。计划放在最后(PAD-13)。agentd 里现在的 `notify: {kind: none}` 是空钩子。
|
||||
Reference in New Issue
Block a user