---
name: wecomcli-meeting
description: 何时用:仅当用户明确指向企业微信『在线会议』(含会议号/入会链接、可远程参会)时使用;泛指约会默认先按消歧流程确认,纯日程走 wecomcli-calendar。企微会议全生命周期:创建、查询、搜索、详情(含纪要/待办)、转写原文逐字记录、更新、取消;仅说'开会/约个会'未明确类型时先追问确认,不可臆断直接创建。
metadata:
  requires:
    bins: ["wecom-cli"]
---

# 企业微信会议技能

> 执行任何 `wecom-cli` 命令前，必须先读取并完成 `wecomcli-shared` 技能的公共前置检查。

本 Skill 负责企业微信会议的全生命周期管理，包括创建、查询、搜索、取消会议，以及会议状态和参会人的管理。

**CRITICAL — 操作执行协议**（每次操作必须遵循）：
1. 识别用户意图对应的操作类型（创建/查询/搜索/取消）
2. **用 `File(action="read")` 读取该操作的参考文档**（见下方"操作参考"表）
3. 严格按照参考文档中的工作流和命令格式执行
4. 禁止跳过步骤 2 直接执行命令，即使你认为已经知道如何操作
   — 原因：每个操作的参数格式、可选字段和边界行为都在参考文档中精确定义，凭记忆操作极易因参数错误导致调用失败

## 适用范围

### 适用

- 创建 / 新建在线会议（含会议号 / 入会链接，可远程 / 视频参会；含"线下开 + 外地同事远程接入"的会）
- 查看 / 浏览会议列表（最近有什么会、查某时间段的会议）
- 搜索会议（按关键词、会议名找某个会议）
- 查看会议详情（主题、时间、参会人等）
- 更新 / 修改会议（改时间、加减人；不支持更新周期会议）
- 取消会议（不支持取消周期会议）

### 不适用

- 创建、更新、取消周期 / 重复会议（每周 / 每月 / 每天重复）→ 均不支持，引导用户在企业微信客户端手动操作
- 回复 / 拒绝会议邀请（接受 / 拒绝 / 待定，含"拒绝这个会""不参加"）→ 不支持，引导用户在企业微信客户端操作或私信发起人

### 易混淆场景路由

- 用户要的是**不含在线会议链接的日程 / 纯线下面对面碰头**（约日程、看今天有什么安排、安排纯线下会议）→ 改用 `wecomcli-calendar`
- 查忙闲 / 约多人共同空闲 → 改用 `wecomcli-calendar`
- 预订 / 查询公司会议室（订会议室、查会议室空不空、查办公楼）→ 会议室查询能力在 `wecomcli-calendar` 技能；创建/更新会议时若要订/换会议室，`读取 wecomcli-calendar 技能` 的会议室查询参考拿 `meeting_room_id` 传入本技能的 create/update
- 用户仅说"开会 / 约个会 / 安排个会 / xx 会"等、**未明确是日程还是在线会议**（创建场景）→ 必须先用文字追问消歧（固定问题"需要创建日程还是会议？"，请用户回复"日程 / 会议"），不得臆断直接创建
- **仅给了地点 / 会议室号**（如"在 1605 开会""订个会议室开会"）→ 不构成"明确是会议"，仍需先用文字询问消歧，不能因带地点就跳过追问
- **查询场景的模糊表述**（"最近有什么会 / 有哪些会"）→ 严禁追问，日程和会议都查并合并展示；仅当明确提到"在线会议 / 视频会议 / 入会链接 / 会议号 / 腾讯会议 / 远程参会"时才只查会议

## 路由规则

| 用户意图 | 参考文档 |
|---------|---------|
| 新建会议、开个会、安排视频会议 | [meeting-create](references/meeting-create.md) |
| 查会议、我的会议列表、最近有什么会、查某个时间段的会议 | [meeting-list](references/meeting-list.md) |
| 搜索会议、找某个会议、找上周的周会 | [meeting-search](references/meeting-search.md) |
| 查看会议详情、看看参会人 | [meeting-list](references/meeting-list.md) |
| 修改会议、更新会议、改个时间、加人/移除人 | [meeting-update](references/meeting-update.md) |
| 取消会议、不开了 | [meeting-cancel](references/meeting-cancel.md) |
| 查看会议转写原文、逐字记录、把会上说的原话发我、要转写/转录文字、第几段转写 | [meeting-original-get](references/meeting-original-get.md) |
| 总结会议 / 要会议纪要 / 这个会讲了啥 / 看会议待办 / 总结待办 | 见下方核心场景「7. 会议总结（纪要/待办）」，编排 [meeting-list](references/meeting-list.md) 的 get 与 [meeting-original-get](references/meeting-original-get.md) |
| 约日程、日程安排、看看今天有什么安排 | wecomcli-calendar 技能 |
| 查忙闲、看看某人什么时候有空 | wecomcli-calendar 技能 |
| 安排纯线下面对面会议（不含在线会议链接） | wecomcli-calendar 技能 |

> **技能边界（会议 vs 日程）[CRITICAL]**：本技能只创建**含在线会议链接的会议**（含会议号/入会链接，供远程/视频参会）。只要涉及在线会议链接就归本技能；不含在线会议链接的纯线下面对面会议属于日程，使用 `读取 wecomcli-calendar 技能`。用户仅说"会议/会/开个会/约个会/安排个会/xx会/xx会议"等而未明确是日程还是会议时，**必须先用文字追问**，禁止默认直接创建会议：
>
> **问题与选项固定 [CRITICAL]**：消歧确认时，问题与可选项都必须原文照用、严格禁止修改任何内容——问题固定为 `"需要创建日程还是会议？"`，可选项固定为 `日程` / `会议`；不得改写问题措辞、增减或改写选项、翻译，或自行设计其他表述（如"在线会议 / 线上会议 / 视频会议 / 线下会议"等）。
>
> 用文字向用户提问：`需要创建日程还是会议？（请回复：日程 / 会议）`
>
> 用户答「会议」→ 留在本技能创建会议；答「日程」→ 改用 `读取 wecomcli-calendar 技能` 创建日程。
>
> 此文字消歧仅用于「创建」；查询场景严格禁止追问——明确指向在线会议时只查会议，明确是日程/安排时只查日程，模糊表述（"会 / xx会 / 最近有什么会"等）则日程和会议都查（见下文「查询消歧」）。
>
> **"会议""会""开会"等词本身不构成"明确" [CRITICAL]**：这些词只表示要碰头议事，并未说明是日程还是会议。禁止仅因 query 里出现"会议"二字就默认归本技能（会议）创建，也禁止反向默认成日程——只要未明确，一律先用文字追问后再路由。只有出现"入会链接 / 会议号 / 视频会议 / 腾讯会议 / 远程参会"等明确信号时才直接归会议。
>
> **同时支持线下与远程参会**（如"线下开、外地同事远程接入"）时，因含在线会议链接，归本技能创建——创建会议会同时生成对应日程，无需再去 wecomcli-calendar 技能另建日程。
>
> **仅有地点/会议室号**（如"在 1605 开会""到 A 座会议室碰一下""订个会议室开会"）不构成"明确是会议"——会议室里同样可能只是纯线下安排，是日程还是会议仍未知，必须先用文字询问消歧，不能因为带了地点就跳过追问。

> **list vs search 的选择原则**：用户明确提到主题/名称关键词时用 `search`（把关键词传入 `keywords`）；只按时间范围或泛浏览时用 `list`，禁止把日期当 `keywords` 喂给 `search`。两者有时可组合：先search 定位，再 list 确认时间段全貌。

> **查询消歧（模糊查询时日程 + 会议都查）[REQUIRED]**：查询场景严格禁止用文字追问"是日程还是会议"——日程/会议消歧追问仅用于创建，查询时一律按以下规则直接处理、不追问。**判定分两个独立维度，不要混为一谈**：
>
> **维度一：查哪一边（日程 / 会议 / 两边都查）**
> - **明确是在线会议** → 用户明确提到"在线会议 / 视频会议 / 入会链接 / 会议号 / 腾讯会议 / 远程参会"等在线会议专属特征时，留在本技能只查会议。
> - **明确是日程 / 安排** → 用户说的明显是日程类内容（如"日程 / 安排 / 我的安排 / 日历"，且不带在线会议特征）时，改用 `读取 wecomcli-calendar 技能` 只查日程。
> - **模糊表述无法判定**（"会 / xx会 / xx会议 / 开会 / 最近有什么会 / 有哪些会 / 找下 xx会议"等，既可能是日程也可能是会议）→ **日程和会议都要查**：既用本技能查会议，又 `读取 wecomcli-calendar 技能` 查日程。
>
> **维度二：每一边用 `search` 还是 `list`（与维度一独立，逐边各自判断）**
> - **有主题/名称关键词**（如"找下 xx会议""搜一下项目评审会议"）→ 该边用 `search`（把关键词传入 `keywords`）。
> - **只有时间/日期或泛浏览无关键词**（如"最近有什么会""查一下明天的会议"）→ 该边用 `list`，禁止把日期当 `keywords` 喂给 `search`。
> - 即使"两边都查"，也按本维度对每一边各自选择：带关键词时两边都用 `search`，纯时间/泛浏览时两边都用 `list`。
>
> **合并展示**：两边都查时，合并结果后统一展示——按是否含在线会议链接分成「（会议）」（来自会议侧、或日程中 `meeting.meeting_code` 非空者）和「（日程）」（`meeting_code` 为空的纯日程）两部分，同一场会议在两边都出现时按"主题 + 时间"去重只保留一条，末尾汇总"共 N 场，其中会议 X 场、日程 Y 场"。
>
> - 本消歧仅针对查询；创建仍按下文"日程 vs 会议"用文字追问。

**触发表达示例**：
- "帮我开个会" / "安排一场会议" / "创建视频会议"
- "看看我的会议" / "查一下明天的会议" / "最近有什么会"
- "搜一下项目评审会议" / "找找上周的周会"
- "取消那个会议" / "这个会不开了"
- "帮我总结下 xx 会议" / "这个会讲了啥" / "把 xx 会议纪要发我" / "看下这个会的待办" / "按决策点整理下这个会"

## 前置条件

- 需要企业微信账号且已登录
- 取消/更新操作不预先按"是否本人创建"拦截，由接口返回结果判断能否操作（取消前另须按规则 2 复述会议主题与时间并获确认）
- 参会人 userid（前缀为 `wo`）组装为 `[{"userid": "woxxx"}]` 对象数组格式传入；用户提供的是姓名时通过 `读取 wecomcli-contact 技能` 解析为 userid

## 核心场景

### 1. 新建会议

以当前用户为发起人创建一场新会议。

**CRITICAL — 执行前必须先读取参考文档**：收到创建会议意图后，第一步立即读取 [`meeting-create`](references/meeting-create.md)，按其中的完整工作流（参数补全 → 参会人解析 → 参会人忙闲检查 → 调用创建接口 → 获取详情展示）逐步执行，禁止在未读取参考文档的情况下直接发起任何操作。

> **参会人忙闲检查 [REQUIRED]**：创建 / 更新会议时须在时间敲定前查忙闲，避免约到冲突时间。忙闲接口不在本技能，须 `读取 wecomcli-calendar 技能` 的 [忙闲查询参考](../wecomcli-calendar/references/calendar-freebusy.md) 调`free list`。**创建会议时**：查询对象 = 当前用户自己 + 其他内部参会人（`wo` 前缀），**只有自己也要查**（避免约到自己已占用的时段）；外部联系人（`wm`，忙闲不可查）不纳入查询对象、但**不因此跳过**整体检查；仅忙闲接口调用失败时降级放行。**给已有会议加人、不改时间时**：忙闲查询只针对**新增参会人**、且查会议原时段，禁止把当前用户（自己/创建者）和已有参会人纳入——他们正被本会议占用、必然显示"忙"，纳入会误报冲突（详见 [meeting-update](references/meeting-update.md) 工作流）。

> **会议室预订 [REQUIRED]**：用户创建会议时提到"订会议室 / 在 1605 开 / 找个会议室 / 某栋楼的会议室"等意图时，会议室查询能力不在本技能——须 `读取 wecomcli-calendar 技能` 的 [会议室查询参考](../wecomcli-calendar/references/calendar-meeting-room.md)（`buildings list` + `rooms search`）查到真实会议室，拿 `meeting_room_id` 传入 `meeting create`（占用）。禁止把会议室名仅写进 `location`、禁止凭记忆/猜测编造 `meeting_room_id`；先订房后建会，详见 [meeting-create](references/meeting-create.md) 步骤 4。

> 详见 [meeting-create](references/meeting-create.md)

### 2. 查询会议列表

**CRITICAL — 执行前必须先读取参考文档**：收到查询会议列表意图后，第一步立即读取 [`meeting-list`](references/meeting-list.md)，按其中的完整工作流（时间范围确定 → 拉取列表 → 批量获取详情 → 反查参会人姓名 → 合并输出）执行，禁止在未读取参考文档的情况下直接发起任何操作。

> **模糊查询必须日程 + 会议都查 [CRITICAL]**：若本次是"会 / xx会 / xx会议 / 最近有什么会 / 有哪些会 / 找下 xx会议"等模糊查询（见上文「查询消歧」），无论会议列表是否查到结果，都必须同时 `读取 wecomcli-calendar 技能` 用相同时间范围拉日程 `list`，把两边结果合并、按是否含在线会议链接分「（会议）」「（日程）」两部分汇总展示（同一场会议按主题 + 时间去重），禁止因会议已查到就跳过日程查询。仅当用户**明确指向在线会议**（入会链接 / 会议号 / 视频会议 / 腾讯会议 / 远程参会等）时才只查会议；此时若查无，再兜底去日程查一把（命中则说明「这是一条日程」，两边都无再告知）。

> 详见 [meeting-list](references/meeting-list.md)

### 3. 搜索会议

根据关键词匹配会议主题或内容。有关键词时不执行特定追问操作补全时间，直接搜索。适合用户知道会议名称或关键词的场景。

> **模糊搜索必须日程 + 会议都搜 [CRITICAL]**：若用户搜的是"会 / xx会 / xx会议"等模糊目标（非明确在线会议），无论会议是否搜到，都必须同时 `读取 wecomcli-calendar 技能` 用同样关键词搜日程，把两边结果合并分「（会议）」「（日程）」汇总展示；仅当**明确指向在线会议**时才只搜会议，此时搜不到再兜底去日程搜（命中则说明「这是一条日程」，两边都无再告知）。

> 详见 [meeting-search](references/meeting-search.md)

### 4. 取消会议

**CRITICAL — 执行前必须先读取参考文档**：收到取消会议意图后，第一步立即读取 [`meeting-cancel`](references/meeting-cancel.md)，按其中的完整工作流（定位会议 → 状态检查 → 周期判断 → 复述主题与时间并获确认 → 执行取消 → 按返回结果判断）执行，禁止在未读取参考文档的情况下直接发起任何操作。

> 详见 [meeting-cancel](references/meeting-cancel.md)

### 5. 更新会议

**CRITICAL — 执行前必须先读取参考文档**：收到更新/修改会议意图后，第一步立即读取 [`meeting-update`](references/meeting-update.md)，按其中的完整工作流（定位会议 → 周期判断 → 参数收集 → 执行更新 → 按返回结果判断）执行，禁止在未读取参考文档的情况下直接发起任何操作。

> 详见 [meeting-update](references/meeting-update.md)

### 6. 查询会议转写原文

**CRITICAL — 执行前必须先读取参考文档**：收到查询会议转写原文（"原话/逐字记录/完整对话/转写/转录/第几段"等）意图后，第一步立即读取 [`meeting-original-get`](references/meeting-original-get.md)，按其中的完整工作流（定位会议 → 确定段落 → 拉取转写 → 翻页拼接 → 原样输出）执行，禁止在未读取参考文档的情况下直接发起任何操作。

> **转写原文 ≠ 智能纪要 [CRITICAL]**：转写原文（`original_data`，逐句原始发言）与 `meeting get` 里 AI 总结的 `notes`（纪要/待办）是两种不同内容，禁止用纪要替代转写原文。**`media_index` 默认不传**——不传时接口返回全部段转写，仅当用户明确要"第 N 段"时才传 `N-1`（从 0 开始），不主动追问要哪一段。`has_more` 为 true 时必须翻页到底并按序拼接，输出时**原样保留**时间戳+说话人的逐行格式，不总结、不裁剪。

> 详见 [meeting-original-get](references/meeting-original-get.md)

### 7. 会议总结（纪要 / 待办）

用户要"总结某场会议"——包括要**会议纪要**、问"这个会讲了啥"、要**会议待办**、"总结下待办"等，本质是对已有的 `meeting get`（现成纪要/待办）与 `meeting original get`（转写原文）两个接口做**编排**，没有新接口。**纪要与待办同属此逻辑**，处理方式一致。

**CRITICAL — 执行前必须先读取参考文档**：先按 [`meeting-list`](references/meeting-list.md) 定位会议并（无自定义要求时）取 `get`；需回到原文加工时读取 [`meeting-original-get`](references/meeting-original-get.md)。

**唯一分叉维度：本次总结是否带「自定义要求 / 描述」**

**只要用户在"总结"之外附带了任何自定义的要求、描述、角度、范围、结构或风格，一律走原文生成**；**只有纯粹地说"总结下 / 讲了啥 / 纪要发我 / 看待办"、不带任何额外描述时，才返回已有的现成内容**。

- **只说"总结下"（无任何自定义描述）**：仅泛泛地要一份总结/概要/待办，没有附加任何要求。触发语如"总结下 xx 会""这个会讲了啥""纪要发我""看下这个会的待办""有哪些待办"。
  1. 先调 `meeting get`，取目标字段：要纪要 → 看 `notes[].note_content`；要待办 → 看 `notes[].todo_content`。
  2. **可用则直接返回官方现成内容**（判定：`has_note_permission == true` 且目标字段有实质内容），无需再调用转写原文接口。
  3. **不可用**（目标字段空 / `has_note_permission == false`）→ 转下方原文兜底。
- **带了任何自定义要求 / 描述**：只要用户附加了结构、角度、聚焦范围、风格或长度等任意描述，就归此类。触发语如"按决策点整理""用三段式""列出每人发言重点""重点讲预算那部分""写成正式会议纪要""一句话概括""结合上次的会说说进展"等。
  - **跳过 `get`，直接 `meeting original get` 拉全部转写**，按用户的要求/描述加工总结。理由：官方 `notes` 是固定视角的成品，满足不了任何定制诉求，必须回到原文重新加工。

**原文兜底顺序 [REQUIRED]**：凡需要走原文（get 不可用，或带自定义要求），一律先调 `meeting original get`（翻页到底），再按结果处理：
- 接口报错（无权限/其他）→ 按接口返回如实提示，不静默失败。
- 成功但 `original_data` 为空 → 告知"该会议暂无智能纪要，也没有转写原文（可能未开启会议转写、会议未开始或无发言记录）"，不编造。
- 成功且有内容 → 按默认或用户指定的结构总结（此时 `original get` 允许加工总结，区别于"要原话/逐字记录"时的原样输出）。

> 详见 [meeting-list](references/meeting-list.md)（定位 + get）与 [meeting-original-get](references/meeting-original-get.md)（拉原文并加工）。

## 核心概念

- **会议（Meeting）**：企业微信会议实体，含主题、起止时间、参会人、入会链接等属性。
- **会议 ID（meeting_id）**：API 使用的会议唯一标识，较长的字符串（`mt` 前缀）。
- **会议号（meeting_code）**：9 位纯数字，仅用于用户入会，不能作为 meeting_id 使用。
- **周期会议（Recurring）**：按规则重复的会议，`update`/`cancel` 均不支持（见「已知限制」）；`original get` 与 `meeting get` 查询周期会议的某一场时均需指定 `sub_meeting_id`。
- **参会人（Attendee）**：以 userid（`wo` 前缀）标识。用户提供的是姓名时通过 `读取 wecomcli-contact 技能` 解析为 userid。

## 核心规则

### 规则 1: userid 获取

- `attendees` 字段格式为 `[{"userid": "woxxx"}, {"userid": "woyyy"}]` 对象数组，不接受姓名，不接受平铺字符串数组。
- 用户提供的是姓名时，通过 `读取 wecomcli-contact 技能` 解析为对应 userid；多候选人时用文字让用户选择，不自行猜测。
- **禁止**把姓名当 userid 拼接，**禁止**凭记忆或猜测编造 userid。
- `open_vid` 和 `userid` 是同一概念的不同叫法，其他系统返回的 `open_vid` 可直接作为 `userid` 使用。

### 规则 2: 写操作执行口径

- 创建会议时，参数就绪后直接执行，无需向用户展示摘要或询问确认。
- 取消会议前向用户复述会议主题与时间并获确认；参数就绪后执行。
- 结果返回时**禁止暴露 userid**，只展示人名。
- **原因**：创建类操作的信息已在上层交互完整展示并确认，执行阶段再复述一遍冗余；取消会议属破坏性操作，复述主题与时间并获确认可防止误取消；userid 是系统内部标识，对用户没有实际意义，展示反而容易造成困惑。

### 规则 3: 参数补全

任何操作中，当必要参数不明确或需要用户做出选择时，**必须用文字直接向用户提问**，禁止自行猜测或使用默认值代替询问。提问时把可选项 / 候选值一并写进文字里，让用户直接回复。

以下情况均适用此规则：

- **必填参数及参会人缺失**：操作所需的参数无法从上下文中推断（如创建会议时 `subject`/`begin_time` 缺失、参会人 `attendees` 缺失、搜索时 `keywords` 缺失）时必须用文字询问；其余非必填参数（地点、会议室等）用户未明确指定时不追问，走默认值；`end_time`（时长）缺失时不追问，默认时长 1 小时（`begin_time + 1h`）；仅描述参会方式或动作的词（如「视频会议 / 开个会 / 远程接入」）不构成有效 `subject`，按缺失处理走文字询问，禁止当主题直接创建
- **多候选项需用户选择**：搜索/查询返回多个匹配项、wecomcli-contact 技能搜索到多个同名候选人
- **操作范围需确认**：如更换会议室时查到多个 bookable 候选，需用户选定具体一个

**文字询问的约束**：
- 列出的可选项 / 候选建议以 **2~4 个**为宜。可选候选多于 4 个时（如同名候选人、多个匹配会议），取最相关的前 4 个列出，并提示用户可进一步缩小范围（输入更精确的关键词 / 完整姓名 / 具体时间），不要一次性罗列 5 个及以上候选。
- **询问时间时，列出的候选时刻必须是精确到分钟的具体时刻**（如"明天 14:00"、"后天 09:30"），禁止给出"上午/下午/傍晚/午间/上班后/下班前"等模糊时间选项——模糊选项会导致用户回复后仍需二次追问具体几点，必须一次问到可直接落为 `begin_time` 的精确时刻。

各场景具体的提问话术和候选项见对应操作的参考文档。

### 规则 4: 权限判定交给接口

- 取消 / 更新会议不预先按"是否本人创建"拦截，也不区分 `created_meetings` / `attended_meetings`——由接口返回结果判断能否操作（取消前另须按规则 2 复述会议主题与时间并获确认）。
- 返回成功即操作完成；返回权限类错误则说明当前用户无权操作该会议，告知用户并建议联系会议发起人。

### 规则 5: 输入安全处理

- 用户提供的是姓名时，必须经过 `读取 wecomcli-contact 技能` 搜索验证后才能转换为 userid。**禁止**把姓名直接拼接为 userid，**禁止**凭记忆或猜测编造。原因：用户输入的字符串可能不对应真实员工（姓名不唯一、已离职等），直接拼接会导致将消息发送给错误的人或创建出包含无效参会人的会议，且此类错误无法被 API 在调用时拦截。

### 规则 6: 错误重试上限

- 同一操作失败后，最多重试 **2 次**。两次重试后仍失败，停止自动操作，向用户输出完整的错误诊断信息，等待人工介入。
- 不同错误类型应用不同策略：网络超时可重试，权限不足/参数错误不应重试（重试无效）。

> **长期记忆原则**：用户的常用参会人组合（如"产品团队"= 张三+李四）等个性化信息，在首次明确后应在当前会话内记忆，减少重复追问。如果当前会话不支持跨会话持久记忆，则在本次会话内保持记忆；会话结束后偏好清空，下次使用时重新澄清即可。（会议时长不在此列：用户未指定时一律默认 1 小时、不追问、也无需记忆时长偏好。）

## CLI 调用格式

```bash
wecom-cli meeting [action] --json '{"key": "value"}'
```

- `meeting action`：`create`、`list`、`get`、`search`、`cancel`、`update`、`original get`
- `--json`：JSON 参数，用**单引号**包裹

## 操作参考

操作参考文档是对常用操作的详细说明。**执行操作前务必先读取对应文档。**

| 操作参考 | 说明 |
|----------|------|
| [`meeting-create`](references/meeting-create.md) | 创建会议并确认详情 |
| [`meeting-list`](references/meeting-list.md) | 查询会议列表（list + get） |
| [`meeting-search`](references/meeting-search.md) | 按关键词搜索会议 |
| [`meeting-cancel`](references/meeting-cancel.md) | 取消已创建的会议 |
| [`meeting-update`](references/meeting-update.md) | 更新已创建会议的信息（主题、时间、参会人、地点等） |
| [`meeting-original-get`](references/meeting-original-get.md) | 查询会议转写原文（逐句原始发言，区别于纪要） |

## 上下文传递表

| 操作 | 从返回中提取 | 用于 |
|------|-------------|------|
| `search` | `meetings[].meeting_id` | `get` 查详情、`cancel` 取消会议 |
| `list` | `created_meetings[].meeting_id` / `attended_meetings[].meeting_id` | `get` 查详情、`cancel` 取消会议 |
| `search` | `meetings[].meeting_id`（周期会议加 `meetings[].sub_meeting_id`） | `original get` 拉取会议转写原文、`meeting get` 获取周期会议某场详情 |
| `list` | `created_meetings[].meeting_id` / `attended_meetings[].meeting_id`（周期会议加对应 `sub_meeting_id`） | `original get` 拉取会议转写原文、`meeting get` 获取周期会议某场详情 |
| `list` | `created_meetings` / `attended_meetings` | 展示会议列表时区分"我创建的"与"我参加的"（不用于取消/更新的权限判断） |
| wecomcli-contact 技能搜索 | `userid`（`wo` 前缀） | `create` 的 `attendees` 数组 |
| `get` | `meeting_status` | 判断会议状态（`"init"` / `"started"` / `"end"`） |
| `get` | `repeat_rule` | 判断是否周期会议（非空即周期会议）：命中时 `cancel`/`update` 均不支持，告知用户并引导企业微信客户端操作 |
| `create` | `meeting_id` | 会议唯一标识 |
| `search` / `list` + `get` | 会议 ID（search 取 `meetings[]`、list 取 `created_meetings[]`/`attended_meetings[]`）、`repeat_rule` | `update` 的定位与周期会议判断（命中周期会议则不支持更新） |

## 错误处理

> 原则：告诉用户**出了什么问题** + **可以怎么做** + **备选方案**。禁止静默失败。最多重试 2 次，超出后停止自动操作。

| 错误场景 | 可能原因 | 恢复建议 |
|---------|---------|---------|
| 接口返回权限不足（非发起人取消/修改） | 当前用户非会议发起人 | 由接口返回判断（取消前另须按规则 2 复述确认）；返回权限错误时告知用户无权操作，建议联系会议发起人；不重试 |
| 时间校验失败 | `begin_time` 早于当前时间 | 提示用户重新选择未来的时间点；不重试，等待用户修正 |
| 参数格式错误（meeting_id） | meeting_id 误传 9 位会议号 | 检查 ID 来源：[正确] `"meeting_id": "mtkSFfCgNxxxxxxx"`（长字符串）；[错误] `"meeting_id": "123456789"`（9 位会议号是 meeting_code，不能作为 meeting_id）；不重试 |
| 参数格式错误（attendees） | attendees 格式不正确 | 检查格式：[正确] `"attendees": [{"userid": "woxxx"}]`；[错误] `"attendees": ["woxxx"]`（不接受平铺字符串数组）或 `"attendees": ["张三"]`（不接受姓名）；用户提供的是姓名时通过 `读取 wecomcli-contact 技能` 解析为 userid |
| 搜索/列表无结果 | 时间范围或关键词不匹配；**或用户找的「会」其实是日程而非含在线会议链接的会议** | 先建议扩大时间范围或修改关键词重试；同时**主动 `读取 wecomcli-calendar 技能` 用同样关键词在日程里搜一把**（企微里「会」有「含在线会议链接的会议」和「日程」两种载体，团队聚一起的会常落在日程而非会议），命中则一并呈现并说明「这是一条日程」，仍无果再告知两边都没有 |
| 网络超时 | 网络不稳定 | 等待后重试，最多 2 次；2 次后提示用户稍后再试 |
| 连续 2 次失败 | 根因未知或持续性问题 | 停止自动重试，输出完整错误信息，建议用户联系管理员或手动操作 |

## 输出质量标准

好的输出应满足以下条件：
- 会议列表：每条只展示主题、时间、参会人姓名三项（不含状态标签、参会人数、地点、会议号、入会链接等），按开始时间升序排序，详见下方「会议列表展示规范」
- 参会人展示：原样使用接口返回的 `attendees[].name` 字段（完全与接口返回的格式保持一致，如返回 `zhangsan(张三)` 就展示 `zhangsan(张三)`），不展示 userid
- 会议详情：含关键字段（主题、时间、参会人姓名；不展示会议号、入会链接）
- 操作结果：明确告知成功/失败及原因，操作成功后展示最新状态

不可接受的输出：
- 直接展示 userid 而非姓名
- 遇到错误静默失败，不给用户任何提示

## 输出格式规范

**参会人姓名格式 [REQUIRED]**：所有展示参会人的场景（创建反馈、列表、单条详情等），姓名一律**原样使用接口返回的 `attendees[].name` 字段**，完全与接口返回的格式保持一致（如返回 `zhangsan(张三)` 就展示 `zhangsan(张三)`）；下文模板中的 `{人名}` 均指该原样 name。

**时间年份显示 [REQUIRED]**：下文"时间"行默认省略年份、只到月日（模板中的 `{M月D日}`）；仅当会议年份与当前年份不同（跨年）时，才在月日前补上年份，格式为 `{YYYY}年M月D日 {HH:mm}-{HH:mm}`。

**相对日期标签 [REQUIRED]**：当会议日期为昨天 / 今天 / 明天时，"时间"行在月日前加上相对词，格式 `{昨天|今天|明天} M月D日 {HH:mm}-{HH:mm}`（如 `时间：明天 6月11日 14:00-15:00`）；其余日期按 `{M月D日} {HH:mm}-{HH:mm}` 展示。

**创建成功反馈 [REQUIRED]**：创建会议成功后，输出内容只包含三部分：主题、时间、参会人，禁止输出其他任何内容和额外语句（不展示地点、会议室、会议号、入会链接、meeting_id 等字段，也不附加说明、建议或寒暄）：
```
主题：{subject}
时间：{M月D日} {HH:mm}-{HH:mm}
参会人：{人名1}、{人名2}
```

**会议列表展示规范 [REQUIRED]**（列表/搜索浏览均适用）：
- **禁止使用 markdown 表格**；每条会议作为独立条目顺序输出，按开始时间升序排序。
- 每个条目 **只展示三项：主题、时间、参会人**（不展示状态标签、参会人数、地点、会议号、入会链接等）。
- **超过 10 条时只展示前 10 条**，并在末尾告知"还有 N 条，需要查看更多吗？"。
- 参会人姓名取 `meeting get` 返回的 `attendees[].name`；只需对要展示的前 10 条调用 `meeting get` 反查，禁止展示 userid。
- 单个条目格式：
```
1. {subject}
   时间：{M月D日} {HH:mm}-{HH:mm}
   参会人：{人名1}、{人名2}

2. {subject}
   时间：{M月D日} {HH:mm}-{HH:mm}
   参会人：{人名1}、{人名2}
```

**单条会议详情**（查看单条会议详情时，可展示完整字段）：
```
- 主题：{subject}
- 时间：{M月D日} {HH:mm}-{HH:mm}
- 参会人：{人名1}、{人名2}（禁止展示 userid）
- 地点：{location}（如有）
```

**时区标注 [REQUIRED]**：会议 `timezone.timezone_offset != 28800`（非东八区）时，展示时间必须带时区标注，格式 `{HH:mm}-{HH:mm}（{地区中文名} UTC±N）`，如 `14:00-15:00（纽约时间 UTC-5）`。
- `UTC±N` 由 `timezone.timezone_offset / 3600` 得出。
- 地区中文名由 `timezone.timezone_id` 推导（如 `America/New_York` → 纽约时间）；`timezone_id` 为空时省略中文名，只留 `（UTC-5）`。
- 东八区（`timezone_offset = 28800`，含 `Asia/Shanghai`、`Asia/Singapore` 等）不标注，保持现状。
- 适用于创建反馈、会议列表、单条详情的"时间"行；跨时区改动 `timezone` 后的更新反馈同样适用。

> **禁止展示会议号 / 入会链接 [REQUIRED]**：任何场景（创建反馈、列表、搜索、单条详情等）都**不展示会议号（`meeting_code`）和入会链接（`meeting_link`）**。

## 已知限制

| 限制 | 替代方案 |
|------|---------|
| **不支持创建/更新/取消周期（重复）会议** | 用户希望创建"每周/每月/每天重复"等周期会议，或对已识别为周期会议（`repeat_rule` 非空）的会议发起更新、取消时，均直接告知用户目前不支持，并引导用户在企业微信客户端手动操作；禁止用批量创建多条单次会议、传入未公开参数等方式变通绕过 |
| **不支持回复 / 拒绝会议邀请（RSVP）** | 本技能不支持对收到的会议邀请做接受 / 拒绝 / 待定等回复（含"拒绝这个会""不参加""婉拒邀请"等）。用户有此需求时，告知其本技能不支持，建议直接在企业微信客户端对该会议邀请操作，或通过消息告知会议发起人 |
| **参会人上限 100 人** | `attendees` 数组不超过 100 个 userid |
| **时长上限 24 小时** | `begin_time` 与 `end_time` 间隔不超过 24 小时。出现超 24h 的单场会议需求时，直接告知不支持并拒绝，禁止自行拆分成多场会议或变通绕过；用户确需多天安排时，由其明确拆分要求后再分别创建 |
| **批量查询上限 10 个** | `meeting get` 单次最多 10 个 meeting_id，超出必须分批多次调用（按每批 ≤ 10 切分，再合并结果） |
| **list 不含 meeting_status** | 需额外调用 `meeting get` 才能获取会议状态 |

## 快速参考

### 接口对比

| 功能 | meeting create | meeting list | meeting get | meeting search | meeting cancel | meeting update | meeting original get |
|------|---------------|-------------|------------|---------------|---------------|----------------|----------------------|
| 用途 | 创建会议 | 查询会议列表 | 获取会议详情 | 按关键词搜索会议 | 取消会议 | 更新会议信息 | 查询会议转写原文 |
| 前置依赖 | 需先获取 userid | 无 | 需先 list/search 拿到 meeting_id | 无 | 需先确认 meeting_id | 需先确认 meeting_id | 需先 list/search 拿到 meeting_id |

### 参数速查表

| 接口 | 核心参数 |
|------|---------|
| `meeting create` | `subject`（必填）、`begin_time`（必填）、`end_time`（必填）、`attendees`（对象数组 `[{"userid": "woxxx"}]`）、`location`（地点文本；会议室须走 `meeting_room_id`，非会议室文本才只写 `location`）、`meeting_room_id`（会议室 ID，订会议室时传，来自 `读取 wecomcli-calendar 技能` 的会议室查询）、`description`、`timezone`（格式 `{"timezone_id": "Asia/Shanghai", "timezone_offset": 28800}`） |
| `meeting list` | `begin_time`、`end_time`（均选填，须同时传入或同时省略）、`cursor`、`limit` |
| `meeting get` | `meeting_ids`（必填，对象数组，格式 `[{"meeting_id": "xxx"}]`，**单次最多 10 个**，超出需分批多次调用；周期会议需加 `sub_meeting_id`） |
| `meeting search` | `keywords`（必填，字符串数组）、`begin_time`、`end_time`、`cursor`、`limit`（固定传 `20`）；`keywords` 可匹配会议主题、参会人姓名、会议纪要内容、会议室名称等信息 |
| `meeting cancel` | `meeting_id`（必填）；不支持取消周期会议 |
| `meeting update` | `meeting_id`（必填）、`subject`、`begin_time`、`end_time`、`add_attendees`/`remove_attendees`（对象数组 `[{"userid": "x"}]`）、`location`（地点文本；会议室须走 `meeting_room_id`）、`meeting_room_id`（更换会议室时传，须先经 `rooms search` 确认 `status=bookable`）、`description`；不支持更新周期会议 |
| `meeting original get` | `meeting_id`（必填，`mt` 长字符串）、`sub_meeting_id`（周期会议某场时传）、`media_index`（第几段，从 0 开始，**默认不传返回全部段**，仅用户明确指定"第 N 段"时传 `N-1`）、`cursor`、`limit`（默认 100，上限 500） |
