安全与参考
开发频道插件
只在你要给 CogineWork 新增一种消息渠道时读本页。把飞书、Slack 接到现有智能体,走频道;把现成插件装进桌面,走插件。
频道插件复用内建频道的 manager、队列、显示策略、ACL、错误/审批处理和生命周期,不需要另建一套配置页面或消息运行时。
本页只说明频道插件 seam。通用插件安装、签名、权限和版本治理仍以当前 CogineWork 插件政策为准;
manifest.trust 不能授权自定义 endpoint、远程媒体写入或其他高风险配置。
最小结构
my-channel/
├── plugin.json
├── plugin.py
└── channel.py
plugin.json 示例:
{
"id": "my-channel",
"name": "My Channel",
"version": "1.0.0",
"type": "channel",
"entry": { "backend": "plugin.py" },
"coginework_version": {
"min": "2.2.1",
"max": "2.4.0"
}
}
版本范围必须与插件真实测试矩阵一致,不要使用没有验证过的宽泛上限。
实现 BaseChannel
自定义类必须是 coginework.app.channels.base.BaseChannel 的具体子类,并提供唯一、规范化的
小写 channel key。至少实现 from_config、start、stop 和 send:
from coginework.app.channels.base import BaseChannel
class MyChannel(BaseChannel):
channel = "my_channel"
display_name = "My Channel"
@classmethod
def from_config(
cls,
process,
config,
on_reply_sent=None,
display_config=None,
no_text_debounce=True,
):
return cls(
process=process,
on_reply_sent=on_reply_sent,
display_config=display_config,
no_text_debounce=no_text_debounce,
)
async def start(self):
# 建立 client/webhook/poller,并开始接收平台事件。
...
async def stop(self):
# 取消并等待自有任务,关闭 client/session,释放缓存。
...
async def send(self, to_handle, text, meta=None):
# 使用稳定 reply route 发送一条文本消息。
...
入站平台事件应先解析成结构化 content parts,再使用 BaseChannel 的 request builder 和 manager queue。 不要绕过 BaseChannel 直接调用 Agent,也不要把 raw transport body 当作公开错误返回给远端用户。
注册频道和配置 schema
插件入口通过 api.register_channel 注册:
from .channel import MyChannel
class MyChannelPlugin:
def register(self, api):
api.register_channel(
channel_class=MyChannel,
label="My Channel",
description="Connect CogineWork to My Channel",
icon="message-circle",
doc_url="https://docs.example.com/my-channel",
config_fields=[
{
"name": "bot_token",
"label": "Bot Token",
"type": "password",
"required": True,
},
{
"name": "streaming_enabled",
"label": "Streaming",
"type": "switch",
"default": False,
},
{
"name": "region",
"label": "Region",
"type": "select",
"options": [
{"label": "Default", "value": "default"},
{"label": "EU", "value": "eu"}
],
},
],
)
plugin = MyChannelPlugin()
每个 config_fields 项必须包含 name、label 和 type。支持的类型是:
textpasswordnumberswitchselect
还可以提供 required、placeholder、help、default 和 options。密码字段在工作台与 CLI
中必须保持遮罩;插件日志同样不得打印凭据。
插件不能覆盖内建频道 key,也不能覆盖其他插件已经注册的 key。注册时会验证子类类型、字段 schema 和 key;不合法的注册应 fail closed。
显示与安全默认值
插件频道默认继承外部频道 profile:
{
"show_tool_calls": false,
"show_tool_results": false,
"show_thinking": false,
"tool_call_max_length": 200,
"tool_result_max_length": 500
}
插件频道和内建频道一样服从根配置 show_tool_details;插件自己的频道配置不应声明或覆盖该字段。
两个长度字段都允许设为 0,表示不截断。
不要在插件的 send、streaming hook、error override 或 approval card 中重新拼接原始 runtime 事件,
否则会绕过共同的 renderer 和 redaction。自定义呈现应复用 BaseChannel 的结构化发送 seam,并覆盖:
- 普通最终消息;
- streaming start/delta/end;
- tool failure 与 runtime failure;
- approval 请求、过期和重复回调;
- history/replay 与主动发送;
- 面向用户资源和 context-only media 的区分。
自定义 endpoint 和远程媒体还必须经过 CogineWork 的策略、URL/redirect/大小/类型/超时校验,以及 Workspace/File Guard。插件自行提供的“受信任”字段不能替代这些检查。
CLI configurator
coginework channels config 会先加载已安装的频道插件,再构建菜单。频道类可以提供自定义 configurator:
class MyChannel(BaseChannel):
channel = "my_channel"
@classmethod
def get_configurator(cls):
def configure(current):
current["enabled"] = True
current["binding_method"] = "oauth"
return current
return configure
未提供时,CLI 使用基本的 enabled/bot-prefix 回退配置。工作台则使用注册时的 config_fields
自动生成表单。
Webhook 和主动发送
需要 webhook 时,插件可另外注册 FastAPI router;路由必须位于插件自己的 /api prefix 下,并进行
平台签名、时间窗口、重放和 body 大小校验。
主动发送必须保存并使用真实会话的稳定 target/reply route。不要从昵称或未验证的 payload 推导目标; 无法证明路由有效时应明确失败。
验证清单
频道插件至少应有以下自动化与真实平台证据:
- 注册、重复 key、内建 key 冲突和 schema 验证。
- 工作台表单与 CLI configurator 的保存/reload round-trip。
- 默认隐藏、显式 opt-in、长度上限和公开错误 redaction。
- DM、群聊、ACL、mention、session isolation 与 reply route。
- start/stop/reload 后无孤儿 task、client 或未界定缓存。
- 媒体、引用回复、streaming、审批、history/replay 与主动发送。
- 固定 CogineWork 版本和真实平台版本的 UAT。
自动化通过不等于插件已被签名、打包、发布或生产验证。