Skip to content

插件定时任务开发

插件定时任务主要通过两个 API 实现:

  • nekro_agent.api.timer — 一次性与临时定时器
  • nekro_agent.api.recurring_timer — 循环定时任务(cron)

选择依据

需求推荐 API
一次性提醒、临时自我唤醒timer
周期重复执行、cron 表达式recurring_timer
需要暂停/恢复/立即执行recurring_timer
工作日/节假日模式recurring_timer

一次性定时器

基本用法

python
import time
from nekro_agent.api import timer

async def remind_later(chat_key: str) -> bool:
    return await timer.set_timer(
        chat_key=chat_key,
        trigger_time=int(time.time()) + 300,
        event_desc="五分钟后提醒用户继续当前任务",
    )

如需保证同一频道只保留最新一个短期提醒,使用 set_temp_timer

python
await timer.set_temp_timer(
    chat_key=chat_key,
    trigger_time=int(time.time()) + 60,
    event_desc="一分钟后再次检查状态",
)

trigger_time 特殊值

trigger_time 参数除正常 Unix 时间戳外还支持以下特殊值:

行为
0立即触发当前频道的 Agent 任务(等效于 schedule_agent_task
负数(如 -1清空当前频道的定时器

管理定时器

python
from nekro_agent.api import timer

# 获取当前频道所有未触发的定时器
timers = await timer.get_timers(chat_key)

# 清空当前频道的所有定时器
await timer.clear_timers(chat_key)

# 只清空临时定时器
await timer.clear_timers(chat_key, temporary=True)

# 只清空非临时定时器
await timer.clear_timers(chat_key, temporary=False)

持久化与 misfire 补发

一次性定时器(set_timer / set_temp_timer 设置的无回调普通定时器)会被自动持久化到磁盘。服务重启后会自动恢复:

  • 未过期的定时器:恢复后继续按原定时间触发。
  • 已过期但在宽限期内(默认 300 秒)的定时器:立即补发一次系统消息。
  • 已过期且超出宽限期:丢弃。

循环定时任务

python
from nekro_agent.api import recurring_timer

async def create_daily_job(chat_key: str) -> str:
    job = await recurring_timer.create_cron_job(
        chat_key=chat_key,
        cron_expr="0 9 * * *",
        event_desc="每天上午九点执行日报提醒",
        timezone="Asia/Shanghai",
        workday_mode="mon_fri",
        title="工作日报提醒",
    )
    return job.job_id

常用操作

python
# 暂停 / 恢复 / 立即执行 / 删除
await recurring_timer.pause_job(job_id)
await recurring_timer.resume_job(job_id)
await recurring_timer.run_now(job_id)
await recurring_timer.delete_job(job_id)

# 更新任务(可同时更新多个字段)
await recurring_timer.update_job(
    job_id,
    cron_expr="0 10 * * *",
    event_desc="更新后的描述",
    timezone="Asia/Shanghai",
    workday_mode="mon_fri",
    title="新标题",
)

# 查询
jobs = await recurring_timer.list_jobs(chat_key)                          # 全部
active_jobs = await recurring_timer.list_jobs(chat_key, status="active")  # 仅活跃
job = await recurring_timer.get_job(job_id)                               # 单个任务

# 任务统计摘要:返回 (活跃数, 暂停数, 即将触发列表, 最近触发列表)
active, paused, upcoming, recent = await recurring_timer.get_job_summary(
    chat_key, upcoming_limit=5, recent_limit=5,
)

# 获取任务对外短 ID
short_id = recurring_timer.get_job_id(job)

校验工具

python
from nekro_agent.api import recurring_timer

# 校验 cron 表达式是否合法(5 段格式:min hour day month dow)
recurring_timer.validate_cron_expr("0 9 * * 1-5")

# 校验时区是否合法(IANA TZ)
recurring_timer.validate_timezone("Asia/Shanghai")

工作日模式

workday_mode 参数用于在指定时间范围内按工作日规则过滤触发:

说明
none不限制,按 cron 正常触发
mon_fri仅周一至周五
weekend仅周末
cn_workday仅中国法定工作日(含调休补班)
cn_restday仅中国法定休息日(含调休放假)

降级策略:当中国节假日数据不可用时,cn_workday 会降级为 mon_fri(周一至周五),cn_restday 会降级为 weekend(周六日)。

与 push_system 结合

定时器触发后,通常需要将上下文推回 Agent 继续处理。推荐使用 message.push_system

python
from nekro_agent.api import message

async def on_timer_trigger(chat_key: str):
    await message.push_system(
        chat_key=chat_key,
        message="定时任务触发:请执行每日汇总并发送报告",
        trigger_agent=True,
    )

完整签名

python
async def push_system(
    chat_key: str,
    message: str,
    ctx: Optional[AgentCtx] = None,
    trigger_agent: bool = False,
) -> None
参数说明
chat_key聊天标识,格式为 {adapter_key}-{channel_id}
message系统消息内容
ctxAgent 上下文对象(可选)
trigger_agent是否触发 AI 响应,默认 False

这种组合适合自动工作流推进、定时巡检和后台定期通知。

Misfire 策略(周期任务)

当服务重启或调度阻塞导致 cron 任务错过预定触发时间时,由以下字段控制补发行为:

字段类型默认值说明
misfire_policystr"fire_once"错过触发策略。fire_once:在宽限期内补发一次;skip:跳过本次
misfire_grace_secondsint300宽限秒数,超过此时间则不再补发

连续失败自动暂停

周期任务连续触发失败 3 次后会自动暂停,并向频道发送通知消息,提示用户可调用 resume_job 恢复或 update_job 修正参数。

成功触发后 consecutive_failures 计数器会自动归零。

相关文档