# Automation

> Proma 内嵌自动任务与定时任务 Skill，属于 Proma 自带能力而不是用户临时安装的外部 Skill。触发要非常宽泛、非常冗余：只要用户的话里出现任何“未来还要做”“以后继续看”“重复做”“再跑一次也有价值”“定期/周期/每天/每周/每月/每隔一段时间”“持续关注/持续观察/长期跟进/长期监控”“自动检查/自动汇总/自动生成/自动复盘/自动维护”“无人值守”“有变化告诉我”“异常时提醒我”“结果不好就调整”“查看运行记录”“优化已有任务”“暂停/恢复/删除/立即运行任务”等迹象，就应该触发此 Skill，先判断是否适合 Proma 定时任务。也要覆盖一次性与有限次的延时执行信号：“X 小时/天后跑一次”“过一会儿/晚点/稍后自动做”“到某个具体时间点执行一次”“跑几次/连续观察 N 次就停”——这类未来无人值守的延时任务现在同样适合 Proma 定时任务（用 once 或 maxRuns），不要再一概当成不支持。模糊场景也可以触发：例行报告、日报周报、项目状态、GitHub/邮件/飞书/文件/发布/CI/价格/竞品/数据源的反复检查，重复研究流程，定期整理知识，自动化工作流维护。高频触发不代表必须创建任务；纯提醒/闹钟/倒计时、需要用户实时参与判断、或结果没有任何留存价值的事，要明确说明不推荐创建 Proma 定时任务，并给出替代做法。

- Skill: `proma-ai/automation` (Agent Skill)
- Install (CLI): `npx skillmds@latest add proma-ai/automation`
- Raw SKILL.md: https://api.skillmd.com/api/skills/proma-ai/automation/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: proma-ai (https://skillmd.com/u/proma-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/proma-ai/automation

---


# Proma Automation

你负责帮助用户判断、创建和维护 Proma 的定时任务（Automation）。这是 Proma 内嵌 Skill，会随 Proma 一起分发到默认 Skills 和 Proma 工作区 Skills 中，不依赖用户额外安装。定时任务适合**无人值守、有稳定价值**的工作：既包括长期反复的周期任务，也包括「未来某个时间点 / 跑有限几次」的延时任务（用 `once` 或 `maxRuns`）。真正不适合的是纯提醒闹钟、需要用户实时参与判断、或结果没有任何留存价值的事。

Proma 已提供内置 `automation` MCP 工具。你必须通过这些工具操作定时任务，不要使用 `TaskCreate`、`CronCreate`、Bash `cron`、系统日历或隐藏注释协议来创建 Proma 定时任务。

## 触发策略

这个 Skill 的触发策略要宽：**宁可频繁触发，再判断“不建议创建”，也不要错过潜在的自动化机会**。

只要用户的需求里出现下面任意信号，就应该先使用本 Skill 做判断：

- 时间信号：定期、每天、每周、每月、每隔一段时间、长期、以后、下次、持续。
- 重复信号：经常、反复、例行、固定流程、每次都要、还会再做。
- 观察信号：关注、跟进、监控、检查、发现变化、异常提醒、状态更新。
- 产出信号：日报、周报、报告、汇总、复盘、提醒我看结果、整理进展。
- 自动化信号：自动跑、无人值守、后台执行、到点执行、帮我维护。
- 维护信号：查看任务、运行记录、效果不好、修改频率、暂停、恢复、删除、立即运行。

触发本 Skill 只是进入判断流程，不代表一定创建 Proma 定时任务。你要主动区分“适合长期自动化”和“只适合当前执行一次”。

## 先判断是否值得创建

优先推荐定时任务的场景：

- 长期反复：每天、每周、每隔一段时间都要做，且会持续存在。
- 未来延时执行：现在不用做、但**将来某个时间点**要无人值守自动跑一次（用 `once`），如"3 小时后检查构建结果""下周一早上生成报告"。间隔比 10-30 分钟长正是 `once` 的典型场景。
- 有限次执行：要跑固定几次就停（用 `maxRuns`），如"每小时查一次部署，最多查 5 次"。
- 无人值守：Agent 可以在没有用户即时参与的情况下完成主要工作。
- 稳定目标：每次执行的输入来源、判断标准和交付物相对稳定。
- 有复利价值：定期报告、持续监控、自动汇总、状态追踪、例行复盘。
- 可验证：每次运行后能看出成功、失败、遗漏或质量问题。

