> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentscope.io/llms.txt
> Use this file to discover all available pages before exploring further.

# 钉钉

> 在钉钉中与智能体服务里的智能体对话。

钉钉渠道通过官方 Stream 模式建立长连接接入，无需公网回调地址，本地或内网部署也能直接使用。目前钉钉渠道的实现支持：

* **交互式卡片确认**：智能体调用需要审批的工具时，在钉钉里以卡片形式请求确认，点击按钮即可批准或拒绝；
* **流式回复**：配置 AI 卡片模板后，回答在同一张卡片内逐步更新；未配置时回复以普通 Markdown 消息发出；
* **多模态输入**：接收用户发来的图片、文件、语音、视频与图文混排消息，交给智能体处理；
* **主动发送**：智能体可以查询通讯录与已知聊天，把消息、图片、文件发送到当前会话之外的用户或群。

接入分四步：在[钉钉开放平台](https://open.dingtalk.com/)创建应用并拿到凭据，在卡片平台准备卡片模板，启动一个智能体服务承载渠道，最后在管理界面添加钉钉渠道。

## 前置条件

钉钉渠道依赖 `dingtalk-stream`，随 `channel` 可选依赖安装：

```bash 安装依赖 theme={null}
pip install "agentscope[channel]"
```

## 创建应用

在[钉钉开放平台](https://open.dingtalk.com/)完成企业内部应用与机器人的创建配置。

<Steps>
  <Step title="创建企业内部应用">
    在开发者后台创建一个"企业内部应用"，填写名称与图标。
  </Step>

  <Step title="记录 Client ID 与 Client Secret">
    在应用的凭证与基础信息页，复制 **Client ID**（AppKey）与 **Client Secret**（AppSecret），稍后填入渠道配置。Client Secret 是机密，请妥善保管。
  </Step>

  <Step title="添加机器人能力">
    在"应用能力"中添加"机器人"，填写机器人名称与图标，机器人才能收发消息。
  </Step>

  <Step title="消息接收模式选择 Stream">
    在机器人配置页，把消息接收模式设为 **Stream 模式**，无需填写 HTTP 回调地址。
  </Step>

  <Step title="申请权限">
    在"权限管理"中申请：企业内机器人发送消息、卡片实例的创建与更新、媒体文件的上传与下载。若需要 `ListUsers` 工具按姓名搜索用户，再申请通讯录的用户搜索与个人信息读取权限。具体权限项以[钉钉官方文档](https://open.dingtalk.com/document/)为准。
  </Step>

  <Step title="发布应用">
    发布应用版本，使其在企业内可用。之后即可把机器人加入群聊，或直接与它私聊。
  </Step>
</Steps>

## 准备卡片模板

钉钉的交互式卡片必须先在[卡片平台](https://open-dev.dingtalk.com/fe/card)建好模板，渠道运行时只负责填充模板变量。渠道用到两类模板，都是可选的，不配置则相应能力降级。

**审批卡片模板**用于工具确认。渠道下发卡片时填充以下变量：

| 变量           | 内容                                     |
| ------------ | -------------------------------------- |
| `title`      | 卡片标题                                   |
| `markdown`   | 待执行的工具名与参数摘要                           |
| `status`     | 卡片状态：`pending` / `approved` / `denied` |
| `toolCallId` | 本次工具调用的标识                              |
| `chatId`     | 发起调用的聊天标识                              |
| `agentId`    | 处理该消息的智能体标识                            |
| `sessionId`  | 该消息所属的会话标识                             |
| `approverId` | 允许做出决定的用户标识，私聊时为对方的 `staffId`          |

模板中需要放置"同意"与"拒绝"两个回传按钮，并在按钮的回传参数（`cardPrivateData.params`）里带上 `action` 以及 `toolCallId`、`chatId`、`agentId`、`sessionId`、`approverId`。`action` 的取值：批准用 `allow`、`approve`、`accept` 或 `agree`，拒绝用 `deny` 或 `reject`。

<Warning>
  未配置审批卡片模板时，需要确认的工具调用无法在钉钉里得到答复，`SendMessage`、`SendImage`、`SendFile` 三个主动发送工具也不会开放给智能体。
</Warning>

**流式卡片模板**用于流式回复，需要在模板中放置一个 AI 卡片流式组件，并把它的模板变量名填到渠道配置的 `streaming_card_key`（默认 `content`）。

<Note>
  钉钉对单次卡片更新的内容大小有限制。当回复增长到超出该限制时，渠道停止流式更新，改为把完整回答作为普通 Markdown 消息发出。
</Note>

## 启动智能体服务

渠道运行在[智能体服务](/versions/2.0.7dev/zh/deploy/agent-service)之上。用 `create_app` 启动服务，并用 `channels` 参数声明允许接入的渠道类型。渠道依赖消息总线（`message_bus`），单机开发用 `InMemoryMessageBus` 即可，多进程或多节点部署再换成 `RedisMessageBus`。

```python 启动承载渠道的智能体服务 theme={null}
from agentscope.app import create_app
from agentscope.app.channel import DingTalkChannel
from agentscope.app.message_bus import InMemoryMessageBus
from agentscope.app.storage import RedisStorage
from agentscope.app.workspace_manager import LocalWorkspaceManager

app = create_app(
    storage=RedisStorage(host="localhost", port=6379),
    # 单机开发用内存消息总线；多节点部署换成 RedisMessageBus
    message_bus=InMemoryMessageBus(),
    workspace_manager=LocalWorkspaceManager(basedir="./workspaces"),
    channels=[DingTalkChannel],   # 本服务允许接入的渠道类型
)
# 用 uvicorn 启动后，渠道功能即可用
# uvicorn.run(app, host="0.0.0.0", port=8000)
```

## 添加渠道

在智能体服务的管理界面（参见示例前端 [`examples/web_ui`](https://github.com/agentscope-ai/agentscope/tree/main/examples/web_ui)）中，通过可视化表单添加渠道，无需手写配置。

<Steps>
  <Step title="新建渠道并选择钉钉">
    在渠道管理页新建一个渠道，平台类型选择"钉钉"。
  </Step>

  <Step title="填入凭据">
    把上一步拿到的 **Client ID** 与 **Client Secret** 填入凭据表单。
  </Step>

  <Step title="填入卡片模板 ID">
    把审批卡片与流式卡片的模板 ID 填入平台配置，二者都可留空。
  </Step>

  <Step title="配置路由规则">
    选择消息交给哪个智能体、会话如何划分。路由规则的含义见[会话路由](/versions/2.0.7dev/zh/deploy/channel/routing)。
  </Step>

  <Step title="保存并启用">
    保存后启用渠道，服务立即建立与钉钉的 Stream 连接，机器人上线。把它加入群聊或发起私聊即可开始对话。
  </Step>
</Steps>

<Note>
  管理界面的操作对应一组 `/channels` 接口，需要以编程方式批量创建渠道时可直接调用，字段见本章 [API](/versions/2.0.7dev/en/deploy/openapi.json) 部分。
</Note>

## 平台配置

钉钉渠道的平台专属字段：

| 字段                           | 说明                                      | 默认值               |
| ---------------------------- | --------------------------------------- | ----------------- |
| `only_at_reply`              | 群聊中是否仅在被 @ 时才回复。私聊不受影响，始终回复             | `true`            |
| `show_thinking`              | 是否把模型的思考过程一并展示在回复里                      | `false`           |
| `show_tool_process`          | 是否把工具调用与结果一并展示在回复里                      | `false`           |
| `max_media_bytes`            | 单个收发附件的最大字节数，上限 100 MB                  | `10485760`（10 MB） |
| `approval_card_template_id`  | 工具审批卡片使用的模板 ID，留空则不下发审批卡片               | `""`              |
| `streaming_card_template_id` | 流式回复使用的 AI 卡片模板 ID，留空则回复走普通 Markdown 消息 | `""`              |
| `streaming_card_key`         | AI 卡片流式组件的模板变量名                         | `content`         |

<Note>
  路由匹配 `chat_type` 时，群聊的值为 `group`，私聊为 `private`。
</Note>

## 智能体工具

配置好审批卡片模板后，渠道会向智能体额外提供一组钉钉工具，用于把消息发到当前会话之外的用户或群。发送目标由查询类工具返回，形如 `user:<staffId>` 或 `group:<openConversationId>`，智能体原样传给发送类工具即可。

| 工具                  | 作用                                             | 权限      |
| ------------------- | ---------------------------------------------- | ------- |
| `ListConversations` | 列出本渠道进程启动以来收到过消息的聊天                            | 只读，直接放行 |
| `ListUsers`         | 在企业通讯录中按姓名搜索用户                                 | 只读，直接放行 |
| `SendMessage`       | 向指定用户或群发送 Markdown 文本                          | 需用户确认   |
| `SendImage`         | 把工作区里的图片发送到指定用户或群，在聊天中直接渲染                     | 需用户确认   |
| `SendFile`          | 把工作区里的文件发送到指定用户或群，支持 doc、docx、pdf、rar、xlsx、zip | 需用户确认   |

<Warning>
  钉钉的企业内部机器人无法枚举自己加入的全部群聊，因此 `ListConversations` 只能列出当前进程启动以来收到过消息的聊天。想让某个群出现在结果里，先在群内给机器人发一条消息。
</Warning>

## 验证与排查

* 在管理界面查看渠道状态，或调用 `GET /channels/{id}/status` 确认 Stream 连接已建立。
* 若机器人在群里不响应，先确认 `only_at_reply` 与 @ 行为是否符合预期，再检查发送消息权限是否已申请并随版本发布。
* 若机器人完全不上线，检查 Client ID / Client Secret 是否正确、消息接收模式是否设为 Stream。
* 若点击卡片按钮没有反应，检查按钮回传参数是否带上了 `action` 与上表中的各个标识字段。
* 若附件发送失败，检查文件是否超过 `max_media_bytes`，以及扩展名是否在钉钉支持的范围内。

## 延伸阅读

<CardGroup cols={2}>
  <Card title="会话路由" icon="route" href="/versions/2.0.7dev/zh/deploy/channel/routing" cta="查看详情" arrow>
    把不同的群路由到不同的智能体。
  </Card>

  <Card title="飞书" icon="comment" href="/versions/2.0.7dev/zh/deploy/channel/feishu" cta="查看详情" arrow>
    用同一套流程接入飞书。
  </Card>
</CardGroup>
