feat(agent-runner): finalize 4.x processor integration

This commit is contained in:
huanghuoguoguo
2026-07-12 15:44:05 +08:00
parent 29689962f3
commit e6384aae5d
109 changed files with 2200 additions and 1204 deletions
@@ -104,7 +104,7 @@ bin/lbs case list
1. 打开 WebUI Pipeline 配置页。
2. 查看 AI runner 下拉列表。
3. 选择 `plugin:langbot/local-agent/default`
3. 选择 `plugin:langbot-team/LocalAgent/default`
4. 保存并刷新页面。
通过条件:
@@ -120,7 +120,7 @@ bin/lbs case list
步骤:
1. 使用绑定 `plugin:langbot/local-agent/default` 的 Pipeline。
1. 使用绑定 `plugin:langbot-team/LocalAgent/default` 的 Pipeline。
2. 在 Debug Chat 发送确定性普通文本。
3. 查看 WebUI 回复和后端日志。
@@ -160,7 +160,7 @@ Smoke 前应优先保留一层轻量单测或 fixture 测试:session 创建/
步骤:
1. 确认目标 harness(例如 ACP daemon、Claude Code 或 Codex)在对应机器上可执行且已登录。
2. 绑定目标 runner,例如 `plugin:langbot/acp-agent-runner/default``plugin:langbot/claude-code-agent/default``plugin:langbot/codex-agent/default`
2. 绑定目标 runner,例如 `plugin:langbot-team/ACPAgentRunner/default``plugin:langbot-team/ClaudeCodeAgent/default``plugin:langbot-team/CodexAgent/default`
3. 配置 runner 必要字段,例如 remote target、workspace、provider、startup timeout、reuse session 等。
4. 在 Debug Chat 执行一次确定性真实 smoke。
5. 检查 LangBot MCP gateway、`run_id` 回填和 host-owned state。
@@ -5,13 +5,13 @@
> 数据结构唯一定义在 [PROTOCOL_V1.md](./PROTOCOL_V1.md)runner 可见)与 [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md)Host 内部模型);本文只讲 EBA 语义,不重抄 schema。
> 与当前 runner 外化分支、后续 Agent Platform / Runtime Control Plane 的边界见 [EXTENSION_SCOPE_MATRIX.md](./EXTENSION_SCOPE_MATRIX.md)。
本文描述 EBA 接入时,事件如何进入 LangBot、如何触发 AgentRunner,以及如何复用插件化 agent 基础设施。本分支不实现完整 EventBus / EventRouter / Platform API;这些能力正在外部 EBA 分支联调。这里的目标是把协议边界说清楚,避免当前消息入口继续绑死 Pipeline 和用户文本消息
本文描述 EBA 接入时,事件如何进入 LangBot、如何在平级的 Pipeline / Agent 处理器之间路由,以及 Agent 分支如何复用插件化 AgentRunner 基础设施。本分支不实现完整 EventBus / EventRouter / Platform API;这些能力正在外部 EBA 分支联调。这里的目标是把处理器路由与 runner 协议边界说清楚。
## 1. 设计目标
- 消息、撤回、入群、好友申请、定时任务、API 调用都能抽象为 host event。
- EventRouter 可以根据 event type、bot、workspace、conversation、actor、subject 解析 `AgentBinding`
- AgentRunner 通过同一套 orchestrator 调用。
- EventRouter 可以根据 event type、bot、workspace、conversation、actor、subject 选择一个 Pipeline 或 Agent 处理器
- Pipeline 目标执行完整消息 Stage 链;Agent 目标通过统一 orchestrator 调用 AgentRunner
- 非消息事件不伪造成用户文本消息。
- 平台动作执行通过显式 capability / permission / result type 预留,不混入普通文本回复。
@@ -42,11 +42,11 @@
## 4. Event Envelope 与 Binding
- 入口事件用 `AgentEventEnvelope`HOST_SDK §4.1)承载;顶层字段使用 LangBot 稳定协议名,平台原始事件名和原始 payload 放 `metadata` / `raw_ref`
- 触发关系用 `AgentBinding`HOST_SDK §4.2)表达。EBA 阶段 binding 通过 `event_types``scope``filters` 决定哪些事件触发当前 bot / channel 绑定的 Agent
- EBA 持久路由通过 `event_pattern``filters``target_type``target_uuid` 选择处理器。只有 `target_type=agent`,或 Pipeline AI Stage 需要调用 runner 时,才进一步解析 `AgentBinding`HOST_SDK §4.2
EBA dispatch 基数、Agent 复用和 fan-out 边界以 PROTOCOL_V1 §13 为准;本节只说明外部 EBA 分支的 EventRouter 如何产出当前 v1 主线需要的 binding
EBA 每个事件只选择一个有效处理器;AgentRunner 调用的基数、Agent 复用和 fan-out 边界以 PROTOCOL_V1 §13 为准。
Binding scope 示例:workspace 全局、bot 级、platform channel 级、conversation / group / thread 级、user / actor 级。Pipeline 可迁移为 `message.received` 的临时 binding source,但目标持久配置应是 Agent,不是 Pipeline
路由 scope 示例:workspace 全局、bot 级、platform channel 级、conversation / group / thread 级、user / actor 级。Pipeline `message.*` 场景的一等处理器,适合需要预处理、AI、后处理、扩展和输出控制的消息链路;Agent 是 runner 驱动的一等处理器,可处理其声明支持的消息与非消息事件。二者都不会被转换成对方
Event Source 可包括:`platform_adapter`(飞书、QQ、微信、Telegram 等)、`webui``http_api``scheduler``system`。EventRouter 不应写死平台 adapter 的类名。
@@ -56,15 +56,15 @@ Event Source 可包括:`platform_adapter`(飞书、QQ、微信、Telegram
Platform Adapter / WebUI / API
-> Event Gateway normalize payload
-> EventLog append raw event
-> EventRouter resolve one effective AgentBinding
-> AgentRunOrchestrator.run(event, binding)
-> AgentRunContextBuilder.build(event, binding)
-> PluginRuntimeConnector.run_agent()
-> AgentRunResult stream
-> EventRouter resolve one Processor target
-> target_type=pipeline: MessageAggregator -> QueryPool -> Pipeline stages
-> target_type=agent: resolve AgentBinding -> AgentRunOrchestrator
-> AgentRunContextBuilder -> PluginRuntimeConnector.run_agent()
-> AgentRunResult stream
-> DeliveryController render / platform action
```
约束:必须复用现有 orchestrator,不能为 EBA 单独实现另一套 plugin runner 调用协议;非消息事件不能绕过 resource authorizationdelivery 和 platform action 走统一权限模型;外部 harness runner 也通过同一套 envelope/binding/context/result 协议接入,不为 Claude Code / Codex / Kimi 单独发明队列协议。observer / fan-out / parallel arbitration 的额外语义仍按 PROTOCOL_V1 §13 处理。
约束:Pipeline 和 Agent 是 EventRouter 的平级目标;Pipeline 仅接受消息事件,Agent 受其事件能力声明约束。任何 AgentRunner 调用都必须复用现有 orchestrator,不能为 EBA 单独实现另一套 plugin runner 协议;非消息事件不能绕过 resource authorizationdelivery 和 platform action 走统一权限模型;外部 harness runner 也通过同一套 envelope/binding/context/result 协议接入。observer / fan-out / parallel arbitration 的额外语义仍按 PROTOCOL_V1 §13 处理。
## 6. 平台动作执行
@@ -87,6 +87,6 @@ EBA 事件进入 AgentRunner 时仍遵循 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CO
## 8. EBA 分支联调内容
外部 EBA 分支负责联调 EventGateway 完整实现、EventRouter 与 BindingResolver 集成、`AgentBinding` 持久模型和 UI、`DeliveryContext` 完整实现、platform action permission model 和执行器、真实平台事件接入。
外部 EBA 分支负责联调 EventGateway 完整实现、Pipeline / Agent 处理器路由、AgentBindingResolver 集成、事件绑定持久模型和 UI、`DeliveryContext` 完整实现、platform action permission model 和执行器、真实平台事件接入。
当前底座已完成:① 把当前 Pipeline 消息入口适配成 `message.received` event → ② 增加 `AgentBinding` 抽象,先由 current config 生成 → ③ context builder 改为从 event + binding 构造 → ④ 引入 EventLog / Transcript。外部 EBA 分支在此基础上联调:⑤ 非消息事件协议测试与真实事件来源 → ⑥ 真实 EventRouter、binding persistence / UI 和 platform action。
当前底座已完成:① Pipeline 消息链可投影 `message.received` 并在 AI Stage 复用 AgentRunner → ② 独立 Agent 可从 EBA 路由直接生成 `AgentBinding` → ③ context builder 从 event + binding 构造 runner context → ④ 引入 EventLog / Transcript。外部 EBA 分支在此基础上联调真实事件来源、处理器路由、binding persistence / UI 和 platform action。
@@ -12,7 +12,7 @@
| --- | --- | --- |
| AgentRunner Protocol v1 | 定义 Host 调用 runner 的稳定合同:discovery、`AgentRunContext`、result stream、Host pull API、错误和权限边界。 | 不定义 Agent Platform 的产品数据库模型;不定义 runtime task queue。 |
| Host runner 外化底座 | 提供 `AgentEventEnvelope``AgentBinding` 运行投影、`run(event, binding)`、resource authorization、run-scoped session、EventLog / Transcript / State / sandbox 文件边界。 | 不实现 EventGateway、scheduler、integration provider、Agent 管控面 UI。 |
| 当前 Pipeline 入口 | 通过 `QueryEntryAdapter` Query / Pipeline config 投影成 event + binding,作为迁移期入口。 | 不继续把 Pipeline 当作长期 agent 配置中心。 |
| Pipeline 的 AgentRunner 接入 | Pipeline 作为一等消息处理器执行完整 Stage 链;仅在 AI Stage 调用 runner 时,`QueryEntryAdapter`当前 Query/config 投影成 event + binding。 | 不把整个 Pipeline 当成临时 Agent;不复制 Pipeline 配置来自动创建 Agent。 |
| 官方 runner 插件 | 作为协议消费者验证 local-agent / 外部 harness runner 能接入 Host 基础设施。 | 不让官方 runner 的内部实现反向决定 Host / SDK 协议形态。 |
## 2. 扩展矩阵
@@ -20,7 +20,7 @@
| 能力 | 当前分支状态 | 后续归属 | 后续接入方式 | 禁止事项 |
| --- | --- | --- | --- | --- |
| Product `Agent` | 已有 `agents` 产品表 / API 和运行期 `AgentConfig` / `AgentBinding` 投影;完整 binding persistence / EventRouter / UI 闭环仍未完成。 | Agent Platform / binding persistence UI。 | 持久 Agent 保存 runner id、runner config、resource/state/delivery policy;运行前投影为 `AgentBinding`。 | 不把持久 Agent schema 加进 SDK 协议;插件实例边界见 PROTOCOL_V1 §13。 |
| Bot / channel 绑定 Agent | 已有单次运行前的 `AgentBinding` 解析投影;目标调度语义见 PROTOCOL_V1 §13。 | EBA / Agent Platform。 | EventRouter 根据 bot、channel、workspace、conversation、event type 解析有效 `AgentBinding` | 不在本矩阵重定义 fan-out / observer 语义;需要时按 §3 新增设计。 |
| Agent 处理器调用 runner | 已有单次运行前的 `AgentBinding` 解析投影;AgentRunner 调度语义见 PROTOCOL_V1 §13。 | EBA / Agent Platform。 | EventRouter 先选中 Agent 处理器,再根据 bot、channel、workspace、conversation、event type 解析有效 `AgentBinding`Pipeline 目标走独立 Stage 链。 | 不用 `AgentBinding` 取代 EBA 的 Pipeline / Agent 处理器选择;不在本矩阵重定义 fan-out / observer 语义。 |
| Agent session / run | 已有持久 `AgentRun` / `AgentRunEvent` ledger 和 active `AgentRunSessionRegistry`;还没有独立 `AgentSession` / task 产品模型。 | Agent Platform / Runtime Control Plane。 | 如需要可新增 `AgentSession` / task 表,但执行仍回到 `run(event, binding)` 或 runtime-managed 等价入口。 | 不把持久 session 字段塞进 `AgentRunContext` 顶层;不要求所有 runner 长期持有 LangBot session。 |
| EventLog / Transcript / Sandbox files | 已完成 Host-owned store、history pull API 和 sandbox 文件边界;runner 不直接写 DB。 | 本分支持续维护底座;Agent Platform 可复用。 | 外部 EBA、scheduler、integration、runtime task 都写同一套 EventLog / Transcript;当前 run 文件通过 sandbox/workspace staging 共享。 | 不让 runner / sandbox 直接访问 Host DB;不把大 payload 内联进 prompt。 |
| Host-owned state / storage | 已有 state snapshot、`state.updated` 处理和 State APIstorage 作为授权能力保留。 | 本分支持续维护底座;Runtime / Platform 可复用。 | 外部 session id、working directory、checkpoint 等小 JSON 用 state;当前 run 大对象用 sandbox/workspace 文件。 | 不把跨轮次状态存在插件实例内;不绕过 run-scoped authorization。 |
@@ -11,14 +11,14 @@
LangBot 要转为 agent host,而不是内置 runner 容器:
- 接收 IM、WebUI、API 和外部 EBA 分支 EventRouter 产生的事件。
- 根据事件、bot、workspace、scope 解析应该调用的 Agent / agent binding。
- 接收 EBA 选中的 Agent 处理器,并根据事件、bot、workspace、scope 解析 AgentRunner binding。
- 发现、校验和调用插件提供的 AgentRunner。
- 为每次 run 提供受限资源、状态、存储、上下文引用和生命周期控制。
- 接收 AgentRunner 返回的事件流,投递到 IM、WebUI 或其他 output surface。
## 2. 非目标
- Pipeline 当作长期架构中心
-定义 Pipeline 的 Stage 编排语义;Pipeline 是 EBA 的同级处理器,其 AI Stage 只在需要 runner 时接入本 Host 边界
- 不要求所有 AgentRunner 依赖 LangBot 的上下文管理。
- 不要求官方 local-agent 的旧行为反向塑造 host 协议。
- 不在 host 中实现通用 agentic prompt assembler。
@@ -34,27 +34,30 @@ IM / WebUI / API / EventRouter (external EBA branch)
Event Gateway (external EBA branch)
|
v
AgentBindingResolver
EventRouter -> one Processor target
|-- target_type=pipeline -> Pipeline Stage chain
|
v
AgentRunOrchestrator
|-- AgentRunnerRegistry
|-- AgentResourceBuilder
|-- AgentContextBuilder
|-- AgentRunSessionRegistry
|-- PersistentStateStore / EventLogStore / TranscriptStore
|-- Sandbox / workspace file tools
v
Plugin Runtime / AgentRunner
|
v
AgentRunResult stream
`-- target_type=agent -> AgentBindingResolver
|
v
AgentRunOrchestrator
|-- AgentRunnerRegistry
|-- AgentResourceBuilder
|-- AgentContextBuilder
|-- AgentRunSessionRegistry
|-- PersistentStateStore / EventLogStore / TranscriptStore
|-- Sandbox / workspace file tools
v
Plugin Runtime / AgentRunner
|
v
AgentRunResult stream
|
v
Delivery / Renderer / Platform API
```
目标产品模型、单绑定调度、Agent 复用、插件实例无状态和 fan-out 边界以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) §13 为准。本文只说明 Host 如何把当前入口投影为内部模型。当前 Pipeline 只应接入在 Query entry adapter 位置:它可以继续产生 `message.received` 并投影出临时 `AgentConfig` / `AgentBinding`,但不应再拥有 runner 选择、上下文裁剪和业务 agent 执行的核心语义。EventGateway / EventRouter 由外部 EBA 分支实现并联调。
Pipeline 与 Agent 是 EventRouter 的平级处理器目标。本文只定义 AgentRunner Host 边界:Agent 目标直接解析 `AgentBinding`;Pipeline 目标执行自己的完整 Stage 链,仅在 AI Stage 调用 runner 时通过 Query entry adapter 构造一次性 `AgentConfig` / `AgentBinding`。该 runner 调用投影不改变 Pipeline 的一等处理器地位,也不会把 Pipeline 持久化为 Agent。AgentRunner 的单绑定调度、Agent 复用、插件实例无状态和 fan-out 边界以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) §13 为准。EventGateway / EventRouter 由外部 EBA 分支实现并联调。
## 4. LangBot 侧能力
@@ -88,7 +91,7 @@ class AgentEventEnvelope(BaseModel):
### 4.2 AgentConfig 与 AgentBinding
`AgentConfig`迁移期的 Host 内部 Agent 配置投影(不暴露给 SDK)。当前 Query entry adapter 从 Pipeline config 投影出它;未来持久 Agent 也应先投影成这个运行期配置,再由 BindingResolver 结合事件和 scope 解析为 `AgentBinding`
`AgentConfig` 是 Host 内部的一次 AgentRunner 调用配置投影(不暴露给 SDK)。独立 Agent 从自己的持久配置生成它;Pipeline 只在 AI Stage 调用 runner 时,由 Query entry adapter 从该 Stage 的当前配置生成它。两种来源随后都由 BindingResolver 结合事件和 scope 解析为 `AgentBinding`。Pipeline 本身不是 `AgentConfig`,该调用投影也不会创建或更新持久 Agent
```python
class AgentConfig(BaseModel):
@@ -122,11 +125,11 @@ class AgentBinding(BaseModel):
BindingResolver 的基数、fan-out 和冲突处理约束见 PROTOCOL_V1 §13;本节只定义 Host 内部投影形态。
**当前 adapter source**`QueryEntryAdapter.config_to_agent_config(query, runner_id)`
把 current config 投影为迁移`AgentConfig`,再由
只在 Pipeline AI Stage 调用 runner 时,把 current config 临时投影为运行`AgentConfig`,再由
`AgentBindingResolver.resolve_one(event, [agent_config])` 解析出唯一
`AgentBinding`。Pipeline 当前只是迁移期 Agent config sourceAI runner config
`AgentBinding`该调用从 Pipeline 取得 AI runner config
→ runner_config、extension preference → resource_policy、output settings →
delivery_policy,但新设计不再把这些字段命名为 Pipeline 专属概念
delivery_policy,但 Pipeline 仍执行并拥有完整 Stage/config 语义。该适配不会把 Pipeline 持久化为 Agent;独立 Agent 由用户自行新增和绑定
### 4.3 AgentRunnerRegistry
@@ -12,7 +12,7 @@
```text
langbot-app/
langbot-local-agent/ # plugin:langbot/local-agent/default
langbot-local-agent/ # plugin:langbot-team/LocalAgent/default
manifest.yaml
components/agent_runner/default.{yaml,py}
langbot-agent-runner/ # 外部服务 runner 仓库
@@ -25,18 +25,18 @@ langbot-app/
| 旧 runner | 官方插件 | runner id |
| --- | --- | --- |
| `local-agent` | `langbot/local-agent` | `plugin:langbot/local-agent/default` |
| `dify-service-api` | `langbot/dify-agent` | `plugin:langbot/dify-agent/default` |
| `n8n-service-api` | `langbot/n8n-agent` | `plugin:langbot/n8n-agent/default` |
| `coze-api` | `langbot/coze-agent` | `plugin:langbot/coze-agent/default` |
| - | `langbot/acp-agent-runner` | `plugin:langbot/acp-agent-runner/default` |
| - | `langbot/claude-code-agent` | `plugin:langbot/claude-code-agent/default` |
| - | `langbot/codex-agent` | `plugin:langbot/codex-agent/default` |
| `dashscope-app-api` | `langbot/dashscope-agent` | `plugin:langbot/dashscope-agent/default` |
| `deerflow-api` | `langbot/deerflow-agent` | `plugin:langbot/deerflow-agent/default` |
| `langflow-api` | `langbot/langflow-agent` | `plugin:langbot/langflow-agent/default` |
| `tbox-app-api` | `langbot/tbox-agent` | `plugin:langbot/tbox-agent/default` |
| `weknora-api` | `langbot/weknora-agent` | `plugin:langbot/weknora-agent/default` |
| `local-agent` | `langbot-team/LocalAgent` | `plugin:langbot-team/LocalAgent/default` |
| `dify-service-api` | `langbot-team/DifyAgent` | `plugin:langbot-team/DifyAgent/default` |
| `n8n-service-api` | `langbot-team/N8nAgent` | `plugin:langbot-team/N8nAgent/default` |
| `coze-api` | `langbot-team/CozeAgent` | `plugin:langbot-team/CozeAgent/default` |
| - | `langbot-team/ACPAgentRunner` | `plugin:langbot-team/ACPAgentRunner/default` |
| - | `langbot-team/ClaudeCodeAgent` | `plugin:langbot-team/ClaudeCodeAgent/default` |
| - | `langbot-team/CodexAgent` | `plugin:langbot-team/CodexAgent/default` |
| `dashscope-app-api` | `langbot-team/DashScopeAgent` | `plugin:langbot-team/DashScopeAgent/default` |
| `deerflow-api` | `langbot-team/DeerFlowAgent` | `plugin:langbot-team/DeerFlowAgent/default` |
| `langflow-api` | `langbot-team/LangflowAgent` | `plugin:langbot-team/LangflowAgent/default` |
| `tbox-app-api` | `langbot-team/TboxAgent` | `plugin:langbot-team/TboxAgent/default` |
| `weknora-api` | `langbot-team/WeKnoraAgent` | `plugin:langbot-team/WeKnoraAgent/default` |
每个插件可后续提供多个 runner,但迁移目标的默认 runner 统一叫 `default`
@@ -115,7 +115,7 @@ Claude Code、Codex、Kimi Code 这类 runner 不一定通过 LangBot 的模型/
当前形态:
- Runner ID 示例:`plugin:langbot/acp-agent-runner/default``plugin:langbot/claude-code-agent/default``plugin:langbot/codex-agent/default`
- Runner ID 示例:`plugin:langbot-team/ACPAgentRunner/default``plugin:langbot-team/ClaudeCodeAgent/default``plugin:langbot-team/CodexAgent/default`
- Runner 可通过 ACP、远端 daemon、本机 subprocess 或外部 HTTP API 调用 harnessharness 的安装、登录态、workspace 和 provider-native 权限由该运行环境负责。
- Runner 会把当前 LangBot `run_id`、可访问资源摘要和 gateway 使用规则注入本次消息;harness 通过 gateway 回填 `run_id` 后访问 LangBot 资产。
- 外部 session id / workspace / checkpoint 写回 Host state 或 plugin storage,后续轮次可复用目标 harness 会话。
@@ -126,7 +126,7 @@ Claude Code、Codex、Kimi Code 这类 runner 不一定通过 LangBot 的模型/
## 8. 发布和安装策略
最终 LangBot 安装/升级时需保证官方 runner 插件可用,可选方案:首次启动检测缺失并提示安装;打包发行版预装;migration 前检查插件存在性。当前分支未发布,因此不把历史配置兼容旧内置 runner fallback 写入运行时协议面。建议顺序:开发阶段用本地路径插件 → 发布前支持 marketplace 安装 → 若发布升级需要迁移历史配置,再在 release gate 中实现一次性 migration 并要求官方插件已可用
最终 LangBot 安装/升级时需保证官方 runner 插件可用,可选方案:首次启动检测缺失并提示安装,或由用户从 marketplace 安装。当前分支未发布,因此不保留历史 Pipeline Agent 配置兼容旧内置 runner fallback,也不把旧 Pipeline 内的 Agent 配置迁移成独立 Agent。4.x 只读取 `ai.runner.id``ai.runner_config[id]`;升级后由用户选择或安装需要的 AgentRunner
## 9. 验收标准
+10 -9
View File
@@ -33,8 +33,8 @@ Protocol v1 **不定义**
| AgentRunAPIProxy | AgentRunner 访问 Host 能力的受限 API。 |
| AgentBinding | Host 内部的事件到 runner 绑定配置,不直接暴露给 SDK(见 HOST_SDK §4.2)。 |
产品层 `Agent` 替代旧 Pipeline 承载 agent 配置:bot / IM channel
绑定一个 Agent,一个 Agent 可以被多个 bot / channel 复用。Host 内部的
产品层同时保留 Pipeline 与独立 `Agent`:现有 Pipeline 不迁移为 Agent
用户可以新建 Agent 并绑定到 bot / IM channel,一个 Agent 可以被多个 bot / channel 复用。Host 内部的
`AgentBinding` 是一次事件运行前解析出的有效绑定,只影响 Host 构造出的
`ctx.config``ctx.resources``ctx.context``ctx.delivery`。SDK 不需要知道
Agent / binding 的持久化形态。
@@ -700,11 +700,12 @@ Host 不负责业务编排:不拼接全量历史、不替 runner 做 prompt as
> 发布级路径隔离、MCP allowlist、secret redaction、配额、workspace 清理等**不属于** v1 协议闭环,是生产默认启用前的 release gate,见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
## 12. Pipeline Adapter 边界
## 12. Pipeline AI Stage Adapter 边界
Pipeline 是当前入口 adapter,不是协议中心。目标产品模型中 Agent 会替代
Pipeline 承载 runner config、resource policy 和 delivery policy;当前 Query
entry adapter 只是迁移桥。它负责:
Pipeline 与 Agent 是 EBA 中平级的处理器:Pipeline 处理消息事件并执行完整
Stage 链,Agent 处理其声明支持的消息或非消息事件。本协议只约束 AgentRunner
调用,因此 Pipeline 仅在 AI Stage 调用 runner 时进入 Query entry adapter
该适配不会把 Pipeline 变成 Agent,也不会创建或更新持久 Agent。adapter 负责:
-`Query` 构造 `AgentEventContext` 和临时 `AgentBinding`(见 HOST_SDK §4.2)。
- 从当前 Agent/runner config 构造 `ctx.config`
@@ -719,9 +720,9 @@ entry adapter 只是迁移桥。它负责:
## 13. 已确认约束
- v1 / EBA 主线`one event -> one AgentBinding -> one run_id -> one runner`
- 一个 bot / IM channel 在同一时间只绑定一个负责 agentic 处理的 Agent;一个 Agent 可以被多个 bot / channel 复用。
- 如果配置层出现多个匹配 AgentBindingBindingResolver 必须按明确规则选出一个或拒绝配置,不应默认 fan-out。
- EBA 路由层`one event -> one Processor target (Pipeline | Agent)`;同一 bot / channel 可以让不同事件绑定不同类型的处理器
- 进入 AgentRunner Protocol 后,调用基数是 `one AgentBinding -> one run_id -> one runner`。这既适用于独立 Agent,也适用于 Pipeline AI Stage 的单次 runner 调用。
- 一个 Agent 可以被多个 bot / channel 复用。如果 Agent 分支出现多个匹配 bindingBindingResolver 必须按明确规则选出一个或拒绝配置,不应默认 fan-out。
- observer agent、多 runner fan-out、并行裁决、result 合并等能力需要单独设计 delivery、state、platform action 和 audit 语义,不属于当前 v1 契约。
- `AgentRunnerDescriptor.source` 只允许 `plugin`Host 内置 adapter 不能作为 runner source 绕过插件/runtime/proxy 权限链。
- `ctx.resources` 与 proxy action 校验必须来自同一个 run authorization snapshotruntime handler 不应重新执行资源裁剪。
+7 -7
View File
@@ -17,8 +17,7 @@
**本分支目标:AgentRunner 外化 / 插件化基础设施**
本分支只做 LangBot 作为 Agent Host 的基础能力建设,为后续用 `Agent`
替代 Pipeline 承载 agent 配置打底:
本分支只做 LangBot 作为 Agent Host 的基础能力建设,让现有 Pipeline 与用户新建的独立 `Agent` 都能调用插件化 AgentRunner;不负责把两者做持久化迁移:
- LangBot 与 SDK 的稳定协议合同(Protocol v1
- Host-side `AgentEventEnvelope` / `AgentBinding` 模型
@@ -45,15 +44,15 @@ EventGateway / EventRouter 在本文档中描述为 **external EBA branch integr
## 目标产品模型
未来产品层应把 `Agent` 理解为 Pipeline 的替代物:原先 bot 绑定 PipelinePipeline 携带 agent/provider/RAG/tool 等配置;后续应改为 bot 或 IM channel 绑定一个 AgentAgent 携带 runner id、runner config、resource/state/delivery policy 等 agent 配置
产品层同时保留 Pipeline 与独立 `Agent`。现有 Pipeline 保持原实体和执行链,也可继续被 bot 绑定;新建 Agent 则携带 runner id、runner config、resource/state/delivery policy 等配置,并可被多个 bot / IM channel 复用。统一产品列表可以聚合展示两类处理器,但不会把 Pipeline 或其内嵌 runner 配置自动迁移成 Agent;用户需要 Agent 时自行新增并绑定
调度基数、Agent 复用、插件实例无状态、Pipeline adapter 和 fan-out 边界的规范来源是 [PROTOCOL_V1.md](./PROTOCOL_V1.md) §13;README 不复写这些约束。
## 当前入口关系
## Pipeline 与 AgentRunner 的关系
**当前 Pipeline 是入口 adapter,不再是 agent runner 设计核心**
**Pipeline 与 Agent 是 EBA 中平级的处理器;`QueryEntryAdapter` 只适配 Pipeline 内部的 AgentRunner 调用**
主入口仍可由 Pipeline 触发,但内部已转换成 event-first path`run_from_query()``QueryEntryAdapter``Query` 转换为 `AgentEventEnvelope` + `AgentBinding`,再委托到统一的 `run(event, binding, ...)`Pipeline path 因此获得了 event-first host capabilitiesEventLog / Transcript / PersistentStateStore 写入,History / Event / State pull API 和 sandbox/workspace 文件读写能力可用)
EBA 先根据 `target_type` 选择 Pipeline 或 Agent。Pipeline 目标执行完整 Stage 链;当 Pipeline 的 AI Stage 调用 runner 时,`run_from_query()``QueryEntryAdapter``Query` 转换为 `AgentEventEnvelope` + `AgentBinding`,再委托到统一的 `run(event, binding, ...)`Agent 目标则直接从自己的持久配置构造 binding。两条路径可以复用同一套 AgentRunner Host capabilities,但 Pipeline 本身不会被投影或持久化为 Agent
下一轮测试路径、状态定义和 smoke 记录见 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md)。
@@ -62,8 +61,9 @@ EventGateway / EventRouter 在本文档中描述为 **external EBA branch integr
| 术语 | 含义 |
| --- | --- |
| Protocol v1 | Host 调用 AgentRunner 的 runner 可见合同:discovery、`AgentRunContext`、result stream、Host pull API 和错误模型。 |
| Processor | EBA 的处理器上位概念;当前平级类型为 Pipeline 与 Agent。 |
| Agent | 目标产品层配置对象,保存 runner id、runner config 和资源/状态/投递策略;不等于插件实例。 |
| AgentConfig | Host 内部迁移期配置投影,由当前 Pipeline config 或未来持久 Agent 生成。 |
| AgentConfig | Host 内部的单次 AgentRunner 调用配置投影,由 Pipeline AI Stage 或持久 Agent 生成;投影本身不会创建 Agent。 |
| AgentBinding / binding | Host 在一次事件运行前解析出的有效绑定,决定调用哪个 runner 以及带什么策略。 |
| envelope | Host 内部事件封装,即 `AgentEventEnvelope`runner 看到的是由它投影出的 `ctx.event`。 |
| descriptor / manifest | runner discovery 的能力和配置描述;manifest 来自插件,descriptor 是 Host 校验后的注册表视图。 |
@@ -532,7 +532,7 @@ Tests: 40+ 个文件
## 12. 待定问题
- Host 是否需要最小持久 `Agent` / `Binding` 模型,还是继续由 Pipeline / Platform 插件投影运行期 `AgentBinding`
- 已确认:Agent 与 Pipeline 都持久存在,并由 EBA 处理器 binding 指向其中之一;Pipeline 仅在 AI Stage 调用 runner 时投影一次性 `AgentBinding`,不会充当持久 Agent 的替代物
- Platform 插件创建 run 时,是否传完整 `AgentBinding` snapshot,还是引用 Host-owned binding id。
- `AgentRunEvent` 与现有 `EventLog` / `Transcript` 的查询关系:直接 join,还是通过专门 view 聚合。
- `run.append_result` 的认证粒度:runner plugin identity、run token、scoped capability token,或 SDK runtime 内部 channel。
@@ -16,7 +16,7 @@ local-agent 已移植 Pi 的事件生命周期、并行工具语义、hook 扩
### 1.1 问题
IM 场景下用户在 agent 运行中追加消息非常常见(补充信息、纠正方向、"算了别查了")。
当前主线是 `one event -> one AgentBinding -> one run_id -> one runner`
EBA 先按事件选择一个 Pipeline 或 Agent 处理器;进入 AgentRunner 后,当前调用链是 `one AgentBinding -> one run_id -> one runner`
PROTOCOL_V1 §13):同会话的新消息要么等待当前 run 结束后触发新 run,
要么并发触发独立 run。两种行为都无法把新消息送进**正在执行的 tool loop**
用户体验是"agent 自顾自跑完过期任务,然后才看到新消息"。
+2 -2
View File
@@ -36,8 +36,8 @@
| Runner | 状态 | 最近证据 |
| --- | --- | --- |
| `plugin:langbot/local-agent/default` | Unit-pass; UI smoke pending | 2026-06-10 本地 pytest / ruff 通过;WebUI smoke 由人工统一执行。 |
| `plugin:langbot/acp-agent-runner/default` / `plugin:langbot/claude-code-agent/default` / `plugin:langbot/codex-agent/default` | Unit-pass; E2E pending | 通过 runner 仓库单测覆盖 session、run_id 注入和 LangBot MCP gateway;真实 harness E2E 取决于对应运行环境、CLI/daemon 可用性和 provider 登录态。 |
| `plugin:langbot-team/LocalAgent/default` | Unit-pass; UI smoke pending | 2026-06-10 本地 pytest / ruff 通过;WebUI smoke 由人工统一执行。 |
| `plugin:langbot-team/ACPAgentRunner/default` / `plugin:langbot-team/ClaudeCodeAgent/default` / `plugin:langbot-team/CodexAgent/default` | Unit-pass; E2E pending | 通过 runner 仓库单测覆盖 session、run_id 注入和 LangBot MCP gateway;真实 harness E2E 取决于对应运行环境、CLI/daemon 可用性和 provider 登录态。 |
| Dify / n8n / Coze / DashScope / Langflow / Tbox / DeerFlow / WeKnora | Unit-pass; credential smoke optional | 2026-06-13 plugin layout / parser tests 通过;真实服务凭据 smoke 非每轮必跑。 |
## Host / SDK 验收状态
@@ -1,340 +1,342 @@
# EBA Productization and Release Plan
# EBA 产品化与发布计划
> Status: planning draft, 2026-07-01
> 状态:规划草案,2026-07-01
>
> Scope: productizing the merged AgentRunner pluginization and Event Based Agent adapter work into a product that non-technical users can start with quickly. This document focuses on product gaps, release gates, and SaaS multi-namespace tenancy. It does not introduce new protocol schema; protocol facts remain in [PROTOCOL_V1.md](./PROTOCOL_V1.md) and host model facts remain in [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md).
> 范围:将已经合并的 AgentRunner 插件化和 Event Based Agent 适配器工作产品化,使非技术用户也能快速上手。本文聚焦产品缺口、发布门禁和 SaaS 多命名空间租户能力。本文不引入新的协议 schema;协议事实仍以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) 为准,Host 模型事实仍以 [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md) 为准。
## 1. Product Direction
## 1. 产品方向
The current technical direction is correct: LangBot should treat platform input as events, resolve one effective route for each event, and invoke a processing asset through the AgentRunner host boundary. However, this is not yet a product that non-technical users can adopt without understanding internal architecture.
当前技术方向是正确的:LangBot 应该把平台输入视为事件,为每个事件解析出一个有效路由,并通过 AgentRunner Host 边界调用一个处理资产。但这还不是一个非技术用户无需理解内部架构就能采用的产品。
The product-level model should be:
产品层模型应当是:
- **Bot**: the platform connection and event routing surface. A bot owns adapter credentials, platform permissions, incoming event visibility, and the route table for those events.
- **Processor**: a reusable processing asset that can handle routed events. Current processor types are **Agent** and **Pipeline**. Future types can include **Workflow**.
- **Pipeline**: a first-class no-code message processor kept for compatibility and low-code users. It is message-only and should be bindable only to `message.*` events.
- **Agent**: a runner-backed processor for event-first processing. It can handle message and non-message events according to its declared supported event range.
- **Solution**: a future distribution/export unit containing processors, route templates, dependency manifests, variables, and docs. A solution must not include concrete bot credentials, tenant secrets, or installed UUID bindings.
- **机器人(Bot**:平台连接与事件路由入口。机器人拥有适配器凭据、平台权限、入站事件可见性,以及这些事件的路由表。
- **处理器(Processor**:可复用的事件处理资产。当前处理器类型包括 **Agent** **Pipeline**。未来可以增加 **Workflow**
- **Pipeline**:一等的无代码消息处理器,通过完整 Stage 链提供预处理、AI、后处理、扩展和输出控制。Pipeline 只处理消息,应当只能绑定到 `message.*` 事件。
- **Agent**:由 runner 驱动的事件优先处理器。Agent 可以根据自身声明的事件支持范围处理消息事件和非消息事件。
- **Solution(方案包)**:未来的分发/导出单元,包含处理器、路由模板、依赖清单、变量和文档。Solution 不应包含具体机器人凭据、租户密钥或已安装资产的 UUID 绑定。
`EBA` is an internal engineering term. It can appear in internal design documents, but it should not be visible in primary product flows. User-facing language should prefer terms such as "channel", "event routing", "processor", "message pipeline", "automation", and "route template".
`EBA` 是内部工程术语。它可以出现在内部设计文档中,但不应出现在主要产品流程里。面向用户的语言应优先使用“频道”“事件路由”“处理器”“消息流水线”“自动化”“路由模板”等表达。
## 2. Current Foundation
## 2. 当前基础
The merged branch has enough technical foundation for internal smoke testing:
已合并分支已经具备内部冒烟测试所需的技术基础:
- EBA adapters can normalize platform activity into stable host event names.
- Bots can persist `event_bindings` and route events to an Agent, Pipeline, or discard target.
- Legacy message input can be projected into the canonical `message.received` event path.
- Pipeline remains available as a message-only no-code processor.
- AgentRunner pluginization provides the host-runner contract, event-first context, result stream, and runtime integration boundary.
- Official local and external runner plugins can validate that runner behavior is no longer hard-coded into LangBot core.
- The WebUI has an Agent/processor management surface and bot-side event routing surface.
- EBA 适配器可以把平台活动规范化为稳定的 Host 事件名。
- 机器人可以持久化 `event_bindings`,并将事件路由到 AgentPipeline 或丢弃目标。
- 旧消息输入可以投射到标准的 `message.received` 事件路径。
- Pipeline 仍可作为只处理消息的无代码处理器使用。
- AgentRunner 插件化提供了 Host 与 Runner 的契约、事件优先上下文、结果流和运行时集成边界。
- 官方 local runner 和 external runner 插件可以验证 runner 行为已经不再硬编码在 LangBot Core 中。
- WebUI 已具备 Agent/处理器管理页面,以及机器人侧事件路由页面。
- 机器人事件路由已具备 dry-run 诊断、运行时状态展示,以及安全的合成测试事件派发;测试事件会走已保存的 runtime 路由,但抑制真实平台出站动作。
- MCP 工具面已暴露机器人事件路由状态查询和合成测试事件派发,便于 QA agent 或外部调试工具复用。
This is a technical convergence milestone, not a product-ready release.
这是一个技术收敛里程碑,还不是产品就绪版本。
## 3. Gap to a Non-Technical Product
## 3. 距离非技术产品的缺口
### 3.1 Conceptual Load
### 3.1 概念负担
Current users still need to understand too many internal concepts: EBA, adapter event names, runner identifiers, plugin runtime health, event patterns, priority, and binding targets. A non-technical product should guide users through intent and outcomes:
当前用户仍需要理解过多内部概念:EBA、适配器事件名、runner 标识、插件运行时健康状态、事件模式、优先级和绑定目标。面向非技术用户的产品应当通过意图和结果来引导:
- "When a message is received, reply with this processor."
- "When a new group member joins, send a welcome message."
- "When a friend request arrives, ask an Agent to decide whether to accept."
- “收到一条消息时,用这个处理器回复。”
- “有新群成员加入时,发送欢迎语。”
- “收到好友请求时,让 Agent 判断是否接受。”
Raw event patterns such as `group.member_joined` should remain available in advanced mode, but the default UI should group events by friendly names and platform capability.
`group.member_joined` 这类原始事件模式应继续保留在高级模式中,但默认 UI 应按友好名称和平台能力对事件进行分组。
### 3.2 Onboarding
### 3.2 上手路径
The first-run path needs to start from a use case, not from architecture:
首次使用路径应当从用例开始,而不是从架构开始:
1. Choose a channel.
2. Connect the account or webhook.
3. Pick an event preset supported by that channel.
4. Choose or create a processor.
5. Send a test event.
6. Read a simple run trace if it fails.
1. 选择一个频道。
2. 连接账号或 webhook
3. 选择该频道支持的事件预设。
4. 选择或创建一个处理器。
5. 发送测试事件。
6. 如果失败,阅读简单的运行轨迹。
The current product still assumes users can diagnose whether the backend, plugin runtime, box runtime, adapter, and runner plugin are all connected. That is acceptable for developers, but not for non-technical users.
当前产品仍假设用户能诊断后端、插件运行时、Box 运行时、适配器和 runner 插件是否都已连接。对于开发者这是可接受的,但对非技术用户不可接受。
### 3.3 Adapter Readiness
### 3.3 适配器就绪度
Each adapter needs a product capability manifest, not only an engineering implementation:
每个适配器都需要产品能力清单,而不仅是工程实现:
- supported event list with friendly labels;
- supported outgoing actions;
- required credentials and setup steps;
- local/self-host/SaaS availability;
- test signal availability;
- deprecated/legacy status;
- known limitations.
- 支持的事件列表及友好标签;
- 支持的出站动作;
- 所需凭据和配置步骤;
- 本地部署、自托管、SaaS 可用性;
- 测试信号可用性;
- 废弃/遗留状态;
- 已知限制。
Deprecated adapters should be clearly marked as "deprecated" or "legacy" in the product. New event-based adapters should be described by channel name and capability, not by the EBA acronym.
废弃适配器应在产品中明确标记为“已废弃”或“遗留”。新的事件型适配器应按频道名称和能力描述,而不是使用 EBA 缩写。
### 3.4 Processor UX
### 3.4 处理器体验
The Agent page should manage reusable processors, not make users think about all event routing decisions at once.
处理器页面应管理可复用的 Agent 与 Pipeline,而不是让用户一次性理解所有事件路由决策。
- Agent creation should provide opinionated runner templates.
- Pipeline creation should remain a no-code message pipeline path.
- Future Workflow creation can be introduced as another processor type when execution semantics are stable.
- Supported event range should be shown as capability information and advanced constraints, not as the main creation concept.
- Dependency health should be visible: runner plugin installed, runtime connected, required model configured, required resource accessible.
- 创建 Agent 时应提供有倾向性的 runner 模板。
- 创建 Pipeline 时应继续保持无代码消息流水线路径。
- 未来 Workflow 的执行语义稳定后,可以作为另一种处理器类型引入。
- 支持的事件范围应作为能力信息和高级约束展示,而不是作为创建流程的主要概念。
- 依赖健康状态应可见:runner 插件是否安装、运行时是否连接、所需模型是否配置、所需资源是否可访问。
### 3.5 Bot Event Routing UX
### 3.5 机器人事件路由体验
The Bot page should be the primary place for platform-specific event routing because platform events are easiest to understand in the context of the connected channel.
机器人页面应成为平台特定事件路由的主要配置位置,因为平台事件在已连接频道的上下文中最容易被用户理解。
Minimum product requirements:
最低产品要求:
- friendly event selector generated from adapter capability;
- target selector filtered by event compatibility;
- Pipeline hidden for non-message events;
- conflict warnings for overlapping routes;
- priority explained visually rather than as a raw number first;
- route test button that can inject or replay a sample event;
- per-route status showing last matched run and last failure reason;
- safe fallback route, including explicit discard.
- 基于适配器能力生成友好的事件选择器;
- 目标选择器按事件兼容性过滤;
- 对非消息事件隐藏 Pipeline
- 对重叠路由给出冲突警告;
- 优先级先用视觉方式解释,而不是首先展示原始数字;
- 提供路由测试按钮,可以注入或重放样例事件;
- 每条路由展示状态,包括最近一次匹配的 run 和最近失败原因;
- 提供安全的兜底路由,包括显式丢弃。
### 3.6 Observability
### 3.6 可观测性
Non-technical users need a short run trace rather than raw logs:
非技术用户需要的是简短运行轨迹,而不是原始日志:
```text
Event received -> Route matched -> Processor started -> Action delivered
收到事件 -> 命中路由 -> 启动处理器 -> 动作已投递
```
When something fails, the UI should point to the failing layer:
当失败发生时,UI 应指出失败层级:
- channel not connected;
- event unsupported by adapter;
- no route matched;
- processor disabled;
- runner plugin unavailable;
- model/resource missing;
- delivery permission denied.
- 频道未连接;
- 适配器不支持该事件;
- 没有路由命中;
- 处理器已禁用;
- runner 插件不可用;
- 模型/资源缺失;
- 投递权限被拒绝。
### 3.7 Documentation and Templates
### 3.7 文档和模板
The release needs product docs and templates for common scenarios:
发布需要面向产品场景的文档和模板:
- customer service bot;
- group welcome and moderation;
- friend request review;
- Dify-backed external Agent;
- local Agent with LangBot model and knowledge base;
- message Pipeline for compatibility.
- 客服机器人;
- 群欢迎和群管理;
- 好友请求审核;
- Dify 支持的外部 Agent
- 使用 LangBot 模型和知识库的本地 Agent;
- 用于多阶段消息处理的 Pipeline。
The docs should describe the product model first and expose internal terms only in advanced architecture sections.
文档应先描述产品模型,只在高级架构章节中暴露内部术语。
## 4. Recommended UX Boundary
## 4. 推荐 UX 边界
The previous "put all event orchestration in Agent" direction should be narrowed. The better boundary is:
之前“把所有事件编排都放进 Agent”的方向应当收窄。更好的边界是:
- **Bot page owns event routing**, because the event surface is platform-specific and users naturally expect channel behavior to be configured on the bot.
- **Agent page owns processor assets**, because processors should be reusable across bots and can later be packaged into solutions.
- **Pipeline remains a processor type**, not a historical object hidden behind Agent terminology.
- **机器人页面负责事件路由**,因为事件面是平台特定的,用户也自然会在机器人上配置频道行为。
- **处理器页面负责处理器资产**,因为 Agent 与 Pipeline 都应能跨机器人复用,并且未来可以被打包进 Solution
- **Pipeline 保持为一种处理器类型**,而不是隐藏在 Agent 术语背后的历史对象。
This gives a lower mental load:
这样可以降低心智负担:
- A user asks "what should this bot do when something happens?" on the Bot page.
- A user asks "what logic do I want to reuse?" on the Agent page.
- 用户在机器人页面问:“当这个机器人遇到某件事时,应该做什么?”
- 用户在处理器页面问:“我想复用什么处理逻辑?”
It also supports the requirement that different events on the same bot can use different processor types: one event can use Pipeline, another can use Agent, and a future event can use Workflow.
这也支持同一个机器人上的不同事件使用不同处理器类型:一个事件可以使用 Pipeline,另一个事件可以使用 Agent,未来另一个事件可以使用 Workflow
## 5. Future Export, Distribution, and Import Unit
## 5. 未来导出、分发和导入单元
Export/import is not in the current implementation scope, but the product boundary should not block it.
导出/导入不在当前实现范围内,但产品边界不应阻塞它。
The correct future distribution unit is **Solution**, not Bot and not Agent alone.
正确的未来分发单元是 **Solution**,不是机器人,也不是单独的 Agent。
A Solution should contain:
Solution 应包含:
- processors: Agent, Pipeline, future Workflow definitions;
- route templates: event patterns, friendly names, target logical references, default priority, and optional conditions;
- dependency manifest: required runner plugins, adapter capability requirements, models, tools, and resources;
- variables: user-provided values such as API keys, channel choices, model selections, and prompt parameters;
- docs: setup intent and expected behavior.
- 处理器:AgentPipeline、未来 Workflow 定义;
- 路由模板:事件模式、友好名称、目标逻辑引用、默认优先级和可选条件;
- 依赖清单:所需 runner 插件、适配器能力要求、模型、工具和资源;
- 变量:用户提供的值,例如 API key、频道选择、模型选择和 prompt 参数;
- 文档:配置意图和预期行为。
A Solution should not contain:
Solution 不应包含:
- concrete bot credentials;
- installed runtime tokens;
- tenant or namespace UUIDs;
- secrets;
- raw platform account identifiers;
- resolved bot event binding UUIDs.
- 具体机器人凭据;
- 已安装运行时 token
- 租户或命名空间 UUID
- 密钥;
- 原始平台账号标识;
- 已解析的机器人事件绑定 UUID
During import, route templates should be resolved inside the target namespace after the user chooses a bot/channel and grants required permissions.
导入时,应在目标命名空间内解析路由模板。用户需要先选择机器人/频道,并授予所需权限。
## 6. SaaS Multi-Namespace Architecture
## 6. SaaS 多命名空间架构
The product must support a multi-namespace SaaS architecture before public SaaS release. The event routing model is sensitive because adapters, credentials, processors, runtimes, state, and logs all cross trust boundaries.
产品在公开 SaaS 发布前必须支持多命名空间 SaaS 架构。事件路由模型很敏感,因为适配器、凭据、处理器、运行时、状态和日志都会跨越信任边界。
### 6.1 Namespace Model
### 6.1 命名空间模型
Use a layered namespace model:
采用分层命名空间模型:
| Scope | Purpose |
| 范围 | 用途 |
| --- | --- |
| Tenant | Billing, legal ownership, top-level isolation. |
| Workspace | Collaboration and product workspace inside a tenant. |
| Namespace | Deployable isolation boundary for bots, processors, runtime tokens, resources, and logs. A self-host deployment can have one default namespace. |
| Bot scope | Platform adapter instance and event route table. |
| Processor scope | Agent, Pipeline, Workflow, and related config. |
| Runtime scope | Plugin runtime, runner registrations, leases, and execution permissions. |
| Resource scope | Knowledge bases, model credentials, files, state, and secrets. |
| 租户(Tenant | 计费、法律归属、顶层隔离。 |
| 工作空间(Workspace | 租户内的协作和产品工作区。 |
| 命名空间(Namespace | 机器人、处理器、运行时 token、资源和日志的可部署隔离边界。自托管部署可以只有一个默认命名空间。 |
| 机器人范围 | 平台适配器实例和事件路由表。 |
| 处理器范围 | AgentPipelineWorkflow 及相关配置。 |
| 运行时范围 | 插件运行时、runner 注册、lease 和执行权限。 |
| 资源范围 | 知识库、模型凭据、文件、状态和密钥。 |
Core persisted objects should carry `tenant_id`, `workspace_id`, and `namespace_id` before SaaS GA. Self-hosted deployments can seed a default tenant/workspace/namespace during migration.
在 SaaS GA 前,核心持久化对象都应携带 `tenant_id``workspace_id` `namespace_id`。自托管部署可以在迁移时种子化一个默认租户/工作空间/命名空间。
### 6.2 Event Ingress Isolation
### 6.2 事件入口隔离
Every incoming event must resolve namespace before route matching:
每个入站事件都必须先解析命名空间,再进行路由匹配:
```text
adapter ingress -> tenant/workspace/namespace resolution -> event normalization -> event log append -> route match -> processor run
```
Webhook and callback endpoints should encode or look up a namespace-scoped adapter installation. A platform event from one namespace must never match a route from another namespace, even if adapter names, bot names, or raw platform IDs collide.
Webhook 和回调端点应编码或查找命名空间范围内的适配器安装。来自一个命名空间的平台事件,绝不能匹配另一个命名空间的路由,即使适配器名称、机器人名称或原始平台 ID 发生碰撞。
### 6.3 Route Target Rules
### 6.3 路由目标规则
Runtime route bindings can use installed UUIDs, but exported route templates must use logical references. In SaaS:
运行时路由绑定可以使用已安装 UUID,但导出的路由模板必须使用逻辑引用。在 SaaS 中:
- a bot route can target only processors in the same namespace by default;
- cross-namespace targets are forbidden unless explicitly shared by policy;
- Pipeline targets remain message-only;
- route conflict evaluation is namespace-local;
- route audit events must include tenant, workspace, namespace, bot, route, target, and run identifiers.
- 默认情况下,机器人路由只能指向同一命名空间内的处理器;
- 跨命名空间目标默认禁止,除非由策略明确共享;
- Pipeline 目标仍然只允许处理消息;
- 路由冲突评估应限制在命名空间内;
- 路由审计事件必须包含租户、工作空间、命名空间、机器人、路由、目标和 run 标识。
### 6.4 Runtime and Plugin Isolation
### 6.4 运行时和插件隔离
The plugin runtime and runner registry need namespace-scoped authority:
插件运行时和 runner 注册表需要命名空间范围的授权:
- runtime registration token is scoped to one namespace or an explicitly allowed namespace set;
- runner discovery is filtered by namespace permissions;
- leases and heartbeats are namespace-scoped;
- run-scoped API tokens cannot access objects outside the run namespace;
- plugin storage, state, and temporary files include namespace in their storage key;
- shared runtime is acceptable for early SaaS only if every API call is scoped and audited;
- dedicated runtime should be available for enterprise or high-risk tenants.
- 运行时注册 token 只作用于一个命名空间,或显式允许的一组命名空间;
- runner 发现结果按命名空间权限过滤;
- lease heartbeat 按命名空间隔离;
- run-scoped API token 不能访问 run 所在命名空间之外的对象;
- 插件存储、状态和临时文件的 storage key 应包含命名空间;
- 早期 SaaS 可以接受共享运行时,但每个 API 调用都必须被 scoped 并审计;
- 企业或高风险租户应支持专用运行时。
### 6.5 Secrets, Resources, and State
### 6.5 密钥、资源和状态
Secrets and resources must not be globally addressable:
密钥和资源不能全局寻址:
- adapter credentials live in namespace-scoped secret storage;
- model provider credentials can be tenant/workspace/namespace scoped according to policy;
- knowledge resources declare which namespaces can use them;
- Agent persistent state is partitioned by tenant/workspace/namespace/processor unless a sharing policy says otherwise;
- event logs and transcripts are namespace-scoped and subject to retention policy.
- 适配器凭据存放在命名空间范围的密钥存储中;
- 模型提供商凭据可以根据策略按租户/工作空间/命名空间设定范围;
- 知识资源声明允许哪些命名空间使用;
- Agent 持久状态按租户/工作空间/命名空间/处理器分区,除非共享策略另有规定;
- 事件日志和会话记录按命名空间隔离,并受保留策略约束。
### 6.6 Marketplace and Installed Assets
### 6.6 Marketplace 和已安装资产
Marketplace package visibility is not the same as installed asset visibility:
Marketplace 包可见性不等于已安装资产可见性:
- marketplace package can be public, tenant-private, or workspace-private;
- installation creates namespace-local assets or namespace-local references;
- installed processors and route templates are copied by default to avoid accidental cross-tenant mutation;
- updates should be explicit and auditable.
- Marketplace 包可以是公开、租户私有或工作空间私有;
- 安装会创建命名空间本地资产,或命名空间本地引用;
- 已安装处理器和路由模板默认复制,避免意外跨租户变更;
- 更新必须显式且可审计。
### 6.7 SaaS Test Requirements
### 6.7 SaaS 测试要求
Before SaaS beta:
SaaS beta 前必须验证:
- tenant A event cannot match tenant B routes;
- namespace A runtime cannot claim namespace B runs;
- namespace A processor cannot read namespace B resources;
- solution import cannot preserve source tenant UUIDs or secrets;
- route replay cannot expose raw event payload from another namespace;
- admin users can inspect audit trails without accessing secret values.
- 租户 A 的事件不能匹配租户 B 的路由;
- 命名空间 A 的运行时不能 claim 命名空间 B 的 run
- 命名空间 A 的处理器不能读取命名空间 B 的资源;
- Solution 导入不能保留源租户 UUID 或密钥;
- 路由重放不能暴露另一个命名空间的原始事件 payload;
- 管理员可以查看审计轨迹,但不能访问密钥值。
## 7. Release Plan
## 7. 发布计划
### Phase 0: Technical Convergence
### Phase 0:技术收敛
Goal: prove the merged branch can run with event bindings and externalized runners.
目标:证明合并分支可以基于事件绑定和外置 runner 运行。
Required gates:
必要门禁:
- Bot event routing uses `event_bindings` as the single routing source.
- Legacy bot pipeline routing fields are removed or migrated.
- Pipeline works as a message-only processor.
- Agent runner plugin smoke tests pass with local and Dify runners.
- Migration naming and downgrade paths are valid.
- Primary UI no longer exposes "EBA" in user-facing adapter names.
- 机器人事件路由以 `event_bindings` 作为唯一路由来源。
- 旧机器人 pipeline 路由字段已移除或迁移。
- Pipeline 可作为只处理消息的处理器运行。
- Agent runner 插件冒烟测试通过,覆盖 local runner 和 Dify runner
- 迁移命名和 downgrade 路径有效。
- 主 UI 不再在面向用户的适配器名称中暴露 “EBA”。
### Phase 1: Private Beta for Technical Users
### Phase 1:面向技术用户的私有 Beta
Goal: make the system usable by contributors and early self-host adopters.
目标:让贡献者和早期自托管用户可用。
Required gates:
必要门禁:
- adapter capability matrix exists in docs and UI;
- route editor filters incompatible targets;
- runner/plugin health checks are visible;
- local Agent and Dify Agent setup has a guided path;
- per-route run trace exists;
- deprecated adapters are marked consistently;
- failure messages identify the failing layer.
- 文档和 UI 中存在适配器能力矩阵;
- 路由编辑器会过滤不兼容目标;
- runner/plugin 健康检查可见;
- local Agent Dify Agent 有引导式配置路径;
- 每条路由有运行轨迹;
- 废弃适配器被一致标记;
- 失败信息能指出失败层级。
### Phase 2: Product Beta for Non-Technical Users
### Phase 2:面向非技术用户的产品 Beta
Goal: let users complete common scenarios without reading architecture docs.
目标:让用户无需阅读架构文档也能完成常见场景。
Required gates:
必要门禁:
- first-run bot wizard starts from use case and channel;
- event presets hide raw event patterns by default;
- route simulation or test event exists;
- common processor templates exist;
- conflict warnings and fallback behavior are clear;
- docs use product language first and advanced terms later;
- SaaS namespace schema is implemented or migration-ready.
- 首次使用机器人向导从用例和频道开始;
- 事件预设默认隐藏原始事件模式;
- 存在路由模拟或测试事件能力;
- 存在常见处理器模板;
- 冲突警告和兜底行为清晰;
- 文档先使用产品语言,再介绍高级术语;
- SaaS 命名空间 schema 已实现,或已经具备迁移准备。
### Phase 3: SaaS Beta
### Phase 3SaaS Beta
Goal: run the product for multiple tenants safely.
目标:安全地为多个租户运行产品。
Required gates:
必要门禁:
- tenant/workspace/namespace fields exist on all routing, runtime, state, log, and resource facts;
- namespace-scoped runtime registration and run claim are enforced;
- namespace-scoped secrets and adapter installs are enforced;
- route matching and audit are namespace-local;
- quotas, retention, and admin audit surfaces exist;
- migration from self-host default namespace is documented.
- 所有路由、运行时、状态、日志和资源事实都具备租户/工作空间/命名空间字段;
- 命名空间范围的运行时注册和 run claim 已强制执行;
- 命名空间范围的密钥和适配器安装已强制执行;
- 路由匹配和审计限制在命名空间内;
- 配额、保留策略和管理员审计界面存在;
- 自托管默认命名空间迁移已有文档。
### Phase 4: GA
### Phase 4GA
Goal: make the product reliable for broad adoption.
目标:让产品具备广泛采用所需的可靠性。
Required gates:
必要门禁:
- solution export/import is implemented with dependency and variable resolution;
- marketplace distribution supports namespace-local installation;
- cross-namespace sharing policy is explicit;
- security review covers adapters, runtime tokens, runner APIs, secrets, logs, and route replay;
- upgrade and rollback procedures are documented;
- product telemetry measures onboarding drop-off and route failure categories.
- Solution 导出/导入已实现,并支持依赖和变量解析;
- Marketplace 分发支持命名空间本地安装;
- 跨命名空间共享策略是显式的;
- 安全评审覆盖适配器、运行时 tokenrunner API、密钥、日志和路由重放;
- 升级和回滚流程已有文档;
- 产品遥测可以衡量上手流失和路由失败类别。
## 8. Acceptance Checklist
## 8. 验收清单
A release can be considered product-ready only when:
只有满足以下条件,才可以认为发布版本达到产品就绪:
- a non-technical user can connect a supported channel, choose a scenario, bind a processor, test it, and understand the result without editing raw JSON;
- the product UI avoids internal terms such as EBA in primary flows;
- Bot page owns platform event routing and Agent page owns reusable processors;
- Pipeline remains visible as a no-code message processor and is not offered for non-message events;
- different events on one bot can route to different processor types;
- route failures are explained by layer;
- namespace isolation is enforced by schema, service checks, runtime tokens, storage keys, and tests;
- export/import, when implemented, uses Solution packages with route templates rather than concrete bot bindings.
- 非技术用户可以连接一个受支持频道,选择场景,绑定处理器,测试它,并在不编辑原始 JSON 的情况下理解结果;
- 产品 UI 在主要流程中避免使用 EBA 这类内部术语;
- 机器人页面负责平台事件路由,处理器页面负责可复用的 Agent 与 Pipeline
- Pipeline 仍作为无代码消息处理器可见,并且不会出现在非消息事件目标中;
- 同一个机器人的不同事件可以路由到不同处理器类型;
- 路由失败能按层级解释;
- 命名空间隔离通过 schemaservice check、运行时 tokenstorage key 和测试强制执行;
- 导出/导入实现后,使用带路由模板的 Solution 包,而不是具体机器人绑定。
## 9. Open Decisions
## 9. 待决策问题
- Final user-facing name for the combined processor surface: "Agent", "Processor", or another term.
- Whether Workflow should be a separate persisted processor type or an Agent runner category.
- Whether SaaS namespaces should map one-to-one to workspaces initially, or whether advanced tenants need multiple namespaces per workspace from the first SaaS beta.
- Which adapters are allowed in SaaS shared runtime and which require dedicated runtime isolation.
- Exact package format for future Solution export/import.
- 组合处理器入口统一使用 “Processor / 处理器”;Agent 与 Pipeline 是其中平级的类型。
- Workflow 应作为独立持久化处理器类型,还是作为 Agent runner 类别。
- SaaS 命名空间初期是否与工作空间一一映射,还是高级租户在首个 SaaS beta 就需要一个工作空间下多个命名空间。
- 哪些适配器允许在 SaaS 共享运行时中运行,哪些需要专用运行时隔离。
- 未来 Solution 导出/导入的确切包格式。