Webhook 回调
Wesclaw 支持通过 IM 渠道(企业微信、飞书、钉钉)接入 AI Agent。每个 Cell 拥有独立的渠道配置和 Webhook URL。
支持的 IM 渠道
| 平台 | 标识 | Webhook 路径 |
|---|---|---|
| 企业微信 | wecom | /cells/{cellID}/webhook/wecom |
| 飞书 | feishu | /cells/{cellID}/webhook/feishu |
| 钉钉 | dingtalk | /cells/{cellID}/webhook/dingtalk |
Webhook URL
URL 格式
每个 Cell 使用独立的 Webhook URL,URL 中携带 CellID:
POST http://<engine-host>:<port>/cells/{cellID}/webhook/{platform}
示例
# 企业微信
POST /cells/main/webhook/wecom
# 飞书
POST /cells/main/webhook/feishu
# 钉钉
POST /cells/main/webhook/dingtalk
为什么使用 URL Path
- 物理隔离:不同 Cell 的渠道消息天然隔离
- 无歧义:不依赖 header 或 body 字段推断租户
- 简单路由:Gateway 从 URL 直接提取 CellID
❌ 不再使用
X-Cell-IDHTTP header(v0.2 遗留方式已废弃)。
渠道配置
声明式配置(CellSpec.Channels)
在 Cell 创建时声明渠道:
spec := wesgine.CellSpec{
Channels: []channel.Config{
{
Type: "wecom",
CorpID: "wxXXXXXX",
AgentID: 1000001,
SecretRef: config.SecretRef{
Source: "inline",
Value: "your-secret",
},
},
},
}
运行时管理
通过 cell.Channels() Handle 在运行时管理:
| 方法 | 说明 |
|---|---|
cell.Channels().List() | 列出渠道 |
cell.Channels().Register() | 注册/更新渠道 |
cell.Channels().Delete() | 删除渠道 |
HTTP API
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /cells/{id}/channels | 渠道列表 |
| POST | /cells/{id}/channels | 注册/更新渠道 |
| DELETE | /cells/{id}/channels/{platform}/{account} | 删除渠道 |
渠道绑定
渠道可以绑定到特定的 Agent,实现"不同渠道由不同 Agent 响应"。
查看绑定
GET /cells/{id}/channels/bindings
设置绑定
PUT /cells/{id}/channels/bindings
Content-Type: application/json
{
"bindings": [
{
"platform": "wecom",
"account": "wxXXXXXX",
"agent_id": "agent-assistant"
},
{
"platform": "feishu",
"account": "cli_xxxx",
"agent_id": "agent-researcher"
}
]
}
绑定规则
- 一个渠道可以绑定一个 Agent
- 未绑定的渠道使用默认 Agent
- 绑定列表通过
PUT整体替换
消息发送
主动推送消息
POST /cells/{id}/channels/send
Content-Type: application/json
{
"platform": "wecom",
"account": "wxXXXXXX",
"target": "user_id_or_group_id",
"content": "这是一条通知消息"
}
消息类型
不同平台支持的消息类型:
| 类型 | 企业微信 | 飞书 | 钉钉 |
|---|---|---|---|
| 文本 | ✅ | ✅ | ✅ |
| 富文本 | ✅ | ✅ | ✅ |
| 图片 | ✅ | ✅ | ✅ |
| 文件 | ✅ | ✅ | ✅ |
| 卡片 | ✅ | ✅ | ✅ |
预检验证
在正式配置渠道前,可以使用预检验证确认配置有效性:
POST /cells/{id}/channels/preflight
Content-Type: application/json
{
"type": "wecom",
"corp_id": "wxXXXXXX",
"agent_id": 1000001,
"secret": "your-secret"
}
验证内容
- 凭证是否有效
- API 连通性
- 权限是否足够
渠道事件
SSE 事件流
GET /cells/{id}/channels/events
通过 SSE 实时接收渠道事件,包括:
| 事件类型 | 说明 |
|---|---|
| 消息接收 | 新消息到达通知 |
| 连接状态 | 渠道连接/断开 |
| 扫码回调 | 企业微信扫码等事件 |
| 错误通知 | 发送失败等异常 |
渠道配额
MaxIMChannels
IM 渠道数量受 CellQuotas.MaxIMChannels 限制。
配额判定
配额在唯一增长点判定(INV-QUOTA-05):
- 适配器不知道 cap 的数值
- 只收
QuotaFn(current, delta) error提问 - 覆盖已有名字
delta=0(upsert 是编辑手势,不占配额)
特殊情况
- Channels 没有独立的运行时存储,CellSpec 就是唯一一份副本
- 因此 cap 不在
Cell.Start检查,而是下沉到唯一增长点 - 整体替换(
UpdateSpec)对 cap 幂等,收缩不需要 cap
企业微信配置示例
1. 创建企业微信应用
在企业微信管理后台创建自建应用,获取:
corp_id:企业 IDagent_id:应用 AgentIDsecret:应用 Secret
2. 配置 Webhook URL
在应用的"接收消息"设置中,配置回调 URL:
https://your-domain.com/cells/main/webhook/wecom
3. 在 Wesclaw 中注册渠道
POST /cells/main/channels
Content-Type: application/json
{
"type": "wecom",
"corp_id": "wxXXXXXX",
"agent_id": 1000001,
"secret_ref": {
"source": "inline",
"value": "your-secret"
}
}
4. 验证
# 预检验证
POST /cells/main/channels/preflight
# 查看渠道列表
GET /cells/main/channels
飞书配置示例
1. 创建飞书应用
在飞书开放平台创建应用,获取:
app_id:应用 IDapp_secret:应用密钥
2. 配置事件订阅
在飞书开放平台配置请求地址:
https://your-domain.com/cells/main/webhook/feishu
3. 注册渠道
POST /cells/main/channels
Content-Type: application/json
{
"type": "feishu",
"app_id": "cli_xxxx",
"app_secret_ref": {
"source": "inline",
"value": "your-app-secret"
}
}
故障排查
| 症状 | 可能原因 | 解决方案 |
|---|---|---|
| 消息不到达 | Webhook URL 配置错误 | 检查 URL 中的 cellID |
| 认证失败 | Secret 不正确 | 使用 /channels/preflight 验证 |
| 消息延迟 | 网络或服务端处理慢 | 检查引擎日志 |
| 渠道不可用 | 配额已满 | 检查 MaxIMChannels |
| 跨 Cell 收到消息 | 不可能发生 | Cell 间物理隔离(不同凭证) |