---
date: 2026-06-23
topic: calendar-schedule
---

## Summary

在 AgentKit 客户端右侧面板嵌入行事历（可展开为大抽屉），通过混合模式（ReAct 工具调用 + 时间关键词触发的后处理提取）自动捕获对话中的日程，同时支持完整的手动管理——循环事件、自定义类型、标签、三种视图（日历/卡片/列表），UI 对标 Notion Calendar。日程双向同步 Apple Calendar (CalDAV)、Outlook (Graph API) 和 iCal/ICS，配套独立的多渠道提醒子系统（客户端 + 邮件 + Webhook），个人为主 + 共享邀请。

## Problem Frame

Agent 对话中频繁产生可执行的时间安排——会议时间、截止日期、跟进任务——但这些信息当前无处记录。用户必须手动将这些内容转移到外部日历中，这个过程容易遗漏，尤其在长对话中多个时间点被讨论时。痛点不在"缺少一个日历应用"，而在"Agent 产生的日程与日历之间没有桥梁"：对话结束后，时间承诺就消失了。

## Key Decisions

**混合 Agent 识别模式。** ReAct 工具调用捕获实时意图（Agent 在对话中主动调用 `create_event`），后处理提取作为兜底——但仅在对话包含时间关键词时触发 LLM 提取，避免每轮对话都产生额外 LLM 调用。两层机制互补：工具调用覆盖 Agent 已识别的明确日程，后处理覆盖 Agent 未主动识别但对话中隐含的时间安排。

**右侧面板 + 大抽屉而非独立页面。** 日历紧贴对话上下文，用户不用切换页面就能看到即将到来的日程。需要全屏管理时展开为大抽屉。这牺牲了独立页面的全屏日历体验，但换来了日程与对话的紧密耦合——这是核心痛点的解法。

**提醒系统作为独立子系统。** 多渠道提醒（客户端推送 + 邮件 + Webhook）需要后台调度器、通知规则、渠道适配器、投递追踪——这不仅是日历的一个功能，而是 AgentKit 目前不存在的全新基础设施。作为独立子系统设计，未来可被其他功能复用。

**个人日历 + 共享邀请，不做团队日历。** 用户有自己的私人日历，可以邀请其他用户参加事件（类似 Google Calendar 的邀请），但不支持多用户共同编辑同一日历。团队日历是不同的产品形态，不在此次范围内。

## Actors

- A1. **终端用户** — 管理个人日历，手动创建/查看/编辑/删除事件，管理事件类型和标签，配置提醒规则
- A2. **Agent** — 在 ReAct 循环中自主识别日程意图并调用日历工具创建事件；后处理提取层在时间关键词触发时分析对话内容
- A3. **外部日历服务** — Apple Calendar (CalDAV)、Outlook (Microsoft Graph API)、iCal/ICS 通用格式，作为双向同步目标
- A4. **提醒子系统** — 后台调度器定期扫描即将到期的事件，根据提醒规则通过配置的渠道分发通知

## Requirements

### 事件数据模型

- R1. 事件包含标题、描述、开始时间、结束时间、全天标记、地点字段
- R2. 事件支持循环模式：每日、每周、每月、自定义 RRULE 规则（至少支持 INTERVAL、COUNT、UNTIL、BYDAY）
- R3. 事件支持自定义事件类型——用户可创建带名称和颜色的分类（如"会议"蓝色、"截止"红色），事件创建时选择类型
- R4. 事件支持多标签——用户可自定义标签，单个事件可挂多个标签，支持按标签筛选
- R5. 事件支持时间段——开始时间 + 结束时间，不限于时间点；全天事件和跨天事件均支持

### 视图模式

- R6. 日历视图——月/周/日网格布局，支持拖拽创建（拖选时间段直接建事件）、拖拽移动（拖动事件改变时间）
- R7. 卡片视图——看板风格，按日期或事件类型分组，卡片可拖拽调整分组
- R8. 列表视图——按时间排序的列表，支持行内编辑和批量操作
- R9. 三种视图在右侧面板和大抽屉中均可切换使用

### Agent 自动识别

- R10. Agent 在 ReAct 循环中可调用日历工具集：`create_event`、`query_events`、`update_event`、`delete_event`
- R11. 后处理提取在对话轮次结束后运行，但仅当对话内容包含时间关键词时触发——关键词列表包括但不限于：明天、下周、今天下午、X点、X月X日、开会、截止、deadline、schedule、reminder、提醒、预约
- R12. 时间关键词检测使用正则/关键词匹配（零 LLM 调用），命中后才发起 LLM 提取请求
- R13. Agent 创建的事件标记 `source="agent"`，并关联到 originating 对话 ID，可在日历中追溯来源
- R14. 后处理提取创建的事件标记 `source="post_extract"`，同样关联对话 ID
- R15. 用户可在 UI 中区分手动创建、Agent 创建、后处理提取的事件（通过来源标记或颜色区分）

