Cron 任务 — 按计划运行的智能体
🔵 Agent OS 能够按计划运行智能体,无需用户参与。 Cron 任务将提示注入模板会话并运行一个回合——就像 聊天请求一样,因此预算、钩子、工具和事件存储的行为 完全一致。最终响应会投递到一个或多个 sink。
- 任务配置存放在 YAML 中,并支持热重载。
- 动态任务在运行时由脚本创建(
schedule_cron),并 持久化到logs/cron.db,可在重启后存活。
在哪里定义
1. 在智能体上 — config/agents/<agent>/agent.yaml 中的 cron: 列表
(template 默认为智能体本身):
# config/agents/rss/agent.yaml
cron:
- name: morning-digest
schedule: "0 0 9 * * *"
prompt: "Резюмируй сегодняшние заголовки."
notify: [{ type: log }]
2. 全局 — config/cron.yaml(每个任务需指定 template):
# config/cron.yaml
jobs:
- name: morning-digest
template: rss
schedule: "0 0 9 * * *"
prompt: "Резюмируй сегодняшние заголовки."
名称冲突时,config/cron.yaml 优先于 agent.yaml。两个来源都支持
热重载;动态(脚本)任务独立于两者。
任务参考
| 字段 | 类型 | 含义 |
|---|---|---|
name |
string(必填) | 任务唯一 id |
template |
string | 要运行的模板(在 agent.yaml 中为隐式) |
schedule |
string | cron 表达式:sec min hour dom month dow(UTC) |
timezone |
string | IANA 时区(例如 Europe/Moscow),用于解释 schedule;默认为 UTC |
interval_secs |
int | 固定间隔(schedule 的替代方案) |
oneshot_at |
string | RFC 3339 时间——触发一次后退出 |
prompt |
string(必填) | 注入会话的用户消息 |
persistent |
bool | true 复用 cron:<name> 的会话(保留上下文);默认为 false |
timeout_secs |
int | 单次运行限制 |
overlap |
string | skip(默认)| queue | parallel |
retry |
map | { max, backoff_secs }(保留) |
enabled |
bool | 默认为 true |
notify |
list | 结果投递目标(见下方 sink) |
schedule / interval_secs / oneshot_at 中必须且只能指定一个。
Sink
一个任务可以组合任意 sink。没有 notify 时,结果只能
通过运行历史(GET /v1/cron、cron.db)获取。
type |
作用 | 字段 |
|---|---|---|
log |
将响应写入服务器日志 | — |
webhook |
将结果(JSON)POST 到 URL | url、token_env(可选的来自 env 的 bearer) |
telegram |
将响应发送到 Telegram 聊天 | chat_id、token_env(可选;默认为模板的机器人) |
vk |
将响应发送到 VKontakte 聊天 | peer_id、token_env(可选;默认为模板的社区令牌) |
yandex_messenger |
将响应发送到 Yandex Messenger | chat_id(聊天/频道 id 或用户登录名)、token_env(可选;默认为模板的机器人令牌) |
messages_db |
将响应持久化到 message store | scope(默认为 cron:run:<name>) |
agent |
将响应作为消息投递给另一个智能体 | template、session(可选)、run(默认 true)、prompt_wrap(可选,{result}) |
email |
通过 SMTP 发送响应 | to、subject(可选;默认为任务名)、smtp |
workflow |
启动工作流(忽略智能体运行) | name、input |
storage |
将响应作为文件写入存储 | storage(backend)、key({source}/{ts}) |
多 sink 示例:
notify:
- type: log
- type: webhook
url: "https://hooks.example.com/ingest"
token_env: "CRON_WEBHOOK_SECRET"
- type: telegram
chat_id: 123456789
- type: vk
peer_id: 41848219
- type: messages_db
scope: "cron:reports"
- type: agent
template: summarizer
session: "pipeline:reports"
run: true
prompt_wrap: "Новый отчёт:\n{result}"
- type: email
to: "ops@example.com"
subject: "Cron: reports"
smtp:
host: "smtp.example.com"
username: "agent@example.com"
password_env: "SMTP_PASSWORD"
from: "agent@example.com"
脚本 API
工具脚本和钩子脚本可以在运行时调度任务(契约
对 Rhai 和 JS 通用)。这些任务是 dynamic,可跨重启持久化。
const r = schedule_cron({
name: "watch-price",
template: "hello-agent",
interval_secs: 3600,
prompt: "Проверь цену и сообщи.",
});
// r = { name: "watch-price", ok: true }
const gone = cancel_cron("watch-price"); // -> bool
const jobs = list_cron(); // -> массив статусов заданий
schedule_cron 返回 { name, ok, error? };cancel_cron(name) — bool;
list_cron() — 状态数组(name、template、schedule、last run)。错误
仅在 cron 服务未连接时抛出(例如无服务器的 agent-os hook)。
历史与监控
每次运行都会写入 logs/cron.db(表 cron_runs),包含状态
(success / error / budget_exhausted / rate_limited / timeout)、
token 数量、成本估算和时间信息。
GET /v1/cron(管理员)——列出任务及其计划和最近一次 运行的摘要。POST /v1/cron/:name/run(管理员)——手动「立即」运行任务, 无需等待计划(走同一条路径:overlap、运行记录、 sink)。- 原始历史——对
logs/cron.db→cron_runs执行 SQL 查询。
注意事项
- 预算:计划任务像普通会话一样从模板的预算组中
消耗。在共享组上频繁运行的任务可能会让活跃
用户「饥饿」——请配置
budget/budget_group。 - 时间默认为 UTC;可通过
timezone字段设置本地时间 (IANA 名称,例如Europe/Moscow)。interval_secs和oneshot_at不依赖 时区。 - 不补跑:错过的 tick(服务器停机、overlap)会被跳过,不会 重放。
- Sink 为 best-effort:失败的 sink 会记录警告,不会导致运行失败。
agent-sink 可组合:A → B → C链可以工作,因为每一 跳都是普通的会话回合。