不推荐创建定时任务的场景：

- 纯提醒 / 闹钟 / 倒计时：只是到点弹个提示，没有 Agent 要执行的实际工作（这种让用户用系统提醒 / 日历）。
- 需要用户实时判断、批准或在执行中持续提供上下文。
- 现在就该做、且做完即终结的事——直接现在执行，不必排进调度。
- 执行目标还没稳定，频率、触发时间和交付物都不清楚。
- 结果没有任何留存价值，只是为了"别忘了"。

注意区分：「未来要无人值守跑一次」**适合**用 `once`，不要再当成"不支持一次性任务"而拒绝；但「纯粹提醒我去做某事」不适合，因为没有 Agent 可执行的实质工作。

当不推荐时，直接说明原因，并给出更合适的替代方式：现在执行一次、把流程沉淀成 Skill、写入项目计划、让用户去日历/提醒工具设置提醒等。

## 创建前要想清楚

创建定时任务前，至少明确这些信息：

- `name`：短名称，描述任务目标。循环任务用持续性的名字（如"每日 PR 汇总"），`once` 任务可以直接写成具体动作（如"周五检查发布构建"）。
- `scheduleType` + 对应字段：循环任务频率要克制，优先用一条任务表达完整的时间规则；一次性延时任务用 `once`。选择策略见下表。
- `prompt`：每次自动执行时发给 Agent 的完整指令。
- **时间窗口型重复任务**：当用户表达“每天/工作日/周末/指定星期几，在某个时间段内每隔 X 分钟/小时执行”时，必须创建**一条** `scheduleType=interval` 任务，使用 `activeWindowStart`、`activeWindowEnd` 和 `activeWeekdays` 表达约束；不得拆成多个 daily/once 任务。
  - `activeWindowStart` / `activeWindowEnd` 使用 `HH:MM`，开始包含、结束不包含；例如“10:00–22:00 每 20 分钟”触发 10:00、10:20 … 21:40。
  - `activeWeekdays` 使用数字数组：0=周日、1=周一 … 6=周六；每天可以省略或传空数组，工作日传 `[1,2,3,4,5]`，周末传 `[0,6]`。
  - 这三个字段是同一条 interval 任务的调度维度，不需要为每个时间点、每一天创建独立任务。
- 权限模式：定时任务默认使用 `bypassPermissions` 以支持无人值守；涉及高风险操作时不要依赖权限模式解决，应缩小 prompt 的授权范围，必要时改为先汇报、等待用户确认的流程。
- 会话模式（`sessionMode`）：默认 `daily`，同一自然日内的触发复用同一个子会话、跨日自动新建；`reuse` 始终复用同一个子会话保留长期上下文。选择策略见下文。

### 在其他工作区创建任务

- `create_automation.workspaceId` 是可选的**目标工作区 ID**；不传则仍使用当前会话工作区。用户说“在 B 工作区设置”时，先调用 `list_workspaces`，按名称或 slug 找到目标，再传返回的精确 ID；不要猜 UUID、用路径代替 ID 或为了查 ID 读取其他工作区的配置文件。
- `list_workspaces` 只返回 id、name、slug、isCurrent 和 projectRootStatus。`managed` 表示 Proma 托管项目；`available` 表示本地项目根可用。`missing`、`not_directory`、`unavailable` 时先告知用户目标根不可用，不要声称任务能正常运行。名称有歧义时先请用户确认，不静默选择同名项目。
- 跨工作区创建前仍调用 `list_automations`，按返回的 workspaceId 检查**目标工作区**是否已有同目标任务；该工具仍返回全局列表。
- A 会话创建到 B 后，任务归属和自动运行会话都在 B；运行时加载 B 的项目文件、工作区规则、Skills、MCP 和附加目录。渠道与模型继续继承 A 的创建会话，sourceSessionId 保留来源追踪，**不会复制 A 的会话历史或附加目录**。cwd 按 B 的自动会话规则解析，不保证等于项目根目录；prompt 引用路径时使用 B 的路径或运行时注入的项目根，不能沿用 A 的绝对路径。
- 创建结果中的 workspaceId、workspaceName、workspaceSlug 用于核对归属，向用户明确报告目标工作区。目标不存在或被删除时重新查询，不回退当前工作区。
- 此能力仅用于**创建时选择目标**，`update_automation` 不支持迁移工作区；不要通过修改配置文件迁移。定时任务自动执行中仍禁止递归创建新任务。

