安全与参考频道插件

安全与参考

开发频道插件

只在你要给 CogineWork 新增一种消息渠道时读本页。把飞书、Slack 接到现有智能体,走频道;把现成插件装进桌面,走插件。

频道插件复用内建频道的 manager、队列、显示策略、ACL、错误/审批处理和生命周期,不需要另建一套配置页面或消息运行时。

本页只说明频道插件 seam。通用插件安装、签名、权限和版本治理仍以当前 CogineWork 插件政策为准; manifest.trust 不能授权自定义 endpoint、远程媒体写入或其他高风险配置。

最小结构

text
my-channel/
├── plugin.json
├── plugin.py
└── channel.py

plugin.json 示例:

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:

python
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 注册:

python
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。支持的类型是:

  • text
  • password
  • number
  • switch
  • select

还可以提供 required、placeholder、help、default 和 options。密码字段在工作台与 CLI 中必须保持遮罩;插件日志同样不得打印凭据。

插件不能覆盖内建频道 key,也不能覆盖其他插件已经注册的 key。注册时会验证子类类型、字段 schema 和 key;不合法的注册应 fail closed。

显示与安全默认值

插件频道默认继承外部频道 profile:

json
{
  "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:

python
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 推导目标; 无法证明路由有效时应明确失败。

验证清单

频道插件至少应有以下自动化与真实平台证据:

  1. 注册、重复 key、内建 key 冲突和 schema 验证。
  2. 工作台表单与 CLI configurator 的保存/reload round-trip。
  3. 默认隐藏、显式 opt-in、长度上限和公开错误 redaction。
  4. DM、群聊、ACL、mention、session isolation 与 reply route。
  5. start/stop/reload 后无孤儿 task、client 或未界定缓存。
  6. 媒体、引用回复、streaming、审批、history/replay 与主动发送。
  7. 固定 CogineWork 版本和真实平台版本的 UAT。

自动化通过不等于插件已被签名、打包、发布或生产验证。

相关页面:插件 · 频道 · 命令行 · 工作台配置