跳到内容
MagicFrog
目录

触发器

定时 run 与事件 watcher——两者都绑定显式目标,并在同一个总览中可见。

触发器让 MagicFrog 在没有人类回合的情况下行动:cron 触发器按计划触发一个动作,watcher 则循环运行一小段脚本,判断是否发生了需要你注意的事。两类共享同一个总览,也都拒绝猜测自己在哪里运行。

定时触发器(cron)

一条定时触发器携带自己的身份、一份计划和一个动作:

字段 含义
triggerId 触发器的稳定身份
kind cron
schedule 非空的计划表达式
intervalMinutes 整数;下限 30 分钟,低于即被拒绝
targetComputerId 动作在其上运行的计算机——cron 必填
ownerTaskId 可选:触发器所属的任务
action 要运行什么(type 加可选参数)

两条契约让计划值得信赖:

  • **失败即关闭(fail-closed)的目标定向。**没有 targetComputerId 的 cron 触发器在注册时即被拒绝,并在每次执行时复查。它绝不对本地机器运行,也绝不被静默改投他处。
  • **不做补跑重放。**服务宕机或 run 超时错过一次触发时,触发器在下一个周期照常触发——错过的那次被跳过,绝不重放。

每次执行的结果都会记录:ok、error 或 rejected。

Watcher

watcher 是一段由你或 agent 编写的 bun 脚本,针对一个目标循环运行。

字段 含义
watcherId watcher 的稳定身份
scriptPath bun 脚本路径
targetKind task 或 agent
targetId 被观察的任务或 agent
interval 循环节拍,单位秒(30 分钟下限是 cron 的契约,不是 watch 循环的契约)
ownerAgentId 可选:拥有该观察的 agent
status stopped、running 或 failed

脚本契约

每轮迭代通过 stdin 收到自己的目标上下文,JSON 形态:

{
  "watcherId": "wat_...",
  "targetKind": "agent",
  "targetId": "...",
  "now": 1792000000000,
  "artifactsDir": ".../watchers/wat_.../",
  "events": [],
  "eventCursor": 0
}

脚本在 stdout 上以一行 JSON finding 作答:

{ "matched": true, "summary": "Build failed twice in a row", "data": { "runId": "run_..." } }

什么算 matched 完全由脚本决定。脚本以非零码退出算一次失败,watcher 继续运行;failed 状态指脚本本身无法启动,例如文件不可读。

每个 watcher 有自己的产物目录,它既是子进程的工作目录,也以 MAGICFROG_WATCHER_ARTIFACT_DIR 暴露,所以脚本产出的文件绝不会在 watcher 之间相撞,也绝不会漏进工作区。

目标

  • agent——循环读取云端 agent 的事件:run.started、tool.called、tool.result、form.pending、form.answered 与 takeover.requested。断连之后从上次的进度继续,而不是从头开始。
  • task——循环读取任务状态快照。读不到任务状态时启动会显式失败,绝不出示伪造状态。

watcher 在你的机器上运行。它可以监视远端云端 agent 的事件,但 watcher 本身不迁移。

一个总览

GET /v1/triggers/overview 一次读取账号范围内每个任务的 cron 触发器与 watcher,各自带状态与下次到期时间。控制台与本机命令看到的是同一份状态。