### 调度类型怎么选

| scheduleType | 适用场景 | 必填字段 |
|---|---|---|
| `interval` | 高频监控（CI 状态、价格、库存、聊天提醒），分钟级响应。间隔可以远大于 10-30 分钟，如 1440=每天、10080=每周 | `intervalMinutes` |
| `daily` | 每日早报、日报、晨间汇总 | `timeOfDay` |
| `weekly` | 周报、周度复盘、每周例会前准备 | `dayOfWeek` + `timeOfDay` |
| `monthly` | 月度报告、月初对账、月底结算、月度复盘 | `dayOfMonth` + `timeOfDay` |
| `once` | 在某个具体时间点只跑一次（X 小时/天后跑一次、某个日期时刻执行一次），跑完自动完成停用 | `scheduledAt` |

`timeOfDay` 用 24 小时制 `HH:MM`（如 `09:30`、`22:00`）。`dayOfWeek` 0=周日、1=周一 … 6=周六。`dayOfMonth` 1-31。`scheduledAt` 是绝对触发时间的**毫秒时间戳**（如 `Date.now() + 3*3600*1000` 表示 3 小时后）。

### once 一次性任务 vs maxRuns 运行次数上限

这两个特性都让任务「跑有限次就停」，但语义不同，别混用：

- **`once`**：表达「在某个**绝对时间点**只跑一次」。适合「30 分钟后提醒我看构建结果」「6 月 30 号下午 3 点生成季度报告」这类一次性、间隔可能很长的任务。跑完一次后任务自动停用（在列表里显示为「已完成」）。
- **`maxRuns`**：正交于所有调度类型的**运行次数上限**，按**实际执行次数**计（成功 + 失败都算，跳过不算）。适合「每隔 1 小时检查一次部署状态，最多查 5 次就停」「每天跑，连跑 3 天观察趋势」。达到上限后任务自动停用。`once` 模式语义上等价于 `maxRuns=1`，所以 once 任务不需要再设 maxRuns。

判断口诀：
- 「**X 时间后/某个时刻**跑一次」→ 用 `once` + `scheduledAt`。
- 「**每隔一段时间**跑，但**只跑 N 次**就停」→ 用 `interval`（或 daily/weekly）+ `maxRuns`。
- 「长期反复、没有终点」→ 不设 maxRuns，用普通循环调度。

自动完成（once 跑完 / 跑满 maxRuns）和用户手动暂停、连续失败暂停是不同状态：列表里单独归到「已完成」组。用户重新启用一个已完成的任务，会**重置运行次数计数**，相当于再跑一轮配额。

### monthly 的短月回退行为（重要）

`dayOfMonth` 选 29/30/31 时，2 月（28/29 天）和 4/6/9/11 月（30 天）会**自动落在当月最后一天**执行，而不是跳过。这意味着：

- 选 31 号 → 一年实际只触发 7 次（1/3/5/7/8/10/12 月），其他月份落在月末。
- 选 29 号 → 平年 2 月落在 2/28，闰年落在 2/29。

用户说"每月底"时，建议**主动用 28 号**而不是 31 号，否则用户可能误以为每月都跑、实际并非如此；或者明确告知这个回退行为，让用户自己决定。

### 组合调度规则（必须遵守）

Automation 的调度规则由多个独立维度组合而成，不要把每个维度展开成多个任务。创建前先把用户描述拆成：**执行动作、间隔/固定时刻、每日时间窗口、周内运行日、结束条件**，再映射到同一条 Automation。

