结论先行
- 定时 Agent 需要「机器不休眠 + 进程可重启 + 日志可审计」——本地 Mac 难保证,远程 Mac M4 更合适。
- launchd 是 macOS 原生编排层:
StartCalendarInterval做 cron 替代,KeepAlive做常驻,ThrottleInterval防崩溃环。 - MCP 触发 建议 Curated tools + n8n Webhook 网关,不要把全部 MCP 端口暴露公网。
- 编码型并行 Agent 见worktree 并行文;磁盘治理见Runner 磁盘/inode 规划。
- 推荐路径:日租 PoC 跑通 launchd + 首条 MCP 任务 → 周租 锁冲刺 → 指标稳定后月租常驻。
- 消息型 OpenClaw Gateway 与批处理定时 CLI Agent 职责不同,本篇不重复 18789 部署骨架。

1. 2026 为何把定时 Agent 放到远程 Mac
2026 年 Cursor Automations、n8n MCP 编排与 Codex CLI remote-control 等能力,让「定时跑一轮 Agent」从玩具 demo 变成可计费 workload。但执行面仍在 macOS:launchd 只能调度本机进程,Seatbelt 与 Keychain 会阻断未声明的工具访问,本地 Mac 还会因休眠、Wi‑Fi 切换、系统更新重启而丢任务。
把 定时 Agent 放到 远程 Mac M4 托管节点,本质是买三样东西:① 7×24 在线与可控重启;② 与 LLM/MCP API 更低的 RTT(亚太或美东可选);③ 按日租/周租/月租弹性,PoC 失败可释放,不必为实验买一台物理机。
本文主轴是「定时/事件触发 + MCP 编排」,不是 git worktree 农场(那篇已单独立文)。OpenClaw 网关、18789 冷启动、Tunnel+MCP 仅在边界节对照,正文不复述。
2. SSH 开通与 launchd/crnd 环境:30 分钟验收清单
开通 远程 Mac M4 后,建议 30 分钟内完成下列项,再加载第一条 LaunchAgent。详细 SSH 接入见帮助中心。
- 密钥 SSH 登录,
uname -m为 arm64,时区与 NTP 正确。 - 安装 Homebrew、Node 22(Agent CLI 常用)、
tmux或screen便于排障。 - 创建目录:
~/agent-runs/state、~/agent-runs/logs、~/agent-runs/scripts。 - 写入 API Key 到
~/.config/agent/env(权限 600),LaunchAgent 用EnvironmentVariables注入,勿硬编码进 plist。 - 手动跑一条
crnd schedule或launchd测试任务,确认日志落盘。 - 从机器
curl你的 LLM/MCP 端点,记录 RTT;Webhook 回调需确认防火墙与入站策略。
全部通过后再做 PoC 租期决策。任一步失败,先别升周/月租。
3. launchd LaunchAgent 拓扑
macOS 上用户级定时任务应放在 ~/Library/LaunchAgents/,用 launchctl bootstrap gui/$(id -u) 加载(Ventura 及以后推荐 bootstrap,而非旧式 load)。
| 模式 | 适用场景 | 优点 | 注意点 |
|---|---|---|---|
| launchd 直调脚本 | 固定间隔/日历、单仓库批处理 | 零依赖、系统原生、日志清晰 | plist 需手写 ThrottleInterval |
| crnd / agent-reveille | 多 Agent、自然语言排期 | CLI 友好、易版本管理 | 底层仍依赖 launchd/cron |
| n8n + MCP Webhook | 跨系统编排、人工审批节点 | Curated tools、重试与告警 | 多一跳延迟,需入站安全 |
典型 LaunchAgent 字段:
StartCalendarInterval:按日/时/分触发,替代 crontab。KeepAlive:进程退出后重启;与ThrottleInterval联用防崩溃环。StandardOutPath/StandardErrorPath:日志必配,否则排障只能猜。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>Label</key><string>com.kvmboot.agent.codex-batch</string>
<key>ProgramArguments</key><array>
<string>/bin/zsh</string><string>-lc</string>
<string>source ~/.config/agent/env && ~/agent-runs/scripts/run-codex-batch.sh</string>
</array>
<key>StartCalendarInterval</key><dict>
<key>Minute</key><integer>0</integer><key>Hour</key><integer>*/1</integer>
</dict>
<key>ThrottleInterval</key><integer>300</integer>
<key>StandardOutPath</key><string>/Users/runner/agent-runs/logs/codex.out.log</string>
<key>StandardErrorPath</key><string>/Users/runner/agent-runs/logs/codex.err.log</string>
</dict></plist>加载命令:launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.kvmboot.agent.codex-batch.plist。卸载用 bootout 同路径。
4. MCP / n8n Webhook 触发链与 Curated tools
MCP 触发 常见两条路:Agent CLI 直连 MCP Server(适合内网或 SSH 隧道内),或 n8n/Cursor Automations 经 Webhook 调远程 Runner 上的脚本(适合要审批、重试、告警的流程)。
安全边界建议:
- 只暴露 Curated tools(白名单文件读写、固定 API),禁止把 shell MCP 无限制暴露公网。
- Webhook 入站校验 HMAC / 短时 token,幂等键写入
state/runs防重复触发。 - 超时与重试:LLM 调用设 hard timeout;失败指数退避,避免 launchd 与 Webhook 双重触发雪崩。
2026 年 Mattermost + n8n + MCP 的案例说明:编排层在 n8n,执行层仍在 macOS Runner——与本文 launchd 直调可并存,按团队是否已有 n8n 选型。
5. Claude Code / Codex CLI 定时任务模板
Claude Code 与 Codex CLI 均可在非交互模式下跑批:关键是 AGENTS.md、工作目录与 env 注入一致,保证 launchd 环境与手动 SSH 同结果。
#!/bin/zsh set -euo pipefail cd ~/projects/my-repo export CODEX_API_KEY="$(grep CODEX_API_KEY ~/.config/agent/env | cut -d= -f2-)" /usr/local/bin/codex exec --prompt-file ~/agent-runs/prompts/nightly-review.md \ >> ~/agent-runs/logs/codex-$(date +%Y%m%d).log 2>&1
若用 agent-reveille / crnd:reveille add "0 9 * * 1-5" -- codex exec ... 可快速试验排期,稳定后再导出 plist 纳入 IaC。
与worktree 并行 Agent配合时:定时任务跑「合并/Review」类批处理,交互式编码仍走 worktree 分仓,避免单目录锁冲突。
6. 日志、密钥与存储规划
Agent 长跑后 state/runs、模型缓存与 npm/pnpm store 会快速占盘。经验区间(非 SLA):轻量文案 Agent 512 GB 可跑数周;带本地 Ollama 或大量 artifact 时 512 GB 可能在 2–4 周内触顶。
- 日志轮转:
log rotate或按日分割,避免单文件撑满 inode。 - 密钥只放 Keychain 或 600 权限 env 文件;LaunchAgent 禁止把 token 写进
ProgramArguments明文。 - 磁盘 80% 告警时优先清理 runs 缓存,再评估扩容或第二台并联 Runner。
内存方面:纯 API 调用型 Agent 16 GB 通常够用;若同机跑 Ollama 7B+ 或并行 Claude Code,关注 swap 与内存洪峰治理,必要时升 24 GB 或拆机。
7. 任务频率 × 租期:决策矩阵与迁移检查表
| 任务特征 | 存储压力 | 建议租期 | 迁移条件 |
|---|---|---|---|
| 每小时轻量 MCP | 低(<5 GB/周) | 日租 PoC → 月租 | 连续 7 天无失败、日志可审计 |
| 每日 Codex 全仓 Review | 中(10–30 GB/周) | 周租 → 月租 | 磁盘 <70%、RTT 稳定 |
| 多 Agent + 本地模型 | 高(>50 GB/周) | 周租 + 512GB→1TB | 考虑第二台并联 |
价格以套餐页与控制台为准。推荐顺序:日租 PoC(1–3 天,跑通 launchd + MCP 首任务)→ 周租锁迭代冲刺 → 连续两周指标稳定再月租常驻。PoC 清单:
- LaunchAgent 加载成功且重启后仍自启。
- 至少一次 Webhook/MCP 端到端成功,state 有幂等记录。
- 24h 日志无未捕获 panic;磁盘/inode 增量可接受。
- API RTT 与错误率在团队阈值内(美东/亚太按 workload 选节点)。
8. 与 OpenClaw Gateway 的边界(对照)
OpenClaw 擅长消息型网关:18789 对外、Tunnel+Webhook、多通道入站。本文的 定时 Agent 是批处理 CLI:launchd 触发、无常驻 HTTP 端口、适合 cron 类任务。二者可同一台 远程 Mac M4 共存,但应分账户/分目录隔离。网关部署详见 OpenClaw 专栏,本篇不展开。
9. 排障 FAQ
plist 加载失败? 用 plutil -lint 校验 XML;确认 Label 唯一;Ventura+ 用 bootstrap 而非 load。
launchctl bootstrap 报 I/O error? 先 bootout 同名 job,检查 plist 是否在 LaunchAgents 且路径无空格问题。
任务跑了但无日志? 检查 StandardOutPath 父目录是否存在、运行用户对目录可写。
KeepAlive 疯狂重启? 加大 ThrottleInterval,脚本内 set -e 前做好 trap;排查脚本是否秒退。
Seatbelt / Keychain 阻断 CLI? 首次交互式 SSH 下授权 Keychain;LaunchAgent 环境需与登录 shell 相同的 PATH 与 HOME。
MCP 超时? 限制 tools 数量、提高 timeout、把 Runner 迁到离 API 更近的区域节点。
Webhook 重复触发? 用幂等键写 state/runs;n8n 侧开 dedupe。
Ollama 本地推理 OOM? 换更小模型、限并发,或升内存档位/拆第二台 Runner。
何时加第二台并联? 单盘 80%+ 且清理无效,或 CPU 长时间 >85% 且任务可 shard。
日租 PoC 最短多久? 至少覆盖 24h 定时周期 + 一次人工 Webhook 触发。
和 worktree 并行文怎么分工? 本篇管「何时跑」;worktree 文管「在哪跑、如何并行编码」。
OpenClaw 还是 launchd? 消息/网关选 OpenClaw;cron/批处理选 launchd。FAQ 语气:不作 SLA 承诺,以 PoC 实测为准。