Files
plane-agentd/docs/runbook.md
T
jj.wang ca2b47eb5f Docs: binary resolution, cancellation, progress cap, phase-1 deviations
- runbook: how executor binaries are resolved (bins or PATH) and what that
  assumes on oregon (no codex installed) and win10; cancellation and
  max_progress_rounds in the item lifecycle; secrets scrubbed from children.
- design: blocked-by ordering is a TODO (not read by the scheduler); failure
  classification, success-when-tagged, one-time immediate rebuild, retries
  outside the thread-round budget, ID-based new-comment filter.
- executor contract: how core reads ExecResult, kill used for cancel, Windows
  quoting assumptions, codex exec resume without -C/-s.
2026-10-21 07:14:20 +00:00

8.4 KiB
Raw Blame History

运行手册

安装

git clone https://git.kappiee.com/kappiee/plane-agentd.git && cd plane-agentd
python3 -m pip install --user pyyaml          # 唯一依赖;有 jsonschema 时用它校验,否则用内置子集校验器
cp config/agentd.example.yaml config/agentd.local.yaml   # git-ignored;或用 AGENTD_CONFIG 指向别处
cli/agentd check-config                       # 校验 + 列出各终端 token 环境变量是否已注入 + cron 所需 --secret-env 参数
python3 -m unittest                           # 离线单测

配置里只写 Vault 键名(token_key)。agentd 读同名环境变量,token 只由 agent-access.py exec --secret-env KEY=KEY 注入进程内存;不要 export 到 shell、不要写文件。agentd 起的所有子进程(本机 runner/执行器、win10 中继脚本)拿到的环境都去掉了全部 token_key 与 webhook_secret_key 变量。

运行

单次 tick(cron 推荐):

cd ~/.local/share/server-access-client && python3 -I agent-access.py \
  --config https://nas.tail9531b.ts.net:8443/identity/agent.json exec \
  --secret-env PLANE_OREGON_API_TOKEN=PLANE_OREGON_API_TOKEN \
  --secret-env PLANE_WINDOW10_API_TOKEN=PLANE_WINDOW10_API_TOKEN \
  --timeout 900 -- /home/ubuntu/Documents/wjj/project/plane-agentd/cli/agentd tick --once

crontab(每 2 分钟;tick 有文件锁,重叠的 tick 直接跳过):

*/2 * * * * cd $HOME/.local/share/server-access-client && python3 -I agent-access.py --config https://nas.tail9531b.ts.net:8443/identity/agent.json exec --secret-env PLANE_OREGON_API_TOKEN=PLANE_OREGON_API_TOKEN --secret-env PLANE_WINDOW10_API_TOKEN=PLANE_WINDOW10_API_TOKEN --timeout 900 -- $HOME/Documents/wjj/project/plane-agentd/cli/agentd tick --once >> $HOME/Documents/wjj/project/plane-agentd/state/cron.log 2>&1

常驻替代:... exec ... -- cli/agentd tick --loop --interval 120(vault 会话超时要够长,cron 更稳)。 cron 的 PATH 很短:本机执行器的二进制用终端 bins 写绝对路径(如 claude: /home/ubuntu/.local/bin/claude)。

执行器二进制的解析(bins 或 PATH)

命令模板的首词(codex、claude…)若在该终端的 bins 里,替换为那里的绝对路径;否则原样交给终端的 shell 按 PATH 查找。没有任何其他探测或回退:

  • oregon(local):runner 是 bash run.sh,环境继承 agentd 进程(cron 下 PATH 只有 /usr/bin:/bin),所以 claude 必须写进 bins。示例配置的 oregon 列了 codex 执行器但没有 bins.codex,即假定 codex 在 PATH 上——目前 oregon 没装 codex(which codex 为空),带 exec:codex 的 oregon 工作项会以 exit 127(command not found,类型=crash,非临时性)转 Waiting。要用就装 codex 并加 bins: {codex: <绝对路径>},否则从 oregon 的 executors 去掉 codex。
  • win10(warpgate-ssh):runner 是计划任务里的 powershell.exe -File run.ps1,以创建任务的用户(Administrator,交互登录)运行,PATH 取该用户的环境。示例配置用 bins.codex 写死 codex.exe 绝对路径;去掉它就等于假定 Administrator 的 PATH 里有 codex。
  • check-config 不检查二进制是否存在;首次接入一个终端用 agentd smoke <PROJECT> <terminal> 验证。

人工操作(同样在 exec --secret-env 下):

cli/agentd new GWENT "T-010 标题" --file brief.md --assign window10 --labels model:astra,needs-game --module M1 --state Todo
cli/agentd show GWENT GW-12 3        # 状态/指派/标签 + 最近 3 条评论
cli/agentd comment GWENT 12 reply.md # 或 - 读 stdin
cli/agentd state GWENT 12 Todo       # Plane 状态名或配置键(todo/review…)
cli/agentd assign GWENT 12 window10
cli/agentd smoke GWENT oregon        # 建一个要求回复 "[review] ok" 的工作项,tick 到结束,PASS 则移到 Done