| 用户表达 | 调度配置 |
|---|---|
| 每隔 X 分钟/小时 | `scheduleType: 'interval'` + `intervalMinutes: X` |
| 每天某个时间段内 | `activeWindowStart` + `activeWindowEnd` |
| 工作日/周一至周五 | `activeWeekdays: [1,2,3,4,5]` |
| 周末 | `activeWeekdays: [0,6]` |
| 周一、三、五 | `activeWeekdays: [1,3,5]` |
| 每天/不限制星期 | `activeWeekdays` 省略或传 `[]` |
| 只运行 N 次 | `maxRuns: N` |
| 某个绝对时刻只运行一次 | `scheduleType: 'once'` + `scheduledAt` |

#### 单任务优先原则

- “工作日 10:00–22:00 每 20 分钟检查一次”必须是**一条**任务：

      scheduleType: interval
      intervalMinutes: 20
      activeWindowStart: 10:00
      activeWindowEnd: 22:00
      activeWeekdays: [1, 2, 3, 4, 5]

- “每天 10:00–22:00 每 20 分钟”同样只创建一条任务，只省略 `activeWeekdays` 或传空数组。
- 禁止按时间点创建 36/37 条 daily 任务，禁止按星期创建 5 条任务，禁止把一个时间窗口拆成多条 `once` 任务。
- 如果 `list_automations` 已发现同一目标已有多条由旧规则拆出的相似任务，优先提出或执行合并迁移：保留一条共同 prompt，转换为上述组合字段；删除其余任务前遵守删除确认规则，不要静默删除。
- `activeWindowStart` 包含，`activeWindowEnd` 不包含。窗口必须是同一自然日且开始早于结束；暂不支持跨午夜窗口。窗口内以窗口开始为间隔锚点，例如 10:00–22:00、20 分钟间隔的触发点为 10:00、10:20 … 21:40。
- `activeWeekdays` 只对 `scheduleType: 'interval'` 生效；空数组/省略表示每天。`weekly` 只用于“每周某一天的一个固定时刻”，不用于表达工作日内的高频运行。

#### 选择流程

1. 先判断用户是否描述了“每隔 X”或“时间段内反复执行”。有则使用 `interval`。
2. 再提取是否有每日时间段。有则同时设置 `activeWindowStart`、`activeWindowEnd`。
3. 再提取是否有周内范围。有则一次性设置 `activeWeekdays`，不要创建多条任务。
4. 再设置 `maxRuns` 或长期运行；没有结束条件时不设置 `maxRuns`。
5. 创建前调用 `list_automations` 检查近似任务，避免重复创建；若用户明确要把拆分任务收敛为一条，先列出将保留/合并/待删除的任务和影响，再执行需要确认的删除。

#### 示例

用户：“每天上午 9 点到下午 6 点，每隔 30 分钟检查一次 GitHub Issue。”

      scheduleType: interval
      intervalMinutes: 30
      activeWindowStart: 09:00
      activeWindowEnd: 18:00
      activeWeekdays: []

用户：“工作日 10 点到 22 点，每隔 20 分钟巡检小红书官方群。”

      scheduleType: interval
      intervalMinutes: 20
      activeWindowStart: 10:00
      activeWindowEnd: 22:00
      activeWeekdays: [1, 2, 3, 4, 5]

用户：“每周一上午 10 点生成周报。”

      scheduleType: weekly
      dayOfWeek: 1
      timeOfDay: 10:00

这里没有“时间段内反复执行”，所以使用 `weekly`，而不是 `interval`。


- `daily`（默认）：同一自然日内的所有触发写入同一个子会话，跨日时自动新建。**绝大多数定时任务用这个**——既能让一天内的多次运行共享上下文（少占左侧栏 tab），又能每天自动归零、避免 token 长期累积。低频任务（间隔 ≥ 24 小时）的实际行为等价于"每次新建"，无需用户单独配置。
- `reuse`：始终复用同一个子会话，保留长期对话历史。适合**真的需要跨日记忆、且明知会有 token 成本**的任务——持续追踪同一个长期 issue、迭代优化同一个文档。

`reuse` 的代价：上下文会随运行次数无限增长，长任务可能因为 token 累积导致成本上升或触发自动压缩。如果任务每次产出独立（如"看一下今天有什么新 PR"），就用默认的 `daily`，别选 `reuse`。

如果用户只说“帮我定期做 X”，但频率或结果不清楚，用 `AskUserQuestion` 最多问一次，把缺失项收敛到可执行配置。不要让用户填写表单式长信息。