### 手动管理

- R16. 用户可通过 UI 手动创建、编辑、删除事件——三种视图均支持创建入口
- R17. 日历视图支持拖拽改期——拖动事件到新时间位置即可调整开始/结束时间
- R18. 事件类型和标签可在事件编辑界面中设置和修改
- R19. 支持批量操作：多选事件后批量删除、批量修改类型/标签

### 外部日历同步

- R20. 与 Apple Calendar 通过 CalDAV 协议双向同步——在 AgentKit 创建/修改/删除的事件同步到 Apple Calendar，反之亦然
- R21. 与 Outlook Calendar 通过 Microsoft Graph API 双向同步——同上双向
- R22. 支持 iCal/ICS 格式的导入和导出——可从 .ics 文件导入事件，可将日历导出为 .ics
- R23. 同步冲突采用 last-write-wins 策略，冲突时保留最后修改的版本，并向用户发送冲突通知
- R24. 用户可在设置中配置每个外部日历的同步频率和同步范围（哪些事件类型参与同步）

### 提醒子系统

- R25. 事件支持提醒规则——可配置多个提醒（如"提前15分钟"、"提前1天"），每个提醒指定渠道
- R26. 提醒渠道支持：客户端内通知（WebSocket 推送 / Tauri 系统通知）、邮件、Webhook
- R27. 后台调度器定期扫描即将到期的事件，匹配提醒规则，通过配置的渠道分发通知
- R28. 用户可为每种事件类型配置默认提醒规则——新建事件时自动继承
- R29. 提醒投递状态可追踪（已发送/已读/失败），失败的提醒有重试机制

### 共享与邀请

- R30. 用户可邀请其他用户参加事件——通过用户名或邮箱搜索并邀请
- R31. 被邀请用户收到通知，可接受/拒绝/暂定
- R32. 事件创建者可查看邀请回复状态（谁接受、谁拒绝、谁未回复）
- R33. 被邀请用户的事件在其日历中以特殊样式标记（如半透明或边框区分）

### UI/UX

- R34. 日历嵌入右侧面板作为标签页（与 Workflow/Monitor 并列），展示今日/近期日程摘要
- R35. 右侧面板日历可展开为大抽屉——覆盖大部分屏幕，提供完整的三视图管理体验
- R36. UI 遵循 Notion Calendar 设计语言——简洁排版、充足留白、流畅拖拽、柔和配色
- R37. Agent 创建事件时，右侧面板实时更新（无需手动刷新），并有视觉提示（如高亮动画）

## Key Flows

- F1. Agent 工具调用创建日程
  - **Trigger:** Agent 在 ReAct 循环中识别到对话内容包含明确的时间安排
  - **Actors:** A2 (Agent), A1 (用户)
  - **Steps:** Agent 调用 `create_event` 工具，传入标题/时间/类型等参数 → 工具执行写入 → 返回创建结果 → Agent 在回复中告知用户已创建日程 → 右侧面板实时更新显示新事件
  - **Outcome:** 事件被创建并标记 `source="agent"`，用户在对话中收到确认
  - **Covers:** R10, R13, R37

- F2. 后处理提取创建日程
  - **Trigger:** 对话轮次结束，对话内容命中时间关键词正则
  - **Actors:** A2 (Agent 后处理层), A1 (用户)
  - **Steps:** 关键词检测命中 → 发起 LLM 提取请求，分析对话中的时间安排 → LLM 返回提取结果（0 或多个事件） → 写入日历，标记 `source="post_extract"` → 在对话中插入轻量提示"检测到 N 条日程，已添加到日历"
  - **Outcome:** 隐含的日程被捕获，用户收到提示可查看/修改
  - **Covers:** R11, R12, R14

- F3. 外部日历双向同步
  - **Trigger:** 定时同步任务触发，或用户手动触发同步
  - **Actors:** A3 (外部日历服务), A1 (用户)
  - **Steps:** 拉取外部日历变更 → 与本地事件比对 → 检测冲突 → last-write-wins 解决冲突 → 推送本地变更到外部日历 → 冲突时向用户发送通知
  - **Outcome:** 本地与外部日历保持一致，冲突被记录和通知
  - **Covers:** R20, R21, R23

- F4. 提醒分发
  - **Trigger:** 后台调度器扫描到事件即将到达提醒时间点
  - **Actors:** A4 (提醒子系统), A1 (用户)
  - **Steps:** 调度器匹配提醒规则 → 按规则配置的渠道分发通知（客户端推送 / 邮件 / Webhook） → 记录投递状态 → 失败时重试
  - **Outcome:** 用户在事件前通过配置的渠道收到提醒
  - **Covers:** R25, R26, R27, R29

