适用版本:ChengOS v0.1.0+ | 最后核对:2026-08-12 | 来源:
chengflow-sdk/README.md、chengflow-sdk/src/sdk/types.ts
网关是外部应用与 ChengOS 工作流之间的一层。它的全部职责就是映射:消息来自哪个应用、应该由哪个工作流处理、属于哪个会话。把这个模型理顺,多应用部署才不会变成猜谜。
关于命名要注意:网关在部署配置中被称为 chengflow-app / cheng-app,而它的源码位于 chengflow-sdk/。
四个标识符
一切都建立在把这几个标识符分开的基础上:
| 标识符 | 回答什么问题 | 说明 |
|---|---|---|
workspaceId |
哪个租户? | 始终显式指定,使多工作区部署不会误路由 |
channelId |
这条消息从哪来? | 工作区内唯一的 slug,例如 weather-app。不是工作流标识符。 |
boundWorkflowId |
应该运行什么? | 工作流 UUID,在配置渠道时绑定 |
sessionId |
属于哪段正在进行的对话? | 映射到一个持久会话 |
关键规则
channelId 标识来源,boundWorkflowId 选择执行目标。二者绝不是同一个东西,后端也绝不能由其中之一推断另一个。
早期版本用 channelId 去查找工作流,这把三件本不相干的事混在了一起:应用来源标识、工作流选择,以及适配器级别的鉴权。后果是:你无法让两个应用指向同一个工作流,也无法在不改动其他部分所依赖的名字的前提下,把一个应用切换到另一个工作流。
当前模型在渠道配置阶段显式绑定工作流。此后 channelId 只做它名字所说的事:告诉网关该把结果路由回哪个应用。
认证
浏览器网关只使用 JWT 认证,不使用别的。 它不使用适配器密钥。
这是一条刻意划下的边界。chk_ 前缀的渠道密钥是给服务端渠道适配器用的——比如从外部调入的 Telegram 或 Slack 集成——而且只对 /api/v1/channel/* 有效。浏览器前端如果复用适配器密钥,就等于把一个长期有效的共享密钥嵌进了客户端代码。参见认证。
消息流
外部应用
↓
网关接受连接并完成应用配对
↓
网关解析 channelId → 应用映射,boundWorkflowId → 执行目标
↓
网关用用户的 JWT 调用后端
↓
后端执行工作流
↓
后端返回执行结果 / 推送执行事件
↓
网关依据 channelId + 会话映射把结果转发回对应应用
分工是:网关负责配对、映射和路由;后端负责执行。双方都不去猜对方的职责。
渠道配置
一条渠道记录包含:
| 字段 | 含义 |
|---|---|
id |
记录自身的 UUID(主键) |
channelId |
业务 slug,工作区内唯一 |
boundWorkflowId |
要执行的工作流 UUID |
name、description |
面向人的标签 |
appType |
应用类型 |
connectionConfig |
各适配器的设置 |
enabled |
是否接受流量 |
connectionState |
连接生命周期状态 |
webhookUrl |
外部平台投递消息的地址 |
注意 id 和 channelId 同时存在且不可互换:id 是数据库主键,channelId 是你在应用代码中使用的 slug。
在 /api/v1/workspaces/:workspace_id/channels 管理渠道,在 /channel-keys 管理其密钥。
会话与对话
一个 session 包含 id(发送给后端的 session_id)、显示用的 label、createdAt、可选的 conversationId 和 pinned 标记。它还带有一个派生的 executionStatus——pending、running、waiting_for_review、completed_unread 或 failed_unread。
*_unread 状态属于界面层关注点,而非后端概念:它们让网关能提示某个会话在用户看别处时已经结束。这些状态由执行协调器派生,SessionManager 从不持久化它们,因此请把它们当作视图状态。
Session 映射到持久的 conversation。conversation 是历史的真相来源;session 是客户端持有的句柄。
每轮两次 REST 调用
浏览器侧的流程是:
POST /api/v1/workspaces/:workspace_id/conversations/resolve——找到或创建会话。POST /api/v1/conversations/:id/messages——发送消息并触发执行。
响应会给出 conversation_id、workflow_id,以及可选的 execution_id。用该 execution_id 通过 WebSocket 订阅流式输出。

暂无评论内容