## Prompt 写法

定时任务的 `prompt` 要像“未来每次都能独立执行的任务说明”，不要依赖当前对话隐含上下文。

高质量 prompt 应包含：

- 目标：这次自动执行要完成什么。
- 范围：查哪些仓库、文件、系统、群聊、邮件、文档或数据源。
- 判断标准：什么算异常、重要、需要汇报。
- 输出格式：最终要给用户什么，例如摘要、列表、报告、行动建议。
- 失败处理：无法访问、信息不足、工具失败时如何记录和降级。
- 跨运行记忆（强烈推荐）：在项目级 Context（以系统提示给出的绝对路径为准）维护 `automation/<task-slug>/notes.md`，让每次运行都能在前次发现上累积，而不是从零开始。**这一段必须写进 prompt 本身**，运行时 Agent 才会执行：
  - 触发时先 `Read` 该文件（首次运行不存在则跳过），延续前几次的观察、判断和待办。
  - 运行结束时 `Edit` 同一文件：在顶部追加 `## YYYY-MM-DD` 条目记录本次新发现；同时**主动清理已经解决、过时或不再适用的旧条目**——文件是滚动维护的工作记忆，不是无限追加的日志。本次执行中只要接触到相关信息（检查某仓库、看 CI 状态、读某个文档），就顺手判断旧条目是否还成立，能删就删，避免 notes.md 越积越胖变成新的上下文负担。
- 自迭代要求：如果连续失败、结果价值低或频率不合适，先 `Read` 笔记和 `get_automation` 的运行记录，再用 `update_automation` 修改当前任务（prompt、频率、`sessionMode`），必要时暂停。

`<task-slug>` 在创建任务时由你直接敲定并写进 prompt：把任务名转成 kebab-case（小写、空格和标点转 `-`、只保留字母数字），例如任务名"每月 GitHub PR 汇总" → slug `monthly-github-pr-summary`。一旦定下就不要再改，否则笔记路径会断。

不要把“请创建定时任务”写进 prompt。prompt 是每次触发时要执行的工作，不是创建指令。

### Prompt 模板示例

一个 monthly 月度报告任务的 prompt 范本（创建任务时按这个结构写，跨运行记忆段落直接照搬）：

    目标：汇总本月 proma-ai/Proma 仓库合入的 PR，按类别归类并标注影响。
    范围：读取 proma-ai/Proma 的 closed PR 列表，筛选本月合入的。
    判断标准：每个 PR 是否引入破坏性变更、是否影响用户配置、是否需要更新文档。
    输出格式：Markdown 报告，分「重大变更」「新功能」「修复」「文档」四组。

    跨运行记忆：
    - 开始前 Read 系统提示给出的项目级 Context 中的 `automation/monthly-pr-summary/notes.md`（首次不存在则跳过），延续前几次的判断和待办
    - 结束后 Edit 同一文件，在顶部追加 ## YYYY-MM-DD 条目；本次执行中顺手清理已解决/过时的旧条目，notes.md 保持精简

    自迭代：连续 2 次失败或输出价值低，用 get_automation 读取当前任务，调整 prompt 或频率。

不适合用跨运行记忆的任务：每次产出完全独立、不需要累积上下文（如"看一下今天有什么新 PR"）。这类任务的 prompt 里不需要写跨运行记忆段落。

## 工具使用

根据场景调用 `automation` MCP 工具：

