Nanobot Cron 技能全解析:在聊天会话中调度提醒、定时任务与一次性任务
Nanobot Cron 技能全解析在聊天会话中调度提醒、定时任务与一次性任务【免费下载链接】nanobotUltra-lightweight, open-source, self-hosted personal AI agent framework in Python with WebUI, tools, memory, MCP, multi-agent workflows, automation, and chat apps项目地址: https://gitcode.com/gh_mirrors/nanob/nanobot导读cron是 Nanobot 内建的一项 Agent 技能Skill它让 Agent 能够在任意聊天会话中通过cron工具创建定时提醒Reminder、定时任务Task和一次性任务One-time并在触发时把结果回执到创建任务的原始会话。读完本文你将掌握cron工具的三种模式、全部参数与校验规则、时间表达式与时区用法并理解任务在底层是如何被调度、持久化并回话的涉及 cron 工具实现 与 CronService 调度引擎。本文以技能定义文档 nanobot/skills/cron/SKILL.md 为主体骨架结合仓库源码与测试用例进行纵深展开。一、cron 技能是什么在 Nanobot 中技能Skill以目录形式存放在 nanobot/skills/ 下每个技能目录内的SKILL.md就是该技能的说明文档会被 Agent 作为提示词加载。cron 技能的元信息定义如下--- name: cron description: Schedule reminders and recurring tasks. ---cron技能的核心是cron工具Agent 可以调用它来安排提醒或周期性任务这些任务触发时会回报到发起它们的聊天/会话should report back to the originating chat/session when they run。这是它与纯后台任务的关键区别需要主动回报给用户的定时行为 → 使用cron需要静默执行、没有有价值内容就不打扰用户的后台周期性检查 → 不要使用cron而应更新HEARTBEAT.md仓库模板见 nanobot/templates/HEARTBEAT.md。受保护的 heartbeat 作业会运行这些检查并且只投递通过通知门控notification gate的结果。二、三种调度模式原文档将 cron 任务归纳为三种模式模式行为Reminder提醒消息直接发送给用户Task任务message是任务描述Agent 每次触发时执行并把结果回报给用户One-time一次性在指定时间运行一次运行后自动删除从源码结构看这三种模式对应 CronSchedule 的三种kindkindevery固定间隔循环对应 Reminder/Task 的every_secondskindcron标准 cron 表达式对应cron_expr 可选tzkindat指定时刻的单次执行对应at并且delete_after_runTrue即运行后自动删除——这正是一次性任务的底层实现见 CronTool._add_job 与 CronService._execute_job 中if job.schedule.kind at: if job.delete_after_run: ...的处理分支。无论哪种模式message字段都承载任务内容对 Reminder 它就是提醒文本对 Task 它就是 Agent 要执行的指令描述。三、cron 工具参数详解cron工具的参数模式定义在 cron.py 顶部 schema完整参数如下参数类型是否必填说明actionstring必填取值add/list/removenamestring可选任务的人类可读短标签如weather-monitor、daily-standup缺省时取 message 前 30 个字符messagestringadd时必填任务触发时 Agent 要执行的指令如给微信发送提醒xxx或检查系统状态并汇报list/remove时不使用every_secondsinteger与cron_expr/at三选一循环间隔秒用于周期性任务cron_exprstring与every_seconds/at三选一标准 cron 表达式如0 9 * * *tzstring可选用于 cron 表达式的 IANA 时区如America/Vancouver省略时使用工具默认时区atstring与every_seconds/cron_expr三选一一次性执行的 ISO 时间如2026-02-12T10:30:00naive不带时区值按工具默认时区解释job_idstringremove时必填要删除的任务 ID通过actionlist获取有几个值得注意的实现细节schema 顶层只要求actionadd必须带非空message 一种调度方式、remove必须带job_id等约束是在运行时由validate_params强制执行的cron.py#L127-L134。设计者特意不在 schema 顶层使用oneOf/anyOf/allOf/enum/not因为部分模型提供商如 OpenAI Codex/Responses会拒绝这类根级结构见 test_cron_schema_advertises_action_specific_requirements。必须从聊天会话创建_add_job会从当前请求快照读取session_key、origin_channel、origin_chat_id并把它们绑定到任务cron.py#L172-L176。若没有会话上下文会返回错误Error: scheduled cron jobs must be created from a chat session对应测试 test_add_job_requires_session_key。tz只能搭配cron_expr使用否则报错时区名会用zoneinfo.ZoneInfo校验未知时区直接返回错误。调度方式必须三选一every_seconds、cron_expr、at至少提供一个否则报错Error: either every_seconds, cron_expr, or at is required。cron 执行上下文中不能再创建新任务CronTool通过 ContextVar 标记当前是否处于 cron 回调内若在 cron 任务执行期间再次调用add会返回Error: cannot schedule new jobs from within a cron job execution防止任务递归爆炸cron.py#L87-L93、cron.py#L147-L150。创建成功后返回Created job name (id: id)id为 8 位随机短 ID后续list/remove都要用到它。四、完整示例以下示例均来自 nanobot/skills/cron/SKILL.md 并保持可复制性固定间隔提醒每 20 分钟提醒一次消息直接发给用户cron(actionadd, messageTime to take a break!, every_seconds1200)动态任务每次触发时 Agent 执行查询并回报结果cron(actionadd, messageCheck HKUDS/nanobot GitHub stars and report, every_seconds600)一次性定时任务at需要由 Agent 根据当前时间计算出 ISO 时间再补足具体时刻cron(actionadd, messageRemind me about the meeting, atISO datetime)时区感知的 cron 表达式工作日早 9 点按温哥华时区cron(actionadd, messageMorning standup, cron_expr0 9 * * 1-5, tzAmerica/Vancouver)查看与删除cron(actionlist) cron(actionremove, job_idabc123)list的输出会给出每个任务的name、id、人类可读的调度时机如cron: 0 9 * * 1-5 (America/Denver)、every 30m、at 2026-... (Asia/Shanghai)以及最近一次运行的Last run状态ok/error及错误信息和Next run时间——这些格式化逻辑见 CronTool._format_timing / _format_state行为被 tests/cron/test_cron_tool_list.py 中的一组测试严格锁定。五、时间表达式速查表原文档给出的用户表述 → 工具参数对照表是 Agent 调用时最常用的换算依据用户说参数every 20 minutes每 20 分钟every_seconds: 1200every hour每小时every_seconds: 3600every day at 8am每天早 8 点cron_expr: 0 8 * * *weekdays at 5pm工作日 17 点cron_expr: 0 17 * * 1-59am Vancouver time daily每天温哥华时间早 9 点cron_expr: 0 9 * * *, tz: America/Vancouverat a specific time在指定时刻at: ISO datetime string由 Agent 基于当前时间计算补充说明两点换算细节every_seconds与 cron 表达式的关系every_seconds是从当前时刻起每隔 N 秒的简易循环底层存为every_ms every_seconds * 1000而cron_expr是标准的日历表达式由croniter库在指定时区下计算下一次触发时刻见 service.py 的 _compute_next_run。at的正确用法Agent 应当基于当前时间推导出具体的 ISO datetime 字符串含秒例如当前时间加上会议剩余时长而非让用户手工填写。六、时区Timezone行为使用tzcron_expr可以在指定的 IANA 时区如America/Vancouver、Asia/Shanghai内调度。不传tz时使用工具默认时区CronTool构造时默认值为UTC实际运行时由ToolContext.timezone注入cron.py#L59-L73即通常会落到服务器/运行时配置的时区上。at的一次性任务若给出naive无时区ISO 时间也按默认时区解释源码中会dt.replace(tzinfoZoneInfo(default_timezone))后再换算成毫秒时间戳cron.py#L192-L204。测试 test_add_at_job_uses_default_timezone_for_naive_datetime 验证了这一点。带时区的cron_expr在list展示时也会显式带上时区名方便核对如cron: 0 9 * * 1-5 (America/Denver)。七、底层调度引擎CronService所有 cron 任务的调度、持久化与执行都由 CronService 承担可以从几个维度理解它持久化与可靠性任务存储在jobs.jsonCronService.__init__的store_path指向每次变更通过临时文件 os.replacefsync原子写入避免容器停机时写坏文件导致任务全部丢失service.py#L433-L468。若启动时发现jobs.json损坏不会用空任务列表覆盖而是把损坏文件备份为jobs.json.corrupt-ts并拒绝启动保留恢复可能service.py#L235-L275。服务间通过action.jsonl追加操作日志合并变更_merge_action支持多实例场景。调度循环服务启动后重算所有任务的next_run_at_ms并武装一个 asyncio 定时器定时器最长睡眠max_sleep_ms默认 5 分钟到期后找出所有到期任务逐个执行最后重新武装service.py#L520-L599。每个任务维护CronJobStatenext_run_at_ms、last_run_at_ms、last_statusok/error/skipped、last_error以及最近20 条运行历史_MAX_RUN_HISTORY 20这些状态都会随list呈现给用户。系统任务保护内部系统任务payload.kind system_event对用户可见但不可删除例如名为dream的记忆整合任务Dream memory consolidation for long-term memory。remove时会被拒绝并给出明确解释cron.py#L276-L294对应测试 test_remove_protected_dream_job_returns_clear_feedback。八、触发时如何回报原会话定时任务触发后执行器 bound_runner.run_bound_cron_job 会用任务message渲染执行提示模板 nanobot/templates/agent/cron_reminder.md模板要求 Agent直接以用户的语言说话、不叙述内部进度、不包含用户 ID、不要添加完成/已提醒之类的状态报告随后以该 prompt 发起一轮正常会话轮次通过任务绑定的session_key覆盖会话归属并按origin_channel/origin_chat_id把输出投递回原始聊天session_delivery.pyorigin_metadata中保留了 Slack 线程、WebUI 等额外路由上下文在消息元数据中写入_cron_trigger含job_id、job_name、run_id、prompt_ref等以及会话空闲时再投递的标记见 session_turns.py 中的CRON_AUTOMATION_SPEC确保 cron 轮次在会话历史中可被正确识别、不与正在进行的对话冲突每次执行还会写入运行审计记录runs/目录供事后排查。简单说cron 任务 被定时触发的代理会话轮次这正是任务结果会回报到原会话这一体验的底层保证。九、cron 与 HEARTBEAT 的分工这是本技能使用中最容易混淆的一点原文档特别强调场景正确选择需要向用户主动推送的提醒、任务结果cron工具周期性后台检查无事发生时应保持安静更新HEARTBEAT.md受保护的 heartbeat 作业负责运行只投递通过通知门控的结果判断标准很简单这次触发是否必须让用户看到。若结果可能有价值但未必值得打扰用户就走 HEARTBEAT 通道由通知门控决定是否打扰若用户明确要求到点提醒我/到点执行并汇报就用cron。仓库中的 heartbeat 模板见 nanobot/templates/HEARTBEAT.md。十、验证与测试仓库对 cron 功能有完善的测试覆盖可作行为契约参考tests/cron/test_cron_tool_list.pylist输出格式化时区显示、every 2h/30m/30s/200ms的人类可读换算、at时间戳展示、Last run/Next run状态展示、受保护系统任务dream不可删除、默认时区落库、会话绑定session_key/origin_channel/origin_chat_id正确写入 payload 且不再使用旧式channel/to投递字段、参数校验规则等tests/cron/test_cron_service.py 等目录内其他测试文件覆盖调度主循环、持久化与一次性任务删除等行为。这些测试同时也揭示了任务数据模型CronJob→CronScheduleCronPayloadCronJobState见 nanobot/cron/types.py是深入阅读源码的最佳入口。结语Nanobot 的cron技能把定时触发与代理会话无缝衔接every_seconds、cron_expr(tz)、at三种调度方式覆盖循环任务与一次性任务任务创建即绑定来源会话、触发即作为一轮代理对话回报结果配合jobs.json的原子持久化、20 条运行历史与系统任务保护构成了一个可靠、可审计、可交互的定时任务体系。日常使用只需记住提醒与任务用cron静默后台检查用HEARTBEAT。【免费下载链接】nanobotUltra-lightweight, open-source, self-hosted personal AI agent framework in Python with WebUI, tools, memory, MCP, multi-agent workflows, automation, and chat apps项目地址: https://gitcode.com/gh_mirrors/nanob/nanobot创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →