# 群聊与消息

## 能做什么

| 场景 | 状态 |
| --- | --- |
| 发单聊 / 群消息 | ✅ |
| 撤回自己发的消息 | ✅ |
| 建群、群成员管理、群昵称 | ✅ |
| 会话分组管理 | ✅ |
| 机器人查询、机器人群发 | ✅ |
| Webhook 通知 | ✅ |
| 话题回复、收藏消息、@消息 | ✅ |
| 发送/下载消息图片与文件 | ✅ |
| **搜索聊天记录、@我汇总、拉历史消息** | ⚠️ **需要「消息搜索」权益** |

## 一个必须知道的限制：消息搜索是单独权益

真机实测，未开通时返回：

```json
{
  "server_error_code": "SearchRightsDenied",
  "message": "当前用户暂无消息搜索权益，无法执行本次搜索。请提示用户开通消息搜索权益后重试。",
  "category": "api",
  "reason": "business_error"
}
```

**助手的行为**（实测用例 a4）：识别出这是**权益问题**而非权限配置问题，如实告诉你需要开通，并说明**哪些 chat 能力仍然可用**。它不会换个命令硬试，也不会把整个 chat 域报成不可用。

这是设计上的硬规则——降级时必须区分四种失败态（没装 / 没授权 / 没权限或权益 / 网络不可达），每种给出不同的下一步。

## 实际用法

### 查可用机器人

```
我这边有哪些可用的机器人？
```

真机实测助手的探索过程（6 条命令）：

```bash
dws schema --cli-path "dev +list-bots" --compact --format json
dws dev --help
dws dev app --help
dws schema --cli-path "dev app list" --compact --format json
dws dev app robot --help
dws dev app list --page-size 30 --format json
```

最终回答：**「当前组织下没有查询到可用机器人（应用列表为空，且已确认分页结束）。」**

> 注意「**且已确认分页结束**」这半句。助手的纪律是：只有拿到 `data.complete=true` 才能说「全部/没有」，响应里缺少集合**不能**当空结果。这样你不会被一个假的"没有"误导。

### 发消息

```
给某某发条消息说「会议改到下午三点」
```

助手会：解析收件人 → **把要发给谁、发什么完整列给你** → 等你确认 → 才发送 → 回读验证。

**对外发消息是不可逆的，没有明确确认绝不发送。** 多人时逐个列出，不群发。

### 撤回

```
把刚才那条消息撤回
```

走 `chat +messages-recall`。

> **文档纠错**：钉钉官方的 `capability-limits.md` 写「无法通过 API 撤回」，这是**错的**（或已过时）。实测 `dws chat --help` 里存在 `+messages-recall`（撤回当前用户发送的消息）、`+messages-recall-by-bot`、`+messages-batch-recall-by-bot`，另有 `ding +recall-personal`。

## 通道选择

| 你想要 | 走哪 |
| --- | --- |
| 钉钉会话里的普通消息 | `chat` |
| 邮件 | `mail` |
| 强提醒（应用内 / 短信 / 电话） | `ding` —— 会响铃、发短信、打电话 |

**`ding` 是强打扰**，除非你明确说「紧急」，助手默认用 `chat`。
