钉钉群聊消息专用 skill。查询/获取/发送群消息、按群名搜索群、把机器人加入现有群、拉取今日或指定日期群记录时必须加载(群聊场景优先于 dws-cli)。 触发示例:获取群消息、帮我获取群、查群、群:、今天的消息、群聊记录、发送群消息、把机器人加进群、添加机器人到群、dws-chat。 用户只提供群名时禁止索...
---
name: dws-chat
description: |
钉钉群聊消息专用 skill。查询/获取/发送群消息、按群名搜索群、把机器人加入现有群、拉取今日或指定日期群记录时必须加载(群聊场景优先于 dws-cli)。
触发示例:获取群消息、帮我获取群、查群、群:、今天的消息、群聊记录、发送群消息、把机器人加进群、添加机器人到群、dws-chat。
用户只提供群名时禁止索要 groupId/openConversationId,须先 chat search 解析群再拉消息。
命令入口:skills/dws-chat/scripts/dws_agent.py;未登录须 get_device_auth_link.py 发设备授权链接(禁止让用户自行 dws auth login);禁止裸 dws。
---
# dws-chat — 钉钉群聊消息 Skill
本 skill 自包含于各 agent 的 `{workspace}/skills/dws-chat/`。多 agent 凭证隔离**只**通过 `scripts/dws_agent.py` 实现。
- **用户使用指引** → [`references/user-guide.md`](./references/user-guide.md)
- 凭证隔离原理 → [`references/isolation.md`](./references/isolation.md)
- 安装 / 一次性清理 / 跨平台 → [`references/install.md`](./references/install.md)
- 命令详细参数 → [`references/dws-chat-commands.md`](./references/dws-chat-commands.md)
- 命令权威来源 → `python3 skills/dws-chat/scripts/dws_agent.py <cmd> --help`
## 触发与分工
收到下列任一表述时,**必须先 read 本 SKILL.md**,不要先纯文字追问。
| 场景 | 用户说法(不限于) |
|------|------------------|
| 查消息 | 获取群消息、查群、今天的消息、群聊记录、看看群里 |
| 带群名 | `群:{名称}`、`{名称}群 今天的消息` |
| 发消息 | 往群里发、发送到群、群通知 |
| 机器人入群 | 把机器人加到群、添加机器人到群、机器人进群 |
| 点名 skill | 用 dws-chat、dws chat skill |
**与 `dws-cli` 的分工**:群聊 / IM(查历史、搜群、发消息、搜机器人、机器人入群)走本 skill;表格/日历/审批等仍用 `dws-cli`。
## 标准执行顺序
```
1. read 本 SKILL.md(若未加载)
2. dws_agent.py auth status -f json
3. 未登录 → get_device_auth_link.py → 按「未登录回复模板」发链接 → 结束
4. 已登录 → 按「常见任务」执行命令
```
未登录时**禁止**执行 `chat` / `message send` 等业务命令;**禁止**仅文字提示用户跑 `dws auth login`。
## 未登录回复模板(强制)
`auth status` 出现 `authenticated: false` / `token_valid: false` / 任何「未登录」字样时:
1. **下一条** tool call:`python3 skills/dws-chat/scripts/get_device_auth_link.py`
2. 从输出 `---DWS_DEVICE_AUTH---` 块解析 `verification_url`、`user_code`(合法 URL 含 `login.dingtalk.com/oauth2/device/verify.htm?user_code=`,**禁止** `open.dingtalk.com`,禁止编造)
3. 照下方格式发给用户,结束本轮:
```
还未登录,无法访问群聊数据。同时生成了新的授权链接,请完成钉钉授权:
授权地址:{verification_url}
授权码:{user_code}
请在 15 分钟内打开链接完成授权,完成后回复「已授权」。
完成后我将继续为你{待办说明}。
```
`{待办说明}` 填用户原诉求(如:拉取「dws测试群」今天的消息)。用户回「已授权」后再次 `auth status`,成功则继续被打断的步骤。
## 常见任务
> 命令均通过 `dws_agent.py` 执行(下文省略前缀 `python3 skills/dws-chat/scripts/dws_agent.py`)。flag 详情以 `<cmd> --help` 与 [`references/dws-chat-commands.md`](./references/dws-chat-commands.md) 为准。
### A. 按群名查群消息(默认流程,禁止索要 groupId)
```
1. chat search --query "<群名>" → 取 openConversationId
2. 按下表选 --time / --forward → chat message list
3. 汇总回复(发送人 / 时间 / 正文)
```
| 用户诉求 | 推荐参数 |
|----------|----------|
| 今天 / 指定日期之后的消息 | `--time "<YYYY-MM-DD> 00:00:00" --forward --limit 100`(**必须**带 `--time`) |
| 最近 N 条(不限时间) | `--forward=false --limit <N>`(从新到旧) |
| 指定时间窗口 | `--time "<start>" --forward --limit 100` + 分页(`hasMore=true` 时用最后一条 `createTime` 续拉) |
> 实测:`chat message list` 不带 `--time` + 默认 `--forward=true` 时,对**部分群(尤其挂 CSpace 协作空间的群,`chat search` 返回 `extension.newCSpaceIdIM` 非空)会返回空**。**拉今日消息必须显式 `--time`**。
#### 返回 0 条的诊断顺序(不要直接告诉用户「群里没消息」)
1. 重试:换 `--forward=false --limit 50`(从新到旧拿最近消息)
2. 仍 0 条:去掉 `--time`、`--forward=false --limit 100` 再试
3. 仍 0 条:用 `chat conversation-info --group <id>` 确认能查到群、当前用户是群成员
4. 三步都 0 条才告知用户「该群在 {日期} 无可见消息」
**禁止**把 0 条归因为「机器人不在群内」—— dws 用**用户身份**读取,与机器人无关。
- 用 `chat message list --group`(已下线的 `mcp ... list_conversation_message_v2` 勿用)
- `chat search` 0 条 → 告知未找到,建议用户换关键词或确认全名;多条 → 列群名供用户选;**唯一**允许追问群名的场景
### B. 发送群消息
| 身份 | 命令 |
|------|------|
| 用户身份 | `chat message send --group <id> --title <t> --text <c>` |
| 机器人身份 | `chat message send-by-bot --robot-code <code> --group <id> --title <t> --text <c>` |
| 自定义 Webhook | `chat message send-by-webhook --webhook <url> --title <t> --text <c>` |
`robot-code` 用 `chat bot search` 取;若机器人尚未在群内,先走 §C 入群。
### C. 把机器人加入现有群(危险,需确认)
```
1. chat bot search --name "<机器人名>" → 取 robotCode(仅当前用户有权限)
2. chat search --query "<群名>" → 取 openConversationId
3. 向用户展示「机器人名 + 群名」摘要等确认
4. chat group members add-bot --robot-code <code> --id <openConversationId> --yes
```
`--id` 是 openConversationId(非内部 groupId)。报错 `PAT_MEDIUM_RISK_NO_PERMISSION` 时按 CLI 返回的链接补 OAuth scope。
### D. 给个人发单聊消息
```
1. contact user search --query "<姓名>" → 取 userId
2. chat message send --user "<userId>" --title <t> --text <c>
```
## 危险操作(执行前必须确认 + 加 `--yes`)
| 命令 | 影响 |
|------|------|
| `chat group members add-bot` | 修改群成员(机器人入群) |
| `chat group members remove` | 移除群成员 |
| `chat message recall` / `recall-by-bot` | 撤回消息 |
确认流程:展示操作摘要(操作 + 目标 + 影响范围)→ 用户明确同意 → 加 `--yes` 执行。
## 严格禁止 (NEVER DO)
- 未加载本 skill 就追问「需要 groupId / openConversationId」(用户给群名时必须自行 `chat search`)
- 让用户自跑 `dws auth login` / `dws login`(必须 `get_device_auth_link.py` 生成链接)
- 直接运行裸 `dws`(必须 `dws_agent.py` / `get_device_auth_link.py`)
- 使用 `~/.dws` 或其它 agent 的 `{workspace}/.dws`
- 编造授权链接、`open.dingtalk.com` 链接、编造群 ID
- 用 curl / HTTP / 浏览器替代 dws 做群聊业务
- 拉今日 / 指定日期消息时**省略** `--time`(必空,对 CSpace 群直接返回空)
- 把 `chat message list` 返回 0 条归因为「机器人不在群」/「无权限」(dws 用用户身份读取;先按 §A 诊断顺序排查)
## 严格要求 (MUST DO)
- 业务命令一律 `python3 skills/dws-chat/scripts/dws_agent.py ... -f json`
- 危险操作先向用户确认,同意后再加 `--yes`
- 参数以 `dws_agent.py <cmd> --help` 为准;参考文档与 `--help` 冲突时以 `--help` 为准
## 错误处理
1. 失败 → 加 `--verbose` 重试一次
2. stderr 含 `RECOVERY_EVENT_ID=<id>` → `dws_agent.py recovery execute --event-id <id> -f json`
3. 仍失败 → 报完整错误给用户,禁止自行尝试替代方案
4. 登录失效 → 走「未登录回复模板」,不要用 `~/.dws`
5. 重置本 agent 凭证 → 删 `{workspace}/.dws` 与 `{workspace}/.dws_home` 后重新授权
## 部署与凭证隔离(一句话)
- 一 agent ↔ 一 `HOME` ↔ 一套 token;`dws_agent.py` 注入 `HOME={workspace}/.dws_home`、`DWS_CONFIG_DIR={workspace}/.dws`、`DWS_DISABLE_KEYCHAIN=1`,详见 [`references/isolation.md`](./references/isolation.md)
- 安装、跨机部署、清理、平台矩阵 → [`references/install.md`](./references/install.md)
- 沙盒 agent 在容器内安装即天然隔离;脚本会自动识别 `/workspace`(stderr `sandbox=yes`)
- **Windows**:本机 PowerShell 执行 [`install.ps1`](https://github.com/DingTalk-Real-AI/dingtalk-workspace-cli/blob/main/scripts/install.ps1) 安装 `dws.exe`;用 `py -3 skills/dws-chat/scripts/...`;**不需要** WSL/Docker(见 `references/install.md`)
don't have the plugin yet? install it then click "run inline in claude" again.