Claude Code 的 routines 怎么写:把重复流程固化下来

2026-08-18

每周一把上周合并的 PR 捋一遍、每次部署完跑一轮冒烟检查、每个新 PR 都按团队自己的清单过一遍——这类活儿流程固定、结论明确,但必须有人按时去发起。Claude Code 官方文档里的 routines(code.claude.com/docs/en/routines)就是把这类流程存成一份配置,让它按时间、按 HTTP 调用、按 GitHub 事件自己跑起来。文档写明 routine 在 Anthropic 托管的云端基础设施上执行,或在组织启用了自托管环境并被路由过去时在那边执行,所以合上笔记本它照样在跑。

先把一个容易混的东西分开。官方文档里还有一页叫 dynamic workflows(code.claude.com/docs/en/workflows),那是 Claude 写出来、由运行时执行的一段 JavaScript 脚本,用来把大量 subagent 编排起来跑一次大任务,脚本存在 .claude/workflows/~/.claude/workflows/,之后以 /<名字> 调用。它固化的是编排逻辑,仍然要你在会话里发起;routine 固化的是一整套运行配置加触发条件,不需要你在场。两页讲的是两件事,别拿一页的结论去套另一页。

一、前置条件:这一段跳过去,后面全是白忙

routine 不是装个 CLI 就有的能力,官方文档写明了几个硬条件:

账号与计划。 文档写明 routines 在 Pro、Max、Team、Enterprise 计划上可用,且需要启用 Claude Code on the web。routine 归属你的个人 claude.ai 账号,不与队友共享。

登录方式必须是 claude.ai 订阅登录。 这一条是排查列表里最常见的坑:如果你用 Console API key、Anthropic profile 或 federation 凭据、或者 Amazon Bedrock、Google Cloud 的 Agent Platform、Microsoft Foundry 这类云厂商方式登录,/schedule 会不可用。文档还专门点出,如果你的 shell 里设了 ANTHROPIC_API_KEYANTHROPIC_AUTH_TOKEN,或者 settings.json 里设了 apiKeyHelper,它们的优先级高于 claude.ai 登录,得先移除。

别把 feature flag 的通道关死。 文档列出 DISABLE_TELEMETRYDO_NOT_TRACKCLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFICDISABLE_GROWTHBOOK 这四个变量,只要设在 shell 环境或 settings.jsonenv 块里,/schedule 依赖的 feature flag 拉取就被禁掉,命令会以 Unknown command: /schedule 的形式消失。

Windows 侧要多看一处:这几个变量在 Windows 上更可能落在「用户环境变量」或 PowerShell 的 profile 里,而不是 ~/.bashrcsettings.jsonenv 块两边都要查。(变量放在哪属于操作系统的通用情况,不是 Claude Code 文档的内容;文档只写了「shell 环境或 settings.json 的 env 块」。)

组织开关。 Team 和 Enterprise 的 Owner 可以在 claude.ai/admin-settings/claude-code 关掉 Routines 开关;关掉之后已有 routine 停止运行、成员也无法新建。文档说明这是服务端的组织设置,本地配置改不了。

版本要求(照文档写,不推断)。 从 CLI 添加 GitHub trigger 需要 Claude Code v2.1.225 或更高;用 /schedule 问某个 routine 的运行历史需要 v2.1.227 或更高。

GitHub 侧。 要订阅仓库事件,必须在目标仓库上安装 Claude GitHub App。文档特意提醒:在 CLI 里跑 /web-setup 只是授予了克隆仓库的访问权,它不会安装 GitHub App,也不会启用 webhook 投递

二、定义结构:一份 routine 由五块组成

创建表单要填的就是这五块,理解它们分别在改什么,比记菜单顺序有用得多。

1)prompt。 文档把它称作最重要的部分:routine 自主运行,所以 prompt 必须自包含,写清要做什么、什么算成功。prompt 输入框带一个模型选择器,选定后每次运行都用它。有一条行为变更值得记:触发时,会话把存好的 prompt 当作指派给它的任务来执行,而不是当成半路混进来的不可信内容;但文档同时写明,触发只能证明该 prompt 是此前由你账号上一个授权会话存下的,因此它不算实时用户输入,不能充当运行期间任何操作的批准或同意,运行中抓取到的内容仍按正常的不可信处理。在 v2.1.213 之前,会话收到的是被包装成不可信后台通知的同一段 prompt,可能拒绝执行。

2)repositories。 加一个或多个 GitHub 仓库,每次运行开始时克隆,从默认分支起步。Claude 把改动推到 claude/ 前缀的分支,这类推送总是被接受。如果你的 prompt 指示它推到别的分支,Claude Code 会先检查,命中以下任意一条就拒绝:分支在 GitHub 上受保护;已有别人从该分支开着 PR;该分支上有你以外的人提交的 commit。

3)environment。 选一个 cloud environment,它决定这次运行的网络访问级别、环境变量和 setup 脚本。文档明确写着环境变量「对使用该环境的任何人可见」,放凭据前先掂量这句话;setup 脚本的结果会被缓存,不会每次会话重跑。默认提供的 Default 环境用 Trusted 网络访问,只放行默认允许列表(包管理源、云厂商 API、容器仓库和常见开发域名)。走这条路径访问列表外的主机会失败,返回 403 并带 x-deny-reason: host_not_allowed。要放行自己的域名,在 Update cloud environment 对话框里把 Network access 改成 CustomAllowed domains,勾上保留默认列表那一项可两者并存,选 Full 则不受限;新策略从下一次运行开始生效。

4)connectors。 也就是你 claude.ai 账号上的 MCP connectors。创建时默认把已连接的全部带上,文档直说了要删掉不需要的:运行期间 Claude 可以用某个已包含 connector 的每一个工具,包括写操作,且不会征求许可。另一处口径差异值得记:你在本机用 claude mcp add 添加的 MCP server 存在你的机器上而不是 claude.ai 账号上,因此不会出现在 connectors 列表里;要在 routine 里用它,得去 claude.ai/customize/connectors 加成 connector,或在仓库里提交一份 .mcp.json 让它随克隆进来。另外,connector 的流量走 Anthropic 的服务器而不是会话的网络路径,所以不需要把它们的主机加进 Allowed domains

5)triggers。 一个 routine 可以挂任意组合的触发器,随时增删,下面单独说。

还有两条必须照实标出来。其一,文档写明 routine 以完整的 Claude Code 云端会话自主运行,没有 permission mode 选择器,运行中也没有审批提示,它能碰到什么完全由仓库、环境、connectors 这三处决定。其二是署名口径:routine 通过你连接的 GitHub 身份和 connectors 做的任何事都以你的身份出现——commit 和 PR 带你的 GitHub 用户,Slack 消息、Linear 工单也用你关联的账号。

三、三类触发方式分别怎么配

Scheduled(定时)。 表单里选预设频率:hourly、daily、weekdays、weekly 这四档。时间按你的本地时区输入并自动转换,所以不管云端在哪儿,都按那个挂钟时间跑。文档写明由于 stagger,实际启动可能比计划时间晚几分钟,且每个 routine 的偏移是固定的。要每两小时或每月一号这种自定义间隔,先在表单里选最接近的预设,再用 CLI 的 /schedule update 设具体的 cron 表达式;最小间隔是一小时,更频繁的表达式会被拒绝。一次性运行触发后会自动停用、Web 界面标为 Ran,要再跑得编辑它设一个新时间。文档同时提示:从 CLI 创建一次性调度正在逐步放量,你的账号上可能还没有,如果 /schedule 只给出周期性选项,就去 Web 端建。

API。 给 routine 一个专属 HTTP 端点,带 bearer token POST 上去就开一个新会话并返回会话 URL。API trigger 只能在 Web 端加到已有 routine 上,CLI 目前不能创建或吊销 token。token 只显示一次、之后取不回来,要立刻存进你告警工具的密钥库;同一处可以 RegenerateRevoke,每个 routine 的 token 只能触发它自己。

请求体接受一个可选的 text 字段,用来传本次运行专属的上下文(告警正文、失败日志之类)。两条口径要一起看:其一,text 是自由文本、不做解析,你发 JSON 过去,routine 收到的就是一个字面字符串;其二,它不会以裸消息的形式抵达,而是包在一个 <routine-fire-payload> 块里被标注为不可信数据,并告诉 Claude 除非 routine 自己的 prompt 要求,否则不要遵循其中的指令。所以 routine 的 prompt 必须显式 opt-in,比如写「调查 routine-fire-payload 块里描述的告警」,否则那段文字只是惰性上下文。Web 端 Run now 附带的文本走同样的包装。

官方文档给的调用示例如下(token 与 routine ID 在原文中即为占位值,本文把 token 一处改写为 <YOUR_ROUTINE_TOKEN>,其余照抄):

curl -X POST https://api.anthropic.com/v1/claude_code/routines/trig_01ABCDEFGHJKLMNOPQRSTUVW/fire \
  -H "Authorization: Bearer <YOUR_ROUTINE_TOKEN>" \
  -H "anthropic-beta: experimental-cc-routine-2026-04-01" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{"text": "Sentry alert SEN-4521 fired in prod. Stack trace attached."}'