- F5. 手动创建事件
  - **Trigger:** 用户在任意视图中触发创建操作（点击新建、拖选时间段、列表中添加）
  - **Actors:** A1 (用户)
  - **Steps:** 打开事件编辑表单 → 填写标题/时间/类型/标签/提醒/地点 → 保存 → 事件出现在日历中 → 如配置了外部同步，异步推送到外部日历
  - **Outcome:** 事件被创建并可管理
  - **Covers:** R16, R18

## Acceptance Examples

- AE1. Agent 在对话中识别日程
  - **Covers:** R10, R13, R15
  - **Given:** 用户与 Agent 对话，用户说"下周三下午3点开个产品评审会"
  - **When:** Agent 在 ReAct 循环中处理该输入
  - **Then:** Agent 调用 `create_event` 创建事件（标题="产品评审会", 开始时间=下周三15:00, source="agent"），并在回复中告知"已为您创建下周三下午3点的产品评审会日程"

- AE2. 后处理提取被关键词门控
  - **Covers:** R11, R12, R14
  - **Given:** 用户与 Agent 对话，对话内容为"这个方案不错，我们继续优化吧"
  - **When:** 对话轮次结束，后处理层检查时间关键词
  - **Then:** 关键词检测未命中（无时间相关词），不发起 LLM 提取请求，不创建任何事件

- AE3. 后处理提取在关键词命中时运行
  - **Covers:** R11, R12, R14
  - **Given:** 用户与 Agent 对话，对话内容为"好的，那下周二之前把文档发给我"
  - **When:** 对话轮次结束，后处理层检查时间关键词
  - **Then:** 关键词"下周二"命中 → 发起 LLM 提取 → 创建事件（标题="发送文档", 截止时间=下周二, source="post_extract"）→ 对话中插入提示"检测到 1 条日程，已添加到日历"

- AE4. 同步冲突解决
  - **Covers:** R23
  - **Given:** 用户在 AgentKit 修改了事件 A（改到周三），同时在 Outlook 也修改了事件 A（改到周四），同步时检测到冲突
  - **When:** 同步任务运行
  - **Then:** 保留最后修改的版本（last-write-wins），向用户发送冲突通知"事件 A 存在同步冲突，已保留最新修改"

- AE5. 提醒按渠道分发
  - **Covers:** R25, R26, R27
  - **Given:** 事件 B 配置了两个提醒：提前30分钟客户端通知 + 提前1天邮件通知
  - **When:** 调度器扫描到事件 B 的提前1天提醒时间点到达
  - **Then:** 通过邮件渠道发送提醒 → 记录投递状态为"已发送" → 继续等待提前30分钟的客户端通知时间点

## Scope Boundaries

### Deferred for later

- Google Calendar 集成——用户未选择，可在后续版本按需添加
- 团队共享日历——多用户共同编辑同一日历，当前仅支持个人 + 邀请
- 日历分析报表——事件统计、时间分布分析等
- 资源预订——会议室、设备等资源预约
- 移动端独立 App——当前仅 Web/Tauri 客户端

### Outside this product's identity

- 替代专业日历应用——AgentKit 行事历的核心差异化是 Agent 自动识别，不是与 Google Calendar/Notion Calendar 全功能竞争
- 项目管理——行事历不承担任务跟踪、甘特图、依赖管理等项目管理职能

## Dependencies / Assumptions

- 复用现有认证系统（`src/agentkit/server/auth/models.py` 的 `UserModel`）作为用户身份基础
- 复用现有 WebSocket 基础设施实现客户端实时通知推送
- 新增依赖：后台调度器（如 APScheduler）用于提醒子系统
- 新增依赖：CalDAV 客户端库用于 Apple Calendar 同步
- 新增依赖：Microsoft Graph SDK 或直接 HTTP 客户端用于 Outlook 同步
- 新增依赖：邮件发送能力（SMTP 或第三方服务）用于邮件提醒渠道
- 假设：用户已拥有 Apple Calendar / Outlook 账号并可提供 OAuth/CalDAV 凭据
- 假设：AgentKit 服务端可持续运行后台调度器进程（提醒子系统依赖）

## Sources / Research

- 现有架构落位参考：路由注册在 `src/agentkit/server/app.py`（第 928-954 行），前端布局在 `src/agentkit/server/frontend/src/components/layout/AgentLayout.vue`（第 146-156 行定义象限标签）
- 前端 Pinia stores 位于 `src/agentkit/server/frontend/src/stores/`，API 客户端位于 `src/agentkit/server/frontend/src/api/`
- 后端路由模块位于 `src/agentkit/server/routes/`（27 个 .py 文件），工具注册在 `src/agentkit/tools/registry.py`
- 用户模型位于 `src/agentkit/server/auth/models.py`（SQLAlchemy 2 + SQLite），可复用 `Base` 创建日历模型
- 消息总线 `src/agentkit/bus/message.py` 的 `AgentMessage` 可用于提醒子系统的内部通信
- DocumentTool（`src/agentkit/tools/document_tool.py`）可作为 Agent 工具集成的参考模式——工具注册、ReAct 循环调用、结果返回
