总体设计
现有聊天能力在 AgentService.java 和 SessionService.java 里,前端聊天页在 ChatView.vue。定时任务建议复用这些能力。
执行流程:
用户创建定时任务
-> 后端保存任务配置
-> Scheduler 注册/刷新任务
-> 到点触发
-> 创建一次执行记录
-> 包装提示词并调用 Agent
-> Agent 工具调用、思考、结果进入同一个聊天 session
-> 前端任务页展示状态,聊天页展示执行过程
后端模块
新增一个 scheduled_task 模块即可,不建议一开始引入 Quartz,Spring 自带 ThreadPoolTaskScheduler + CronTrigger 足够。等以后多实例部署、任务分片、分布式锁再升级 Quartz 或 ShedLock。
建议新增:
controller/ScheduledTaskController.java
service/ScheduledTaskService.java
service/ScheduledTaskRunner.java
service/ScheduledTaskRegistry.java
mapper/ScheduledTaskMapper.java
mapper/ScheduledTaskRunMapper.java
entity/ScheduledTask.java
entity/ScheduledTaskRun.java
dto/scheduled/*
职责划分:
ScheduledTaskController
负责 REST API:列表、新建、修改、删除、启停、立即执行。
ScheduledTaskService
负责参数校验、任务 CRUD、计算下次执行时间、刷新调度注册。
ScheduledTaskRegistry
维护 taskId -> ScheduledFuture 映射,支持启动时加载、编辑后重排、删除后取消。
ScheduledTaskRunner
真正执行任务:创建 run 记录、调用 Agent、更新执行状态。
数据库设计
建议至少两张表:任务定义表 + 执行记录表。
CREATE TABLE scheduled_task (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
cron_expression VARCHAR(100) NOT NULL,
timezone VARCHAR(64) NOT NULL DEFAULT 'Asia/Shanghai',
prompt TEXT NOT NULL,
remark TEXT,
enabled TINYINT(1) NOT NULL DEFAULT 1,
session_id VARCHAR(128) NOT NULL,
last_run_status VARCHAR(32),
last_run_time DATETIME,
next_run_time DATETIME,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
CREATE TABLE scheduled_task_run (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
task_id BIGINT NOT NULL,
session_id VARCHAR(128) NOT NULL,
trigger_type VARCHAR(32) NOT NULL,
status VARCHAR(32) NOT NULL,
prompt_snapshot TEXT NOT NULL,
error_message TEXT,
started_at DATETIME,
finished_at DATETIME,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_task_time (task_id, create_time),
KEY idx_status (status)
);
状态建议:
任务启用状态:enabled / disabled
执行状态:PENDING / RUNNING / SUCCESS / FAILED / WAITING_INPUT
触发类型:SCHEDULED / MANUAL
session_id 很重要。我建议每个定时任务绑定一个固定聊天会话,比如:
scheduled_task_1
scheduled_task_2
这样“每天早上八点查询昨天营业额”的每次执行都会追加到同一个聊天会话里,用户从任务页点进去就能看到完整过程和历史结果。
AI 执行方式
定时任务不要直接把原始 prompt 丢给 AI,建议包装一下,解决“昨天”“今天”这类相对时间问题:
这是一个系统定时任务,请根据用户提示执行数据分析。
任务标题:每日营业额查询
触发时间:2026-07-13 08:00:00
时区:Asia/Shanghai
用户提示词:
查询昨天的营业额,并给出同比/环比变化。
这样 AI 知道“昨天”是相对哪一天。
后端执行时可以复用现有 AgentService.chatStream(sessionId, message, null),即使没有前端 SSE 连接,也可以在后端订阅并消费完整 Flux,让 Agent 把消息保存进 agentscope_sessions。执行结束后更新 scheduled_task_run.status。
如果执行过程中 Agent 触发 ask_user,定时任务应标记为 WAITING_INPUT,前端任务页显示“等待用户输入”,用户点进聊天页后继续回答。
接口设计
GET /api/scheduled-tasks
GET /api/scheduled-tasks/{id}
POST /api/scheduled-tasks
PUT /api/scheduled-tasks/{id}
DELETE /api/scheduled-tasks/{id}
POST /api/scheduled-tasks/{id}/enable
POST /api/scheduled-tasks/{id}/disable
POST /api/scheduled-tasks/{id}/run
GET /api/scheduled-tasks/{id}/runs
创建/编辑请求建议:
{
"title": "每日营业额查询",
"cronExpression": "0 0 8 * * *",
"timezone": "Asia/Shanghai",
"prompt": "查询昨天的营业额,并给出简短总结",
"remark": "每天早上发一次日报",
"enabled": true
}
Spring cron 是 6 段,0 0 8 * * * 表示每天 08:00。
前端页面
新增路由:
侧边栏加一个“定时任务”。
页面结构建议:
顶部工具栏:
新建任务、刷新
任务表格:
标题
执行时间
备注
启用状态
最近执行状态
上次执行时间
下次执行时间
操作:编辑 / 立即执行 / 启停 / 删除 / 查看聊天
编辑抽屉或弹窗:
标题
执行规则
时区
备注
提示词 textarea
是否启用
执行规则前端可以先做简单模式:
每天:选择时间 -> 生成 cron
每周:选择星期 + 时间 -> 生成 cron
每月:选择日期 + 时间 -> 生成 cron
高级:直接填写 cron
比如“每天早上八点”前端生成:
“查看聊天”按钮跳转:
这样执行过程会直接走现有 TracePanel,工具调用、SQL 执行结果、最终总结都能展示。
推荐实现顺序
- 后端先加数据库表、实体、mapper、CRUD API。
- 加
ThreadPoolTaskScheduler 和动态注册逻辑。
- 实现“立即执行”,确认能写入聊天会话。
- 实现定时触发,到点自动执行。
- 前端加任务管理页和任务编辑弹窗。
- 任务页增加“查看聊天”和“立即执行后跳转聊天”。
总体设计
现有聊天能力在 AgentService.java 和 SessionService.java 里,前端聊天页在 ChatView.vue。定时任务建议复用这些能力。
执行流程:
后端模块
新增一个
scheduled_task模块即可,不建议一开始引入 Quartz,Spring 自带ThreadPoolTaskScheduler + CronTrigger足够。等以后多实例部署、任务分片、分布式锁再升级 Quartz 或 ShedLock。建议新增:
职责划分:
数据库设计
建议至少两张表:任务定义表 + 执行记录表。
状态建议:
session_id很重要。我建议每个定时任务绑定一个固定聊天会话,比如:这样“每天早上八点查询昨天营业额”的每次执行都会追加到同一个聊天会话里,用户从任务页点进去就能看到完整过程和历史结果。
AI 执行方式
定时任务不要直接把原始 prompt 丢给 AI,建议包装一下,解决“昨天”“今天”这类相对时间问题:
这样 AI 知道“昨天”是相对哪一天。
后端执行时可以复用现有
AgentService.chatStream(sessionId, message, null),即使没有前端 SSE 连接,也可以在后端订阅并消费完整 Flux,让 Agent 把消息保存进agentscope_sessions。执行结束后更新scheduled_task_run.status。如果执行过程中 Agent 触发
ask_user,定时任务应标记为WAITING_INPUT,前端任务页显示“等待用户输入”,用户点进聊天页后继续回答。接口设计
创建/编辑请求建议:
{ "title": "每日营业额查询", "cronExpression": "0 0 8 * * *", "timezone": "Asia/Shanghai", "prompt": "查询昨天的营业额,并给出简短总结", "remark": "每天早上发一次日报", "enabled": true }Spring cron 是 6 段,
0 0 8 * * *表示每天 08:00。前端页面
新增路由:
侧边栏加一个“定时任务”。
页面结构建议:
执行规则前端可以先做简单模式:
比如“每天早上八点”前端生成:
“查看聊天”按钮跳转:
这样执行过程会直接走现有
TracePanel,工具调用、SQL 执行结果、最终总结都能展示。推荐实现顺序
ThreadPoolTaskScheduler和动态注册逻辑。