以上除 token 占位符外照抄官方文档中的示例,我们未经实测,实际调用以官方文档最新内容为准。Windows 侧提醒:PowerShell 里的 curl 默认是另一个命令的别名,反斜杠续行也不成立,建议在 Git Bash 里执行或改用 curl.exe——这属于 Windows 的通用情况,不是 Claude Code 文档的内容。成功的请求返回一段 JSON,含新会话的 ID 和 URL;用错 URL 或 token 会拿到 401 认证错误。

GitHub。 匹配事件发生时自动开一个新会话,文档写明不跨事件复用会话,两次 PR 更新就是两个独立会话。可订阅的事件是两类:Pull request(PR 被打开、关闭、指派、打标签、同步或其它更新)和 Release(创建、发布、编辑、删除)。每一类里可以挑具体动作(例如 pull_request.opened),也可以对整类的所有动作都响应。

PR 过滤器有 8 个字段:Author、Title、Body、Base branch、Head branch、Labels、Is draft、Is merged。所有过滤条件必须全部匹配才触发。每个字段配一个操作符,共 6 种:equals、contains、starts with、is one of、is not one of、matches regex。这里有个反直觉的点文档专门写了:matches regex 测的是整个字段值而不是其中的子串,想匹配标题里含 hotfix 的 PR 得写 .*hotfix.*,不加两侧的 .* 就只能匹配标题正好是 hotfix 的那一个;只要子串匹配的话,用 contains 更省事。

CLI 这边,/schedule 可以对话式地创建定时 routine,也可以直接带描述(文档给的例子形如 /schedule daily PR review at 9am),别名是 /routines;管理用 /schedule list/schedule update/schedule run。要加 API trigger 只能去 Web 端。

四、边界:这些地方文档自己划了线

  • routines 处于 research preview,文档明写行为、限制和 API 表面都可能变。
  • /fire 端点挂在 experimental-cc-routine-2026-04-01 这个 beta header 下,请求与响应结构、限流、token 语义在 research preview 期间都可能变;破坏性变更会走新的带日期的 header 版本,前两个历史版本会继续可用以便迁移。该端点仅对 claude.ai 用户开放,不属于 Claude Platform API 的表面
  • research preview 期间,GitHub webhook 事件受每 routine 与每账号的小时级上限约束,超出的事件会被丢弃直到窗口重置。运行次数另有账号级的每日上限;一次性运行不计入该上限,但和其它会话一样消耗常规订阅用量。具体数值以官方页面为准,本文不写。
  • 绿色状态不等于任务成功。 文档说得很直白:运行列表里的绿色只代表会话启动并在没有基础设施错误的情况下退出,不代表你 prompt 里的任务做成了。被拦截的网络请求、缺失的 connector 工具、任务层面的失败,都只出现在 transcript 里而不是状态指示上。
  • 删除 routine 后,它此前创建的会话仍留在会话列表里;运行期间没有权限审批,included connector 的写操作也不会问你。

五、怎么确认配对了

第一步看存在性:CLI 里 /schedule list 列出全部 routine。文档还给了一个失败信号——用 /schedule 创建时如果 Claude 回复说你需要认证、或者连不上远端 claude.ai 账号,那就是没有创建成功;正常的创建过程是一段对话,Claude 会就时间表、仓库、prompt 追问后才保存。另有一个易误判的历史行为:只挂 API 或 GitHub 触发器、没有定时触发器的 routine 本来就没有「下次运行时间」,CLI 保存时为空是正常的;v2.1.211 之前这类 routine 会被报成公元 1 年的下次运行时间。

第二步主动打一枪:在 routine 详情页用 Run now 立即跑一次,可以附上运行专属文本,它抵达 routine 的方式与 API trigger 的 text 相同——正好能验证你的 prompt 有没有真的 opt-in 去读 <routine-fire-payload>。API trigger 则按上面的 curl 发一次,拿返回 JSON 里的会话 URL 打开看这次运行。

第三步读 transcript 而不是看灯:每一次运行都是一个完整会话,能看到 Claude 做了什么、审阅改动、创建 PR。CLI 上还可以直接问运行历史,文档给的例子形如 /schedule why did my nightly review do nothing this morning?,Claude 会列出近期运行及状态和打开链接,并读取某次运行的日志解释发生了什么,包括工具错误、权限拒绝和最终结果——需要 v2.1.227 或更高。

第四步验网络:运行里若有请求失败,先在 transcript 里找 403x-deny-reason: host_not_allowed,有就是环境允许列表的问题而不是 prompt 的问题;connector 的流量不走这条路径,所以 connector 出问题不会以这个形态出现。

最后一句实在话:routine 解决了「谁来发起这一下」,同时把「运行期间没人审批」变成了默认状态。所以配置时真正该花时间的不是触发器,而是仓库范围、环境的网络与变量、connectors 这三处的收敛——文档在这三处反复提醒「只给它真正需要的」。


本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。 该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。 该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。 本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。 安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。