CLI 以 --as <terminal> / agentd.cli_terminal / 第一个有 token 的终端的身份操作。

文件

路径 内容
state/agentd-state.json 每项目每工作项:轮次、线程 ID 与所在终端/执行器、线程轮数、各轮标签、已见评论、重试计数/下次重试、在途运行(handle、deadline)
state/agentd.log 每次 tick 的动作与错误
state/heartbeat.json 最近一次 tick 的时间、在途运行、错误;超过 10 分钟不更新 = agentd 没在跑
state/agentd.lock tick 互斥锁
state/runs/<run_id>/ 本机终端的运行目录:prompt.md run.sh pid.txt started.txt exit.txt stderr.txt + 执行器输出
<repo>\runtime\agentd\<run_id>\(win10) 同上,run.ps1;codex 输出 events.jsonl last.md

工作项生命周期

Todo + 指派给终端用户 → agentd 选最小编号、终端有空位、串行组空闲的项 → In Progress,评论 [worker] 第 k 轮开始… → 执行器结束后回帖 [<executor>] 第 k 轮结束(exit, run, 终端, 日志) + 最后消息:

  • [review] → Review,指派 reviewer;[question]/[blocked] → Waiting,指派 answerer(默认 reviewer);[progress] → Todo,留在原终端,下一轮续线程;首行无标签 → 按 review 处理并注明。
  • 回到 Todo 的项总会被重新拾起;续线程时只发送上次之后的新评论(按评论 ID 判断,[worker] 评论永远跳过)。
  • 线程重建:换终端/执行器、续线程失败、线程轮数 ≥ max_rounds_per_thread → 新线程,首轮输入附交接摘要(各轮标签 + 上一轮最后消息),开始评论里注明原因与"附交接摘要"。临时性错误的自动重试算同一轮,不计入线程轮数(run id 照常递增)。
  • 连续 max_progress_rounds(项目配置,默认 12)轮 [progress] → 不再续跑,回帖说明并转 Waiting 指派 answerer;人工移回 Todo 后重新计数。
  • 运行中工作项被移出 In Progress(任何状态)→ 下一 tick 结束该运行(kill),回帖 [worker] 运行已取消:工作项状态被改为 <状态>,释放终端槽位与串行组,保留线程 ID(移回 Todo 时续原线程)。kill 失败则保留槽位,下一 tick 再试。
  • 未实现(TODO):Plane 的 "blocked by" 关系不参与调度——被阻塞的项只要在 Todo 且指派给终端就会被拾起。需要先后顺序时,先只把前一项放进 Todo。

常见故障

现象 原因 / 处理
no Plane token in the environment / tick 报 no Plane token 没在 agent-access.py exec --secret-env … 下运行,或键名不对;check-config 看 MISSING
skip: another tick holds state/agentd.lock 上一 tick 还在跑(win10 上传慢);正常。持续出现则查是否有卡死的 agentd 进程
[worker] 第 k 轮失败:类型=crash(临时性)…重试 n/N 网络/中继/429/5xx:按 backoff_minutes 自动重试,续原线程;超过 transient_max 转 Waiting
类型=timeout 超过 timeout_hours(或 budget:2h 标签);进程树已结束,转 Waiting。看运行目录日志决定拆分任务或加预算
类型=crash(非临时)且是续线程 自动在新线程重跑一次(附交接摘要);再失败转 Waiting
类型=env 匹配 retry.env_patterns(焦点丢失/弹窗/断网等),转 Waiting,同串行组暂停到该项离开 Waiting
win10 unreachable; skipping / busy (N codex running…) 中继不通,或 win10 上有不是 agentd 起的 codex(busy_processes);等它结束
schtasks launch … failed / upload … failed 中继或 Windows 计划任务问题;手工 win10-ps.sh "schtasks /Query /TN agentd-<run>" 查看
工作项在运行中被人改了状态 运行还没结束:下一 tick 取消(kill + [worker] 运行已取消… 评论),不改状态。已经结束(exit.txt 已写):结果照常回帖,但不再改状态/重试
Plane 回帖失败 在途记录保留,下一 tick 重新 collect 并回帖(可能重复一条评论)
想手工终止一轮 把工作项移出 In Progress(如 Waiting)即可,下一 tick agentd 自己 kill 并释放槽位。中继不通、kill 一直失败时:在终端上手工结束(本机 kill -TERM -<pid.txt>,win10 taskkill /T /F /PID <pid.txt>),停 cron 后从 state/agentd-state.json 删掉该项的 inflight
已连续 N 轮 [progress] 达到 max_progress_rounds:看最近几轮是否在原地打转;拆分任务或补充说明后移回 Todo