- `list_automations`：查看已有任务，避免重复创建，也用于了解启用/暂停状态。
- `get_automation`：查看单个任务详情和运行记录；自动任务执行中可省略 `id` 读取当前任务。
- `create_automation`：创建新的 Proma 定时任务，只用于确认值得长期反复执行的场景。
- `update_automation`：修改任意字段——`name`、`prompt`、`scheduleType`/`intervalMinutes`/`activeWindowStart`/`activeWindowEnd`/`activeWeekdays`/`timeOfDay`/`dayOfWeek`/`dayOfMonth`/`scheduledAt`（频率和时间约束）、`maxRuns`（运行次数上限）、`permissionMode`（权限模式）、`sessionMode`（会话模式）、`active`（启用/暂停）。`activeWeekdays` 传空数组或 null 表示取消星期限制；`activeWindowStart` 与 `activeWindowEnd` 必须成对传入，传 null 清除窗口。切换 `scheduleType` 时，只传**目标模式**需要的字段：系统会自动清理旧模式不适用的 `timeOfDay`、`dayOfWeek`、`dayOfMonth`、`scheduledAt` 与 interval 窗口字段，禁止为了通过校验填入无关占位值。`maxRuns: null` 明确表示清除上限、长期运行，绝不能用极大的数字伪装“不限次”。调度相关字段变化时会自动重算下次运行时间；改 `maxRuns` 会重置已执行次数计数；把 `active` 从 false 改回 true 会重置运行配额（已完成的任务可借此再跑一轮）。**改 `maxRuns` 想让停用/已完成任务继续跑时，必须连带处理启用状态，见下文「调整 maxRuns 时连带判断启用状态」。** 自动任务执行中可省略 `id` 更新当前任务。
- `delete_automation`：删除任务。除非用户明确要求，否则删除前要确认。
- `run_automation_now`：用户要求立即验证，或你刚修改任务后需要试跑时使用。自动任务执行中不要触发自身重入。

创建任务前先用 `list_automations` 检查是否已有相同或近似任务。已有任务能改就改，不要重复创建。

### 调整 maxRuns 时连带判断启用状态（重要）

用户想通过调 `maxRuns` 让任务「继续跑 / 再多跑几次」时，不要只改 `maxRuns` 一个字段就交差。先用 `get_automation` / `list_automations` 看目标任务**当前是否还在运行**，再决定要不要连带改 `active`：

- **任务仍 active（运行中）**：只改 `maxRuns` 即可。配额计数会按新上限重置，下次照常触发，不要乱动 `active`。
- **任务已「已完成」/ 被自动停用（`active=false`，通常因跑满旧 `maxRuns` 或 `once` 完成）**：**只改 `maxRuns` 不够**。底层只会把 `runCount` 计数清零，但任务仍是停用状态、`nextRunAt` 也不会重算——结果是「配额刷新了却永远不触发」，完全不符合用户「让它接着跑」的意图。这种情况要在**同一次 `update_automation` 调用里同时把 `active` 设为 `true`**，任务才会真正重新启用、重算下次运行时间、再跑一轮新配额。

判断口诀：用户意图是「让这个任务接着 / 重新跑」且目标任务当前停用或已完成 → 改 `maxRuns` 的同时连带 `active: true`；用户只是「给一个运行中的任务改上限」→ 不要动 `active`。改完后在回复里说明：除了上限，还顺带把任务重新启用了，以及下次大概什么时候触发。

## 维护和自迭代

用户查看或抱怨定时任务效果不好时：

1. 用 `get_automation` 查看 prompt、频率、权限模式和最近运行记录。
2. 判断问题属于哪一类：频率不合适、prompt 太泛、范围不清、工具权限不足、外部系统不可用、任务本身不适合自动化。
3. 如果能直接修复，用 `update_automation` 修改 prompt、频率或暂停状态。
4. 如需验证，用 `run_automation_now` 试跑。
5. 向用户说明改了什么，以及下一次触发会如何不同。

当你自己就是某个定时任务自动触发的 Agent 时：

- 不要创建新的定时任务。
- 先直接执行本轮任务。
- 如果发现当前任务连续失败、输出价值低、频率太高或 prompt 不完整，可以调用 `get_automation` 读取当前任务，再用 `update_automation` 修改当前任务，必要时暂停。
- 修改自身任务后，在最终回复里说明原因和修改内容。

## 回复方式

- 创建、修改、暂停、删除后，用自然语言告诉用户具体结果。
- 创建新任务后，提醒用户：可以点击左上角的「自动任务」入口，找到刚创建的任务，设置任务执行时使用的模型（不同模型在成本和能力上有差异，建议根据任务复杂度选择合适的模型）。
- 不要暴露内部工具调用 JSON。
- 如果不推荐定时任务，要明确说“不建议创建 Proma 定时任务”，并说明更适合的处理方式。
- 对长期反复任务，主动建议用户后续可以从侧边栏的定时任务入口查看运行记录和调整配置。

