feat(runner): unify plugin execution across agents and event processors

This commit is contained in:
RockChinQ
2026-09-10 18:04:38 +08:00
parent 8903a40c41
commit f24a7c9bb2
223 changed files with 4091 additions and 3068 deletions
@@ -1,8 +1,8 @@
# Agent-owned Context 协议设计
本文档描述插件化 AgentRunner 场景下的上下文边界**设计理由**。结论先行:LangBot 不应成为最终 agentic context manager;它提供 context substrateAgentRunner 或其背后的 runtime 自己决定如何管理历史、压缩、召回和 KV cache。
本文档描述插件化 Runner 场景下的上下文边界**设计理由**。结论先行:LangBot 不应成为最终 agentic context manager;它提供 context substrateRunner 或其背后的 runtime 自己决定如何管理历史、压缩、召回和 KV cache。
> 涉及的数据结构(`AgentRunContext`、`ContextAccess`、`AgentRunAPIProxy` 等)唯一定义在 [PROTOCOL_V1.md](./PROTOCOL_V1.md)。本文只讲语义和约束,不重抄 schema。
> 涉及的数据结构(`RunnerContext`、`ContextAccess`、`RunnerAPIProxy` 等)唯一定义在 [PROTOCOL_V1.md](./PROTOCOL_V1.md)。本文只讲语义和约束,不重抄 schema。
## 1. 设计原则
@@ -18,7 +18,7 @@
### 1.2 Host 不定义通用历史窗口
历史窗口策略不是 AgentRunner 协议或 Query entry adapter 的核心概念。Host 只提供 history pull API、cursor、hard cap 和权限边界;runner 自己决定是否读取、读取多少、如何截断和压缩。
历史窗口策略不是 Runner 协议或 Query entry adapter 的核心概念。Host 只提供 history pull API、cursor、hard cap 和权限边界;runner 自己决定是否读取、读取多少、如何截断和压缩。
正确的问题不是"LangBot 每轮裁几轮历史给 agent",而是:
@@ -33,13 +33,13 @@
- `EventLog`: Host 保存原始事件、工具调用、投递结果、错误和系统事件。
- `Transcript`: Host 从 EventLog 投影出的对话视图,用于 UI、审计和按需历史读取。
- `Working context`: Agent 本轮实际送进模型或 runtime 的上下文,由 AgentRunner 决定。
- `Working context`: Agent 本轮实际送进模型或 runtime 的上下文,由 Runner 决定。
LangBot 不提供 host-side inline history window。简单 runner 如果需要历史窗口,应在 runner 内部通过 Host history API 拉取并裁剪。
## 2. Event 到来时传什么
默认 `AgentRunContext`PROTOCOL_V1 §5.2)应尽量小且稳定。默认规则:
默认 `RunnerContext`PROTOCOL_V1 §5.2)应尽量小且稳定。默认规则:
- Host MUST NOT inline full history by default.
- Host SHOULD inline only current event / input and context handles.
@@ -57,7 +57,7 @@ LangBot 不提供 host-side inline history window。简单 runner 如果需要
### 2.3 不提供 Host Inline History Window
`AgentRunContext` 不包含 `bootstrap` 字段。Host 不下发历史窗口,也不通过 Pipeline 配置决定窗口大小。runner 若需要类似 `recent_tail` 的策略,应在自己的 manifest/config schema 中声明参数,并在 runner 内部通过 history API 读取、裁剪和压缩。Host 只负责权限、分页、hard cap 和事实源。
`RunnerContext` 不包含 `bootstrap` 字段。Host 不下发历史窗口,也不通过 Pipeline 配置决定窗口大小。runner 若需要类似 `recent_tail` 的策略,应在自己的 manifest/config schema 中声明参数,并在 runner 内部通过 history API 读取、裁剪和压缩。Host 只负责权限、分页、hard cap 和事实源。
## 3. ContextAccess 的作用
@@ -65,7 +65,7 @@ LangBot 不提供 host-side inline history window。简单 runner 如果需要
## 4. Agent 如何获取更多上下文
所有 API 都走 `AgentRunAPIProxy`PROTOCOL_V1 §8),由 host 用 `run_id` 校验。
所有 API 都走 `RunnerAPIProxy`PROTOCOL_V1 §8),由 host 用 `run_id` 校验。
外部 harness 不能直接访问 LangBot 资源。无论是 history、event、state、model、tool、knowledge base,还是 LangBot skills,都必须通过 SDK runtime 转发到 Host API,并由 Host 按 active `run_id`、runner identity、binding resource policy 和 caller plugin identity 校验。当前运行文件进入授权 sandbox/workspace 后,再由 runner 用 read/write/exec 类工具按需访问。harness 自己的 native tools 只属于 harness 执行环境,不能绕过 SDK runtime 访问 LangBot 内部资源。
@@ -109,7 +109,7 @@ Claude Code、Codex、Kimi Code 这类 runtime 通常已有自己的 session、
- `agent-context.json`:结构化 JSON,包含 `run_id``event``actor``subject``input``delivery``resources``context``state``runtime`
- `LANGBOT_CONTEXT.md`:人类可读摘要。
- `resources`:只包含本次 run 授权后的资源句柄和能力摘要,不暴露 Host 内部私有对象、secret 或资源内容。
- `skills`LangBot skills 不是直接投影给 harness native tool loop 的文件能力,而是**一组被授权的 tool**。发现走 `list_skills`(或 `langbot_list_assets` 增加 skills 一类),激活/注册走 `activate` / `register_skill`,包内操作走 native exec/read/write,统一通过 `ctx.resources.tools``AgentRunAPIProxy` 或 SDK-owned MCP bridge 暴露。Host 不向 prompt 注入 skill 索引(无 progressive-disclosure 注入);harness 通过调用发现工具主动查询 skill 清单。`agent-context.json``skills` 字段仅作发现工具的数据来源与可选 `suggested_skill_prompt` 的输入。
- `skills`LangBot skills 不是直接投影给 harness native tool loop 的文件能力,而是**一组被授权的 tool**。发现走 `list_skills`(或 `langbot_list_assets` 增加 skills 一类),激活/注册走 `activate` / `register_skill`,包内操作走 native exec/read/write,统一通过 `ctx.resources.tools``RunnerAPIProxy` 或 SDK-owned MCP bridge 暴露。Host 不向 prompt 注入 skill 索引(无 progressive-disclosure 注入);harness 通过调用发现工具主动查询 skill 清单。`agent-context.json``skills` 字段仅作发现工具的数据来源与可选 `suggested_skill_prompt` 的输入。
- `MCP config`:只投影 per-run、scoped 的 SDK-owned bridge 或外部 MCP 连接配置;LangBot 资源访问必须回到 SDK runtime / Host API,不允许 harness 通过自带 MCP/native tool 直接读 Host 内部资源。
- `state pointers`:外部 session id、working directory、checkpoint 等小型 JSON 状态通过 Host state API 保存。
@@ -134,7 +134,7 @@ Host 只给当前事件、当前输入和 context handles。Runner 是否能拉
稳定 session key 的用途是隔离外部 runtime 的 resume/cache/state,不是改变 PROTOCOL_V1 §13 定义的 Agent 复用和 dispatch 边界。只有当某个外部 harness 的同一 native session 不支持并发 turn 时,runner 或 future runtime control plane 才应按 external session key 做 turn-level 串行化。
对长期运行的 external harness / daemon,推荐运行形态是 reader 与 writer 分离:一个 session reader 独占读取 stdout/SSE/native event stream,并把 native event 转成 `AgentRunResult` 或 task progress;用户输入只作为 turn write 进入该 session。当前一次性 CLI subprocess runner 可以继续在单次 `run(ctx)` 内同步收集 stdout,但后续改成长连接时不应让多个 request 同时读取同一 native stream。
对长期运行的 external harness / daemon,推荐运行形态是 reader 与 writer 分离:一个 session reader 独占读取 stdout/SSE/native event stream,并把 native event 转成 `RunnerResult` 或 task progress;用户输入只作为 turn write 进入该 session。当前一次性 CLI subprocess runner 可以继续在单次 `run(ctx)` 内同步收集 stdout,但后续改成长连接时不应让多个 request 同时读取同一 native stream。
## 7. Host guardrail
@@ -1,4 +1,4 @@
# Agent Runner QA 指南
# Runner QA 指南
本文档是 agent-runner 插件化下一轮测试的唯一 QA 入口。它合并并取代旧的 Phase 1 验收矩阵与 2026-05-18 / 2026-05-29 两份本地 QA 报告。
@@ -6,7 +6,7 @@
## 1. 测试边界
当前主线验证的是 AgentRunner Protocol v1
当前主线验证的是 Runner Protocol v1
```text
event -> binding -> runner.run(ctx) -> result stream
@@ -137,7 +137,7 @@ bin/lbs case list
通过条件:
- 用户可见回复正常。
- 后端日志显示走 `AgentRunOrchestrator` / `RUN_AGENT`
- 后端日志显示走 `AgentRunOrchestrator` / `RUN_RUNNER`
- 不走旧内置 local-agent 主执行分支。
- conversation transcript 写入用户消息和助手消息。
@@ -170,7 +170,7 @@ Smoke 前应优先保留一层轻量单测或 fixture 测试:session 创建/
步骤:
1. 确认目标 harness(例如 ACP daemon、Claude Code 或 Codex)在对应机器上可执行且已登录。
2. 绑定目标 runner,例如 `plugin:langbot-team/ACPAgentRunner/default``plugin:langbot-team/ClaudeCodeAgent/default``plugin:langbot-team/CodexAgent/default`
2. 绑定目标 runner,例如 `plugin:langbot-team/ACPRunner/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)。
本文描述当前事件如何进入 LangBot、如何在平级的 Pipeline / Agent 之间路由,以及 Agent 如何复用插件化 AgentRunner。路由逻辑由 `pkg/platform/botmgr.py::RuntimeBot` 承担;文中的 EventRouter 表示职责,不代表独立进程或同名类。
本文描述当前事件如何进入 LangBot、如何在平级的 Pipeline / Agent 之间路由,以及 Agent 如何复用插件化 Runner。路由逻辑由 `pkg/platform/botmgr.py::RuntimeBot` 承担;文中的 EventRouter 表示职责,不代表独立进程或同名类。
## 1. 设计目标
- 消息、撤回、入群、好友申请、定时任务、API 调用都能抽象为 host event。
- EventRouter 可以根据 event type、bot、workspace、conversation、actor、subject 选择一个 Pipeline 或 Agent 处理器。
- Pipeline 目标执行完整消息 Stage 链;Agent 目标通过统一 orchestrator 调用 AgentRunner。
- Pipeline 目标执行完整消息 Stage 链;Agent 目标通过统一 orchestrator 调用 Runner。
- 非消息事件不伪造成用户文本消息。
- 平台动作通过已授权的语义工具执行;结构化交互通过 `action.requested` 中的 `interaction.requested` 白名单执行。
@@ -44,7 +44,7 @@
- 入口事件用 `AgentEventEnvelope`HOST_SDK §4.1)承载;顶层字段使用 LangBot 稳定协议名,平台原始事件名和原始 payload 放 `metadata` / `raw_ref`
- EBA 持久路由通过 `event_pattern``filters``target_type``target_uuid` 选择处理器。只有 `target_type=agent`,或 Pipeline AI Stage 需要调用 runner 时,才进一步解析 `AgentBinding`HOST_SDK §4.2)。
EBA 每个事件只选择一个有效处理器;AgentRunner 调用的基数、Agent 复用和 fan-out 边界以 PROTOCOL_V1 §13 为准。
EBA 每个事件只选择一个有效处理器;Runner 调用的基数、Agent 复用和 fan-out 边界以 PROTOCOL_V1 §13 为准。
路由 scope 示例:workspace 全局、bot 级、platform channel 级、conversation / group / thread 级、user / actor 级。Pipeline 是 `message.*` 场景的一等处理器,适合需要预处理、AI、后处理、扩展和输出控制的消息链路;Agent 是 runner 驱动的一等处理器,可处理其声明支持的消息与非消息事件。二者都不会被转换成对方。
@@ -59,12 +59,12 @@ Platform Adapter canonical event
-> RuntimeBot match saved event_bindings and resolve one Processor target
-> target_type=pipeline: MessageAggregator -> QueryPool -> Pipeline stages
-> target_type=agent: resolve AgentBinding -> AgentRunOrchestrator
-> AgentRunContextBuilder -> PluginRuntimeConnector.run_agent()
-> AgentRunResult stream
-> RunnerContextBuilder -> PluginRuntimeConnector.run_runner()
-> RunnerResult stream
-> Host result delivery / authorized platform tool
```
约束: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 处理。
约束:Pipeline 和 Agent 是 EventRouter 的平级目标;Pipeline 仅接受消息事件,Agent 受其事件能力声明约束。任何 Runner 调用都必须复用现有 orchestrator,不能为 EBA 单独实现另一套 plugin runner 协议;非消息事件不能绕过 resource authorizationdelivery 和 platform action 走统一权限模型;外部 harness runner 也通过同一套 envelope/binding/context/result 协议接入。observer / fan-out / parallel arbitration 的额外语义仍按 PROTOCOL_V1 §13 处理。
## 6. 平台动作执行
@@ -84,13 +84,13 @@ Platform Adapter canonical event
## 7. 与 Context 协议的关系
EBA 事件进入 AgentRunner 时仍遵循 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md)inline 当前事件、大 payload 用 raw/staged file ref、不默认 inline 完整 history、agent 按需通过 API 拉取、Host 保留 EventLog 和权限 guardrail。非消息事件可以被投影进 Transcript,但不能强制伪装为 user messageAgentRunner 根据 event type 自己决定是否纳入模型上下文。
EBA 事件进入 Runner 时仍遵循 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md)inline 当前事件、大 payload 用 raw/staged file ref、不默认 inline 完整 history、agent 按需通过 API 拉取、Host 保留 EventLog 和权限 guardrail。非消息事件可以被投影进 Transcript,但不能强制伪装为 user messageRunner 根据 event type 自己决定是否纳入模型上下文。
## 8. 当前集成状态
当前分支已完成 EventRouter、Pipeline / Agent 平级处理器路由、Bot
`event_bindings` 持久化与 WebUI、AgentBinding 投影、路由 dry-run、合成测试事件、
运行状态和真实 OneBot 非消息事件到 Agent 的闭环。Pipeline 消息链和独立 Agent
均复用同一个 AgentRunner orchestrator / context / result 协议。
均复用同一个 Runner orchestrator / context / result 协议。
平台动作授权和结构化交互已实现,但真实平台/provider 验收不等同于单测通过。SDK 的 `platform_tools` 分类发现于 2026-09-05 检视时仍是未提交工作区改动。剩余发布工作和历史验证边界见 [STATUS.md](./STATUS.md)。通用订阅、Scheduler、Workflow 和多 Agent 串并联仍未作为产品交付。
@@ -96,4 +96,4 @@ The full regression also found Windows portability problems in the skills toolin
2. **Bounded stream pressure can fail long responses.** Two recovery runs emitted thinking and then `Streaming action consumer is too slow; response buffer full`; later recovery and six-tool runs succeeded. The error originates in the SDK's existing 128-frame response queue and is preserved in the UI. It is not a missing-tool-result or 30-second HTTP timeout. Full end-to-end flow control under sustained overload remains open; queue limits were not removed to conceal the failure.
3. Mock results verify debug behavior, not real platform credentials, permissions, delivery, or every adapter/event Cartesian combination. Already launched external tool termination timing was not independently measured. A development-branch push does not mean these remaining production release gates passed.
For reproduction, use the retained test Agent, the Mock examples in [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md), and the original welcome Agent. Local diagnostic traces and fixture artifacts are excluded from Git; they contain model responses and local runtime state. This report contains outcomes rather than raw provider reasoning or secrets.
For reproduction, use the retained test Agent, the Mock examples in [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md), and the original welcome Agent. Local diagnostic traces and fixture artifacts are excluded from Git; they contain model responses and local runtime state. This report contains outcomes rather than raw provider reasoning or secrets.
@@ -1,6 +1,6 @@
# AgentRunner 与产品扩展边界
# Runner 与产品扩展边界
更新:2026-09-05,适用于 `dev/4.11.x`。EBA、独立 Agent、Bot 事件绑定和处理器 UI 已与 AgentRunner 插件化合并。当前状态和测试证据以 [STATUS.md](./STATUS.md) 为准;runner 可见 schema 与调度基数以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) 为准。
更新:2026-09-05,适用于 `dev/4.11.x`。EBA、独立 Agent、Bot 事件绑定和处理器 UI 已与 Runner 插件化合并。当前状态和测试证据以 [STATUS.md](./STATUS.md) 为准;runner 可见 schema 与调度基数以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) 为准。
## 当前职责
@@ -9,7 +9,7 @@
| LangBot 产品层 | 独立 Agent CRUD、Pipeline、处理器工作台、Bot 事件绑定、Runner 安装与调试 | Agent 与 Pipeline 各自持久化;聚合列表不转换实体 |
| 平台层 | 适配器事件转换、能力声明、observer 广播、路由匹配、平台 API 与回复 | 路由逻辑在 RuntimeBot;不为每个入口重建 runner 协议 |
| Host Agent 底座 | envelope/binding 投影、统一编排、资源授权、run session、EventLog/Transcript/State、run/result ledger | SDK 不持有 Host 私有 Query 或数据库 |
| SDK / Plugin Runtime | typed contract、AgentRunner 组件和脚手架、proxy、MCP bridge、结果流转发、installation worker 管理 | 具体 Agent 执行策略由 Runner 插件承担 |
| SDK / Plugin Runtime | typed contract、Runner 组件和脚手架、proxy、MCP bridge、结果流转发、installation worker 管理 | 具体 Agent 执行策略由 Runner 插件承担 |
| Box Runtime | 沙盒会话、文件、托管进程、Skill、资源限制与作用域 | 不等于外部 harness 的通用托管承诺;存储统计不等于硬配额 |
## 已有能力与后续扩展
@@ -2,24 +2,24 @@
本文档描述 LangBot 作为 agent host 的内部能力与分层架构,以及 Host 内部模型。
- SDK ↔ Host 的协议数据结构(`AgentRunContext``AgentRunnerManifest``AgentRunResult``AgentRunAPIProxy` 等)的**唯一定义在** [PROTOCOL_V1.md](./PROTOCOL_V1.md);本文只引用,不重抄。
- 测试执行入口和 smoke 记录见 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md);安全发布门槛见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
- 本文定义的 Host 内部模型(`AgentEventEnvelope``AgentBinding``AgentRunnerDescriptor`)不属于 SDK 协议字段。
- SDK ↔ Host 的协议数据结构(`RunnerContext``RunnerManifest``RunnerResult``RunnerAPIProxy` 等)的**唯一定义在** [PROTOCOL_V1.md](./PROTOCOL_V1.md);本文只引用,不重抄。
- 测试执行入口和 smoke 记录见 [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md);安全发布门槛见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
- 本文定义的 Host 内部模型(`AgentEventEnvelope``AgentBinding``RunnerDescriptor`)不属于 SDK 协议字段。
## 1. 目标
LangBot 要转为 agent host,而不是内置 runner 容器:
- 接收 IM、WebUI、API 和当前 RuntimeBot 事件路由产生的事件。
- 接收 EBA 选中的 Agent 处理器,并根据事件、bot、workspace、scope 解析 AgentRunner binding。
- 发现、校验和调用插件提供的 AgentRunner。
- 接收 EBA 选中的 Agent 处理器,并根据事件、bot、workspace、scope 解析 Runner binding。
- 发现、校验和调用插件提供的 Runner。
- 为每次 run 提供受限资源、状态、存储、上下文引用和生命周期控制。
- 接收 AgentRunner 返回的事件流,投递到 IM、WebUI 或其他 output surface。
- 接收 Runner 返回的事件流,投递到 IM、WebUI 或其他 output surface。
## 2. 非目标
- 不定义 Pipeline 的 Stage 编排语义;Pipeline 是 EBA 的同级处理器,其 AI Stage 只在需要 runner 时接入本 Host 边界。
- 不要求所有 AgentRunner 依赖 LangBot 的上下文管理。
- 不要求所有 Runner 依赖 LangBot 的上下文管理。
- 不要求官方 local-agent 的旧行为反向塑造 host 协议。
- 不在 host 中实现通用 agentic prompt assembler。
- 不强制 runner 使用 LangBot state / storage;只提供可选、受控的寄宿能力。
@@ -41,17 +41,17 @@ RuntimeBot event_bindings -> one Processor target
|
v
AgentRunOrchestrator
|-- AgentRunnerRegistry
|-- RunnerRegistry
|-- AgentResourceBuilder
|-- AgentContextBuilder
|-- AgentRunSessionRegistry
|-- PersistentStateStore / EventLogStore / TranscriptStore
|-- Sandbox / workspace file tools
v
Plugin Runtime / AgentRunner
Plugin Runtime / Runner
|
v
AgentRunResult stream
RunnerResult stream
|
v
Delivery / Renderer / Platform API
@@ -91,7 +91,7 @@ class AgentEventEnvelope(BaseModel):
### 4.2 AgentConfig 与 AgentBinding
`AgentConfig` 是 Host 内部的一次 AgentRunner 调用配置投影(不暴露给 SDK)。独立 Agent 从自己的持久配置生成它;Pipeline 只在 AI Stage 调用 runner 时,由 Query entry adapter 从该 Stage 的当前配置生成它。两种来源随后都由 BindingResolver 结合事件和 scope 解析为 `AgentBinding`。Pipeline 本身不是 `AgentConfig`,该调用投影也不会创建或更新持久 Agent。
`AgentConfig` 是 Host 内部的一次 Runner 调用配置投影(不暴露给 SDK)。独立 Agent 从自己的持久配置生成它;Pipeline 只在 AI Stage 调用 runner 时,由 Query entry adapter 从该 Stage 的当前配置生成它。两种来源随后都由 BindingResolver 结合事件和 scope 解析为 `AgentBinding`。Pipeline 本身不是 `AgentConfig`,该调用投影也不会创建或更新持久 Agent。
```python
class AgentConfig(BaseModel):
@@ -106,7 +106,7 @@ class AgentConfig(BaseModel):
metadata: dict[str, Any] = {}
```
`AgentBinding` 是"什么事件调用哪个 AgentRunner、带什么 Agent 配置"的 Host 内部运行投影(不暴露给 SDK)。它是 EventRouter / 当前 QueryEntryAdapter 在一次运行前解析出的有效绑定。
`AgentBinding` 是"什么事件调用哪个 Runner、带什么 Agent 配置"的 Host 内部运行投影(不暴露给 SDK)。它是 EventRouter / 当前 QueryEntryAdapter 在一次运行前解析出的有效绑定。
```python
class AgentBinding(BaseModel):
@@ -131,12 +131,12 @@ BindingResolver 的基数、fan-out 和冲突处理约束见 PROTOCOL_V1 §13
→ runner_config、extension preference → resource_policy、output settings →
delivery_policy,但 Pipeline 仍执行并拥有完整 Stage/config 语义。该适配不会把 Pipeline 持久化为 Agent;独立 Agent 由用户自行新增和绑定。
### 4.3 AgentRunnerRegistry
### 4.3 RunnerRegistry
Registry 收集 runner descriptor(来自插件 runtime、开发期本地插件):
```python
class AgentRunnerDescriptor(BaseModel):
class RunnerDescriptor(BaseModel):
id: str
source: Literal["plugin"]
label: I18nObject
@@ -144,17 +144,17 @@ class AgentRunnerDescriptor(BaseModel):
plugin_author: str
plugin_name: str
runner_name: str
capabilities: AgentRunnerCapabilities # 见 PROTOCOL_V1 §4.3
permissions: AgentRunnerPermissions # 见 PROTOCOL_V1 §4.4
capabilities: RunnerCapabilities # 见 PROTOCOL_V1 §4.3
permissions: RunnerPermissions # 见 PROTOCOL_V1 §4.4
config_schema: list[DynamicFormItemSchema]
plugin_version: str | None = None
raw_manifest: dict[str, Any] = {}
```
职责:调用 `plugin_connector.list_agent_runners()` 拉取 runner、校验 typed `AgentRunnerManifest`、输出 descriptor、缓存 discovery 结果并提供 `refresh()`。单个插件 manifest 失败只记 warning,不影响其它 runner。`plugin:author/name/runner` 是稳定 id 格式;插件实例边界见 PROTOCOL_V1 §13。
职责:调用 `plugin_connector.list_runners()` 拉取 runner、校验 typed `RunnerManifest`、输出 descriptor、缓存 discovery 结果并提供 `refresh()`。单个插件 manifest 失败只记 warning,不影响其它 runner。`plugin:author/name/runner` 是稳定 id 格式;插件实例边界见 PROTOCOL_V1 §13。
Host 内置 runner / adapter 不能作为 `AgentRunnerDescriptor.source` 绕过插件
runtime、`run_id``ctx.resources``AgentRunAPIProxy` 权限链。若需要
Host 内置 runner / adapter 不能作为 `RunnerDescriptor.source` 绕过插件
runtime、`run_id``ctx.resources``RunnerAPIProxy` 权限链。若需要
开发期调试 adapter,应放在 Host 内部测试入口,不进入可选 runner 列表。
刷新触发点:插件安装/卸载/升级/重启后;Pipeline metadata 请求时发现缓存为空;可选 TTL(优先保证正确性)。
@@ -182,15 +182,15 @@ run(event, binding)
```text
QueryEntryAdapter / EventRouter
-> AgentRunOrchestrator.run(event, binding)
-> AgentRunnerRegistry.resolve(runner_id)
-> RunnerRegistry.resolve(runner_id)
-> AgentResourceBuilder.freeze_snapshot(binding, event)
-> AgentRunSessionRegistry.register(run_id, runner_id, snapshot)
-> AgentContextBuilder.build(event, binding, snapshot)
-> PluginRuntimeConnector.run_agent(ctx)
-> AgentRunAPIProxy action
-> PluginRuntimeConnector.run_runner(ctx)
-> RunnerAPIProxy action
-> validate active run session + caller identity + snapshot
-> Host API / Store
<- AgentRunResult stream
<- RunnerResult stream
-> apply state.updated to PersistentStateStore
-> write message.completed to Transcript
-> keep current-run files and large tool outputs in sandbox/workspace
@@ -237,11 +237,11 @@ LangBot 可提供 host-owned state 让 runner 寄宿状态(conversation / acto
- `Transcript`: 从 EventLog 投影出的对话视图,用于 UI、审计和按需历史读取。
- `Sandbox / workspace files`: 当前 run 的上传文件、平台附件、工具大结果和临时产物。Host 负责 staging 与授权边界,runner 通过 read/write/exec 类工具按需访问。
三类数据与 working context 的边界、读取约束见 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md)。AgentRunner 可读取这些能力,但不被迫使用 LangBot 作为唯一记忆系统。
三类数据与 working context 的边界、读取约束见 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md)。Runner 可读取这些能力,但不被迫使用 LangBot 作为唯一记忆系统。
### 4.8 External harness resource projection
Claude Code、Codex、Kimi Code 等外部 harness runner 可能不直接调用 LangBot 的 model/tool loop,而是把 LangBot 事件和授权资源句柄投影到自己的 harness 执行。Host 侧仍保持统一边界:Host 负责构造 event-first context、资源授权、state/storage、EventLog/Transcript、sandbox/workspace 文件边界和审计;Host 或 binding policy 决定哪些 MCP bridge、skill-backed tool、sandbox path、history/state 句柄可投影给 runnerrunner plugin 把 scoped projection 转成目标 harness 可消费形式;所有 LangBot 资源访问必须经 SDK runtime / `AgentRunAPIProxy` / SDK-owned MCP bridge 转发并接受 Host 校验;外部 harness 负责自己的 native session、tool loop、压缩、权限模式和 resume,但不能用 native tools 绕过 Host 授权。
Claude Code、Codex、Kimi Code 等外部 harness runner 可能不直接调用 LangBot 的 model/tool loop,而是把 LangBot 事件和授权资源句柄投影到自己的 harness 执行。Host 侧仍保持统一边界:Host 负责构造 event-first context、资源授权、state/storage、EventLog/Transcript、sandbox/workspace 文件边界和审计;Host 或 binding policy 决定哪些 MCP bridge、skill-backed tool、sandbox path、history/state 句柄可投影给 runnerrunner plugin 把 scoped projection 转成目标 harness 可消费形式;所有 LangBot 资源访问必须经 SDK runtime / `RunnerAPIProxy` / SDK-owned MCP bridge 转发并接受 Host 校验;外部 harness 负责自己的 native session、tool loop、压缩、权限模式和 resume,但不能用 native tools 绕过 Host 授权。
投影的具体形态(context 文件、resource handles、LangBot MCP gateway、state pointers)见 AGENT_CONTEXT_PROTOCOL §4.5;当前 code-agent harness runner 形态见 OFFICIAL_RUNNER_PLUGINS §7。发布级隔离要求见 SECURITY_HARDENING。
@@ -250,17 +250,17 @@ Claude Code、Codex、Kimi Code 等外部 harness runner 可能不直接调用 L
SDK 组件入口如下;所有数据结构定义见 PROTOCOL_V1。
```python
class AgentRunner(BaseComponent):
__kind__ = "AgentRunner"
class Runner(BaseComponent):
__kind__ = "Runner"
@classmethod
def get_config_schema(cls) -> list[dict]: ...
async def run(self, ctx: AgentRunContext) -> AsyncGenerator[AgentRunResult, None]: ...
# ctx: PROTOCOL_V1 §5.2 ; AgentRunResult: PROTOCOL_V1 §7
async def run(self, ctx: RunnerContext) -> AsyncGenerator[RunnerResult, None]: ...
# ctx: PROTOCOL_V1 §5.2 ; RunnerResult: PROTOCOL_V1 §7
```
- Manifest / capabilities / effective accessPROTOCOL_V1 §4。Capabilities 来自组件 manifest 的 `spec.capabilities`,不是 SDK 基类 classmethod。
- `AgentRunContext`PROTOCOL_V1 §5.2。`messages` / `bootstrap` 不是协议字段。
- `AgentRunResult`PROTOCOL_V1 §7。
- `AgentRunAPIProxy`PROTOCOL_V1 §8,是 runner 访问 host 能力的唯一入口,所有请求带 `run_id`
- `RunnerContext`PROTOCOL_V1 §5.2。`messages` / `bootstrap` 不是协议字段。
- `RunnerResult`PROTOCOL_V1 §7。
- `RunnerAPIProxy`PROTOCOL_V1 §8,是 runner 访问 host 能力的唯一入口,所有请求带 `run_id`
@@ -1,12 +1,12 @@
# 官方 AgentRunner 插件迁移计划
# 官方 Runner 插件迁移计划
本文档描述内置 `RequestRunner` 迁出 LangBot 后,官方 runner 插件如何组织、迁移和验收。它是 [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md) 和 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md) 的下游落地计划,不是 LangBot 宿主协议的设计前提。QA 入口和 smoke 记录见 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md)。
本文档描述内置 `RequestRunner` 迁出 LangBot 后,官方 runner 插件如何组织、迁移和验收。它是 [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md) 和 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md) 的下游落地计划,不是 LangBot 宿主协议的设计前提。QA 入口和 smoke 记录见 [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md)。
官方 `local-agent` 可以外移,也可以重写。设计重点不是保留旧内置 runner 的内部结构,而是验证一个依附 LangBot host 基础设施的官方 agent 能否完整工作。同时,LangBot host 协议必须服务 Claude Code SDK、Codex、Pi Agent SDK、外部 Agent 平台等自管 context/runtime 的 runner,不能被官方插件的实现细节绑死。
## 1. 仓库组织
官方 runner 插件与 LangBot 主仓库、SDK 仓库以不同节奏迭代:LangBot 主仓库只维护宿主协议和调度,SDK 仓库维护 AgentRunner 组件和 runtime 协议,官方 runner 插件承载业务 runner 的具体实现和第三方平台适配。
官方 runner 插件与 LangBot 主仓库、SDK 仓库以不同节奏迭代:LangBot 主仓库只维护宿主协议和调度,SDK 仓库维护 Runner 组件和 runtime 协议,官方 runner 插件承载业务 runner 的具体实现和第三方平台适配。
当前推荐"官方插件可独立发布,必要时共享 SDK helper"。开发期采用本地多目录布局:
@@ -14,7 +14,7 @@
langbot-app/
langbot-local-agent/ # plugin:langbot-team/LocalAgent/default
manifest.yaml
components/agent_runner/default.{yaml,py}
components/runner/default.{yaml,py}
langbot-agent-runner/ # 外部服务 runner 仓库
acp-agent-runner/ claude-code-agent/ codex-agent/ dify-agent/ n8n-agent/ ...
```
@@ -29,7 +29,7 @@ langbot-app/
| `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/ACPRunner` | `plugin:langbot-team/ACPRunner/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` |
@@ -48,23 +48,23 @@ langbot-app/
## 4. 每个官方插件的组件要求
每个插件至少包含一个 `AgentRunner` 组件,manifest 示例:
每个插件至少包含一个 `Runner` 组件,manifest 示例:
```yaml
apiVersion: langbot/v1
kind: AgentRunner
kind: Runner
metadata:
name: default
label: { en_US: Dify Agent, zh_Hans: Dify Agent }
description:
en_US: Run a Dify application as a LangBot AgentRunner.
zh_Hans: 将 Dify 应用作为 LangBot AgentRunner 运行。
en_US: Run a Dify application as a LangBot Runner.
zh_Hans: 将 Dify 应用作为 LangBot Runner 运行。
spec:
config: []
capabilities: # 字段语义见 PROTOCOL_V1 §4.3
streaming: true
execution:
python: { path: ./main.py, attr: DefaultAgentRunner }
python: { path: ./main.py, attr: DefaultRunner }
```
## 5. local-agent 插件方向
@@ -76,18 +76,18 @@ execution:
责任边界与 Host API 消费方式见 AGENT_CONTEXT_PROTOCOL §8。关键约束:
-`ctx.config` 读取静态绑定 `prompt`**不**读取 `ctx.adapter.extra["prompt"]`;不消费 Query entry adapter 生成的历史窗口。
- 通过 `AgentRunAPIProxy.history` 拉取 transcript,而不是依赖 host 每轮强塞历史窗口。
- 通过 `RunnerAPIProxy.history` 拉取 transcript,而不是依赖 host 每轮强塞历史窗口。
- `ctx.input.contents` 保留图片/文件等多模态内容;RAG 只替换/插入文本部分,不丢图片/文件。
- 不能绕过 `ctx.resources` 调用未授权模型、工具或知识库。
- manifest 声明功能能力、LangBot 资源 permissions 和配置表单;实际授权来自 manifest permissions 与 binding resource policy、runner config、`ctx.context.available_apis` 和 Host run session snapshot 的交集。
### 5.1 Native Execution / Skills 后续接入
本阶段不把 sandbox/skills 做成 AgentRunner 协议字段。后续 sandbox/skills 分支合并后,命令执行、文件操作、skill、MCP managed process 应先由 Host / sandbox 封装成 scoped tools,再通过 `ctx.resources.tools` 和 SDK runtime 转发暴露给 runner。这让 local-agent 只消费授权后的 Host 基础设施,而不是直接持有宿主机执行能力。
本阶段不把 sandbox/skills 做成 Runner 协议字段。后续 sandbox/skills 分支合并后,命令执行、文件操作、skill、MCP managed process 应先由 Host / sandbox 封装成 scoped tools,再通过 `ctx.resources.tools` 和 SDK runtime 转发暴露给 runner。这让 local-agent 只消费授权后的 Host 基础设施,而不是直接持有宿主机执行能力。
## 6. 外部 runner 插件要求
外部平台 runner 迁移遵循:旧配置字段尽量保持同名便于 migration 复制;输出统一转换为 `AgentRunResult`;外部 API timeout 从 runner config 读取;平台 conversation id 存 plugin storage 或 context runtime state,不依赖 LangBot 内置 conversation uuid 私有结构;流式按平台能力声明,没有流式就只发 `message.completed`
外部平台 runner 迁移遵循:旧配置字段尽量保持同名便于 migration 复制;输出统一转换为 `RunnerResult`;外部 API timeout 从 runner config 读取;平台 conversation id 存 plugin storage 或 context runtime state,不依赖 LangBot 内置 conversation uuid 私有结构;流式按平台能力声明,没有流式就只发 `message.completed`
### 6.1 Code-agent harness runner
@@ -95,7 +95,7 @@ Claude Code、Codex、Kimi Code 这类 runner 不一定通过 LangBot 的模型/
本文件只补充官方 runner 的实现要求:输入来自 `ctx.event` / `ctx.input`,不依赖 Pipeline 私有 `Query`;外部 session id / workspace / checkpoint 写入 Host state 或 plugin storage;插件实例边界见 PROTOCOL_V1 §13CLI / subprocess runner 必须处理 timeout、取消、空输出、非零退出和 stderr 映射。
实现结构应把 provider-native output 解析与 LangBot result stream 组装分开:Claude stream-json、Codex JSONL、Kimi / OpenCode 事件等只在 runner adapter 内解析,输出统一归一为 `AgentRunResult``message.completed` / `message.delta``state.updated``run.completed` / `run.failed`)。文件和工具大结果留在当前 run 的 sandbox/workspace,通过消息 metadata、attachment ref 或 path 指向。未知 native event 不应导致 run 崩溃;应记录诊断 metadata 或 warning。新增 harness 时优先补 native fixture -> `AgentRunResult` 的转换测试,再接 WebUI smoke。
实现结构应把 provider-native output 解析与 LangBot result stream 组装分开:Claude stream-json、Codex JSONL、Kimi / OpenCode 事件等只在 runner adapter 内解析,输出统一归一为 `RunnerResult``message.completed` / `message.delta``state.updated``run.completed` / `run.failed`)。文件和工具大结果留在当前 run 的 sandbox/workspace,通过消息 metadata、attachment ref 或 path 指向。未知 native event 不应导致 run 崩溃;应记录诊断 metadata 或 warning。新增 harness 时优先补 native fixture -> `RunnerResult` 的转换测试,再接 WebUI smoke。
并发约束应按外部 session 粒度表达,而不是按 Agent / runner id / 插件实例表达;Agent 复用和全局锁边界见 PROTOCOL_V1 §13。若 runner 使用 `external.session_id` / `thread_id` resume 到同一 native session,且该 harness 不支持并发 turnrunner 应按稳定 external session key 串行写入;一次性 subprocess runner 可以只在单次 `run(ctx)` 内处理,长连接/daemon runner 则应采用 reader 独占 native stream、turn writer 串行写入的结构。
@@ -111,11 +111,11 @@ Claude Code、Codex、Kimi Code 这类 runner 不一定通过 LangBot 的模型/
## 7. Code-agent harness runner 当前形态
外部 code-agent harness 由直接 runner 插件承接,例如 `acp-agent-runner``claude-code-agent``codex-agent`,每个 runner 负责把目标 harness 的 native session、workspace、MCP bridge 和输出事件转换为统一 `AgentRunResult`。本地 smoke 验收入口与记录见 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md)。
外部 code-agent harness 由直接 runner 插件承接,例如 `acp-agent-runner``claude-code-agent``codex-agent`,每个 runner 负责把目标 harness 的 native session、workspace、MCP bridge 和输出事件转换为统一 `RunnerResult`。本地 smoke 验收入口与记录见 [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md)。
当前形态:
- Runner ID 示例:`plugin:langbot-team/ACPAgentRunner/default``plugin:langbot-team/ClaudeCodeAgent/default``plugin:langbot-team/CodexAgent/default`
- Runner ID 示例:`plugin:langbot-team/ACPRunner/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,11 +126,11 @@ Claude Code、Codex、Kimi Code 这类 runner 不一定通过 LangBot 的模型/
## 8. 发布和安装策略
最终 LangBot 安装/升级时需保证官方 runner 插件可用,可选方案:首次启动检测缺失并提示安装,或由用户从 marketplace 安装。当前分支未发布,因此不保留历史 Pipeline Agent 配置兼容、旧内置 runner fallback,也不把旧 Pipeline 内的 Agent 配置迁移成独立 Agent。4.x 只读取 `ai.runner.id``ai.runner_config[id]`;升级后由用户选择或安装需要的 AgentRunner。
最终 LangBot 安装/升级时需保证官方 runner 插件可用,可选方案:首次启动检测缺失并提示安装,或由用户从 marketplace 安装。当前分支未发布,因此不保留历史 Pipeline Agent 配置兼容、旧内置 runner fallback,也不把旧 Pipeline 内的 Agent 配置迁移成独立 Agent。4.x 只读取 `ai.runner.id``ai.runner_config[id]`;升级后由用户选择或安装需要的 Runner。
## 9. 验收标准
- 每个目标 runner 都有对应官方 AgentRunner 插件和稳定 runner id;当前配置只使用 `ai.runner.id` + `ai.runner_config[id]`
- 每个目标 runner 都有对应官方 Runner 插件和稳定 runner id;当前配置只使用 `ai.runner.id` + `ai.runner_config[id]`
- LangBot 主聊天路径不再通过 `RequestRunner` 执行业务 runner。
- 官方插件测试覆盖非流式、流式、错误、timeout、配置缺失。
- `local-agent` 能完成模型 fallback、tool calling、知识库检索、多模态输入、静态绑定 prompt 消费、history API 拉取、rerank。
@@ -1,6 +1,6 @@
# Agent 工具权限
Agent 配置页展示同一次运行中可能投射给 AgentRunner 的完整工具目录:
Agent 配置页展示同一次运行中可能投射给 Runner 的完整工具目录:
- 事件级工具由 Agent 选择的事件范围自动启用。
- `allowed_platform_tools` 管理需要 Agent 自行指定目标的平台级动作。
@@ -12,7 +12,7 @@ Host 会按当前 Workspace 实时解析工具来源。未安装的插件、未
Agent 不直接持有平台适配器,也不能调用任意原始平台接口。每次运行时,Host 根据当前
事件自动加入兼容的事件级工具,并加入 `allowed_platform_tools` 中选择的平台级工具,
再与 AgentRunner 权限、当前适配器声明的 API、当前事件能够安全绑定的目标取交集,
再与 Runner 权限、当前适配器声明的 API、当前事件能够安全绑定的目标取交集,
得到 `ctx.resources.tools``tool_type=platform` 的最终工具集合。
## 两类工具
@@ -38,16 +38,16 @@ Agent 不直接持有平台适配器,也不能调用任意原始平台接口
current event type ── compatible event tools
Agent.allowed_platform_tools ── selected platform tools
├─ AgentRunner capability tool_calling is enabled
├─ AgentRunner manifest permissions.tools contains call
├─ Runner capability tool_calling is enabled
├─ Runner manifest permissions.tools contains call
├─ current adapter.get_supported_apis()
└─ current event type and frozen target are compatible
ctx.resources.tools[tool_type=platform]
├─ Local Agent: AgentRunAPIProxy.call_tool
└─ External AgentRunner: langbot_list_assets / langbot_get_tool_detail /
├─ Local Agent: RunnerAPIProxy.call_tool
└─ External Runner: langbot_list_assets / langbot_get_tool_detail /
langbot_call_tool (MCP Asset Gateway)
@@ -57,7 +57,7 @@ Host revalidates run_id, runner plugin identity, operation and frozen source
current bot adapter semantic API
```
本地和外部 AgentRunner 因此使用同一个工具名、参数 Schema 和 Host 授权快照。外部
本地和外部 Runner 因此使用同一个工具名、参数 Schema 和 Host 授权快照。外部
平台不会获得适配器对象或长期凭据;MCP 网关中的 run token 和 Host 中的 run session
都只对应当前运行。
+41 -41
View File
@@ -1,8 +1,8 @@
# LangBot AgentRunner Protocol v1
# LangBot Runner Protocol v1
本文档是 LangBot Host 与插件 SDK / Runtime / AgentRunner 之间协议合同的**唯一规范来源(single source of truth**。
本文档是 LangBot Host 与插件 SDK / Runtime / Runner 之间协议合同的**唯一规范来源(single source of truth**。
- 本文件描述当前 Protocol v1 稳定合同,不混入验收流水。当前实现状态见 [STATUS.md](./STATUS.md),测试执行入口见 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md),安全发布门槛见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
- 本文件描述当前 Protocol v1 稳定合同,不混入验收流水。当前实现状态见 [STATUS.md](./STATUS.md),测试执行入口见 [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md),安全发布门槛见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
- 本文件之外的任何文档**不得重新定义这里的数据结构**,只能引用,例如"见 PROTOCOL_V1 §4.2"。
- Host 内部模型(`AgentEventEnvelope``AgentBinding`、Descriptor、各 Store)不属于 SDK 协议,定义在 [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md)。
@@ -10,15 +10,15 @@
Protocol v1 只解决四件事:
- LangBot 如何发现插件提供的 AgentRunner。
- LangBot 如何把一次事件调用封装成 `AgentRunContext`
- AgentRunner 如何以事件流形式返回运行结果。
- AgentRunner 如何通过受限 API 访问 LangBot host 能力。
- LangBot 如何发现插件提供的 Runner。
- LangBot 如何把一次事件调用封装成 `RunnerContext`
- Runner 如何以事件流形式返回运行结果。
- Runner 如何通过受限 API 访问 LangBot host 能力。
Protocol v1 **不定义**
- LangBot 内部如何持久化 `AgentBinding`(见 HOST_SDK)。
- AgentRunner 内部如何组装 prompt、压缩历史、管理 memory(见 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md))。
- Runner 内部如何组装 prompt、压缩历史、管理 memory(见 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md))。
- 官方 runner 的具体实现(见 [OFFICIAL_RUNNER_PLUGINS.md](./OFFICIAL_RUNNER_PLUGINS.md))。
- Pipeline 的长期配置模型。
- 发布级安全 hardening 的完整实现(见 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md))。
@@ -29,8 +29,8 @@ Protocol v1 **不定义**
| --- | --- |
| LangBot Host | 事件入口、绑定解析、权限、资源、存储、生命周期、结果投递。 |
| Plugin Runtime | 加载插件,响应 Host 的 runner discovery 和 run 调用。 |
| AgentRunner | 插件提供的 agent 执行组件。 |
| AgentRunAPIProxy | AgentRunner 访问 Host 能力的受限 API。 |
| Runner | 插件提供的 agent 执行组件。 |
| RunnerAPIProxy | Runner 访问 Host 能力的受限 API。 |
| AgentBinding | Host 内部的事件到 runner 绑定配置,不直接暴露给 SDK(见 HOST_SDK §4.2)。 |
产品层同时保留 Pipeline 与独立 `Agent`:现有 Pipeline 不迁移为 Agent
@@ -39,11 +39,11 @@ Protocol v1 **不定义**
`ctx.config``ctx.resources``ctx.context``ctx.delivery`。SDK 不需要知道
Agent / binding 的持久化形态。
外部 harness runnerClaude Code、Codex、Kimi Code 等)也是 `AgentRunner`:它们消费 event-first `AgentRunContext`、返回 `AgentRunResult`,并通过 Host 授权的 state/storage API 保存跨轮次指针;当前运行文件和工具大结果进入 sandbox/workspace。它们内部可以继续使用自己的 session、tool loop、MCP、上下文压缩和权限模型。
外部 harness runnerClaude Code、Codex、Kimi Code 等)也是 `Runner`:它们消费 event-first `RunnerContext`、返回 `RunnerResult`,并通过 Host 授权的 state/storage API 保存跨轮次指针;当前运行文件和工具大结果进入 sandbox/workspace。它们内部可以继续使用自己的 session、tool loop、MCP、上下文压缩和权限模型。
## 3. 协议演进
当前 AgentRunner 合同不暴露显式 `protocol_version` 字段。协议演进先按字段级兼容规则处理:
当前 Runner 合同不暴露显式 `protocol_version` 字段。协议演进先按字段级兼容规则处理:
- 新增可选字段保持向后兼容。
- 删除字段或改变既有字段语义,需要在 SDK 发布前完成;发布后应走新的显式兼容方案。
@@ -52,35 +52,35 @@ Agent / binding 的持久化形态。
## 4. Discovery 协议
### 4.1 LIST_AGENT_RUNNERS
### 4.1 LIST_RUNNERS
Host 调用 Plugin Runtime 获取当前插件暴露的 runner 列表,请求无额外 payload。返回:
```python
class ListAgentRunnersResponse(BaseModel):
runners: list[AgentRunnerDiscovery]
class ListRunnersResponse(BaseModel):
runners: list[RunnerDiscovery]
class AgentRunnerDiscovery(BaseModel):
class RunnerDiscovery(BaseModel):
plugin_author: str
plugin_name: str
runner_name: str
manifest: AgentRunnerManifest
manifest: RunnerManifest
```
`manifest` 是 SDK typed `AgentRunnerManifest`,由 Runtime 从插件组件 manifest 解析并校验后返回。`plugin_author` / `plugin_name` / `runner_name` 保留为 transport 寻址字段;Host 以它们生成稳定 runner id,并把 `manifest.id` 校验为 `plugin:author/name/runner`。单个 runner manifest 解析失败时 Runtime/Host 记录 warning 并跳过该 runner,不影响同一插件或其它插件的 runner discovery。
`manifest` 是 SDK typed `RunnerManifest`,由 Runtime 从插件组件 manifest 解析并校验后返回。`plugin_author` / `plugin_name` / `runner_name` 保留为 transport 寻址字段;Host 以它们生成稳定 runner id,并把 `manifest.id` 校验为 `plugin:author/name/runner`。单个 runner manifest 解析失败时 Runtime/Host 记录 warning 并跳过该 runner,不影响同一插件或其它插件的 runner discovery。
### 4.2 AgentRunnerManifest
### 4.2 RunnerManifest
这里的 manifest 指 Runtime 返回给 Host 的 typed runner manifest
```python
class AgentRunnerManifest(BaseModel):
class RunnerManifest(BaseModel):
id: str
name: str
label: I18nObject
description: I18nObject | None = None
capabilities: AgentRunnerCapabilities = AgentRunnerCapabilities()
permissions: AgentRunnerPermissions = AgentRunnerPermissions()
capabilities: RunnerCapabilities = RunnerCapabilities()
permissions: RunnerPermissions = RunnerPermissions()
config_schema: list[DynamicFormItemSchema] = []
metadata: dict[str, Any] = {}
```
@@ -95,7 +95,7 @@ class AgentRunnerManifest(BaseModel):
### 4.3 Capabilities
```python
class AgentRunnerCapabilities(BaseModel):
class RunnerCapabilities(BaseModel):
streaming: bool = False
tool_calling: bool = False
knowledge_retrieval: bool = False
@@ -122,7 +122,7 @@ Capabilities 字段全部是 `bool`,未知 key 禁止进入 typed manifest。
### 4.4 Permissions 与 Effective Access
```python
class AgentRunnerPermissions(BaseModel):
class RunnerPermissions(BaseModel):
models: list[Literal["invoke", "stream", "rerank"]] = []
tools: list[Literal["detail", "call"]] = []
knowledge_bases: list[Literal["list", "retrieve"]] = []
@@ -151,7 +151,7 @@ effective_access = manifest.permissions ∩ binding.resource_policy ∩ current
1. `AgentResourceBuilder` 先用 manifest permissions 与 binding resource policy / runner config 求交,生成 `ctx.resources`
2. `AgentContextBuilder` 用 manifest permissions 与 binding state/storage policy 求交,生成 `ctx.context.available_apis`
3. `AgentRunSessionRegistry` 冻结 run-scoped resources 与 available APIs。
4. Runtime handler / `AgentRunAPIProxy` 按 active `run_id`、runner identity、caller plugin identity、resource id、scope、payload size、rate limit 和 deadline 校验每次调用。
4. Runtime handler / `RunnerAPIProxy` 按 active `run_id`、runner identity、caller plugin identity、resource id、scope、payload size、rate limit 和 deadline 校验每次调用。
反承诺:manifest permissions **只约束 LangBot 持有的资源访问**。它不承诺限制外部 harness 的 native shell、文件系统、CLI、MCP、网络或本机权限;这些能力由 operator/runtime/sandbox 另行约束,见 HOST_SDK §4.8 与 SECURITY_HARDENING。
@@ -167,7 +167,7 @@ context 边界的设计理由见 [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PRO
## 5. Run 协议
### 5.1 RUN_AGENT
### 5.1 RUN_RUNNER
Host 调用 Runtime
@@ -175,17 +175,17 @@ Host 调用 Runtime
class AgentRunRequest(BaseModel):
runner_id: str
runner_name: str
context: AgentRunContext
context: RunnerContext
```
Runtime 返回 `AgentRunResult` 异步流。底层 transport 可继续用 `plugin_author` / `plugin_name` / `runner_name` 定位组件,但协议语义以 `runner_id``context` 为准。
Runtime 返回 `RunnerResult` 异步流。底层 transport 可继续用 `plugin_author` / `plugin_name` / `runner_name` 定位组件,但协议语义以 `runner_id``context` 为准。
### 5.2 AgentRunContext
### 5.2 RunnerContext
这是 SDK 看到的**唯一权威 context 定义**。
```python
class AgentRunContext(BaseModel):
class RunnerContext(BaseModel):
run_id: str
trigger: AgentTrigger
event: AgentEventContext
@@ -361,7 +361,7 @@ class InteractionDeliveryCapabilities(BaseModel):
max_fields: int | None = None
```
Runner 使用 `AgentRunResult.interaction_requested()` 生成
Runner 使用 `RunnerResult.interaction_requested()` 生成
`action.requested(action="interaction.requested")`。Host 只能把请求投递到当前 run 冻结的
delivery targetRunner 不得通过 `target` 改写 bot、conversation 或用户。Host 为请求保存
`interaction_id -> processor/binding/conversation/expiry` 关联;平台 callback 必须先经过签名、
@@ -455,11 +455,11 @@ class AgentResources(BaseModel):
`skills` 是本次 run 中 pipeline-visible 的 skill facts`skill_name``display_name``description`)。**skill 通过统一 tool 形式消费,不是独立资源类别**:发现走 `list_skills` tool(或 `langbot_list_assets` 增加 skills 一类),激活走 `activate`,操作走 native exec/read/write。Host **不**把 skill 索引注入 system prompt,也不做 progressive-disclosure 注入;LLM 通过调用发现工具主动查询 skill 清单。Host **可选**在 ctx 提供预渲染的 `suggested_skill_prompt`(首轮延迟优化,runner 可忽略 / override),但它不是访问前提。`skills` 字段本身仅作为发现工具的数据来源与该可选预渲染的输入。
资源列表是本次 run 的授权结果。History / Event / State / Storage 访问通过 `ctx.context.available_apis` 和 Host 侧 run session 校验控制,不作为可枚举 resource list 暴露。Runner 只能通过 `AgentRunAPIProxy` 访问这些能力。当前事件的文件和工具大结果优先进入授权 sandbox/workspace,由 runner 通过 read/write/exec 类工具按需读取。
资源列表是本次 run 的授权结果。History / Event / State / Storage 访问通过 `ctx.context.available_apis` 和 Host 侧 run session 校验控制,不作为可枚举 resource list 暴露。Runner 只能通过 `RunnerAPIProxy` 访问这些能力。当前事件的文件和工具大结果优先进入授权 sandbox/workspace,由 runner 通过 read/write/exec 类工具按需读取。
## 7. Result Stream
### 7.1 AgentRunResult envelope
### 7.1 RunnerResult envelope
```python
JSONValue = str | int | float | bool | None | list["JSONValue"] | dict[str, "JSONValue"]
@@ -475,9 +475,9 @@ ResultType = Literal[
"run.failed",
]
class AgentRunResult(BaseModel):
class RunnerResult(BaseModel):
run_id: str
type: AgentRunResultType | str
type: RunnerResultType | str
data: dict[str, Any] = {}
usage: LLMTokenUsage | None = None
sequence: int | None = None
@@ -568,7 +568,7 @@ Host 必须校验 `state.updated` 的 scope、key、value 大小和 JSON 可序
{ "type": "action.requested", "data": { "action": "interaction.requested", "payload": { "interaction_id": "form_1", "kind": "choice", "title": "Approve?", "actions": [{"id": "approve", "label": "Approve", "style": "primary"}], "fallback_text": "Reply approve or reject." } } }
```
## 8. AgentRunAPIProxy
## 8. RunnerAPIProxy
所有 proxy action 必须携带 `run_id`。Host 必须校验:active run session 存在、caller plugin identity 匹配、resource 在本次 `ctx.resources` 中授权、scope 不越界、payload size / rate limit / deadline 合法。
@@ -777,7 +777,7 @@ Protocol v1 的安全边界在 Host
- 大 payload 不应塞进 result event;当前 run 的文件和工具大结果应进入授权 sandbox/workspace,由 read/write/exec 类工具按需访问。
- Host 必须记录 run_id、runner_id、action、resource、scope、result。
Host 不负责业务编排:不拼接全量历史、不替 runner 做 prompt assembly、不内置 agent memory / tool loop / 上下文压缩策略。这些由官方或第三方 AgentRunner 插件实现。
Host 不负责业务编排:不拼接全量历史、不替 runner 做 prompt assembly、不内置 agent memory / tool loop / 上下文压缩策略。这些由官方或第三方 Runner 插件实现。
外部 harness runner 的边界统一见 HOST_SDK §4.8。简言之:harness native permission mode、allowed/disallowed tools、shell/MCP 权限只是额外执行约束,不能替代 Host 对 LangBot 资源的授权。
@@ -786,7 +786,7 @@ Host 不负责业务编排:不拼接全量历史、不替 runner 做 prompt as
## 12. Pipeline AI Stage Adapter 边界
Pipeline 与 Agent 是 EBA 中平级的处理器:Pipeline 处理消息事件并执行完整
Stage 链,Agent 处理其声明支持的消息或非消息事件。本协议只约束 AgentRunner
Stage 链,Agent 处理其声明支持的消息或非消息事件。本协议只约束 Runner
调用,因此 Pipeline 仅在 AI Stage 调用 runner 时进入 Query entry adapter
该适配不会把 Pipeline 变成 Agent,也不会创建或更新持久 Agent。adapter 负责:
@@ -804,12 +804,12 @@ Stage 链,Agent 处理其声明支持的消息或非消息事件。本协议
## 13. 已确认约束
- EBA 路由层是 `one event -> one Processor target (Pipeline | Agent)`;同一 bot / channel 可以让不同事件绑定不同类型的处理器。
- 进入 AgentRunner Protocol 后,调用基数是 `one AgentBinding -> one run_id -> one runner`。这既适用于独立 Agent,也适用于 Pipeline AI Stage 的单次 runner 调用。
- 进入 Runner 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 权限链。
- `RunnerDescriptor.source` 只允许 `plugin`Host 内置 adapter 不能作为 runner source 绕过插件/runtime/proxy 权限链。
- `ctx.resources` 与 proxy action 校验必须来自同一个 run authorization snapshotruntime handler 不应重新执行资源裁剪。
- v1 不要求 Agent、AgentRunner 插件实例或 runner id 全局串行。多个 bot / channel 可复用同一个 Agent;并发隔离依赖 `run_id`、binding、conversation / thread scope 和 Host authorization snapshot。
- v1 不要求 Agent、Runner 插件实例或 runner id 全局串行。多个 bot / channel 可复用同一个 Agent;并发隔离依赖 `run_id`、binding、conversation / thread scope 和 Host authorization snapshot。
- 外部 harness runner 当前是 MVP / dev path,证明协议可接入,不代表发布级安全边界或 Docker 生产可用性完成。
## 14. 开放问题
+18 -18
View File
@@ -1,23 +1,23 @@
# Agent Runner 插件化文档入口
# Runner 插件化文档入口
本文档是 agent-runner 插件化工作的路由页。具体设计拆到独立文档中维护,避免把 LangBot 宿主架构、SDK 协议、上下文管理、EBA 接入边界和官方 runner 迁移混在同一份 README 里。
## 背景与问题
旧 runner 路径主要围绕 Pipeline / Query 和 `pkg/provider/runners` 内置实现展开,扩展外部 agent runtime 时容易把 runner 选择、上下文裁剪、资源授权和消息投递绑在同一条聊天链路里。这个分支要把 LangBot 收敛成 Agent Host:Host 负责事件、绑定、授权、事实源和结果投递;AgentRunner 作为插件或外部 harness 消费统一协议并自主管理 prompt / history / memory。
旧 runner 路径主要围绕 Pipeline / Query 和 `pkg/provider/runners` 内置实现展开,扩展外部 agent runtime 时容易把 runner 选择、上下文裁剪、资源授权和消息投递绑在同一条聊天链路里。这个分支要把 LangBot 收敛成 Agent Host:Host 负责事件、绑定、授权、事实源和结果投递;Runner 作为插件或外部 harness 消费统一协议并自主管理 prompt / history / memory。
## 文档维护原则(单一事实源)
- **协议数据结构(schema)唯一定义在 [PROTOCOL_V1.md](./PROTOCOL_V1.md)。** 其他文档不得重抄 schema,只能引用,例如"见 PROTOCOL_V1 §4.2"。
- 当前实现状态、spec 差距与 runner 验收状态归 [STATUS.md](./STATUS.md);测试执行入口归 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md),安全发布门槛归 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
- 当前实现状态、spec 差距与 runner 验收状态归 [STATUS.md](./STATUS.md);测试执行入口归 [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md),安全发布门槛归 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md)。
- Host 内部模型(`AgentEventEnvelope``AgentBinding`、Descriptor、各 Store)定义在 [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md),不属于 SDK 协议。
- 其余专题文档只讲"为什么/边界/怎么用",避免重复叙述。
## 本分支目标
**本分支目标:AgentRunner 外化 / 插件化基础设施**
**本分支目标:Runner 外化 / 插件化基础设施**
本分支只做 LangBot 作为 Agent Host 的基础能力建设,让现有 Pipeline 与用户新建的独立 `Agent` 都能调用插件化 AgentRunner;不负责把两者做持久化迁移:
本分支只做 LangBot 作为 Agent Host 的基础能力建设,让现有 Pipeline 与用户新建的独立 `Agent` 都能调用插件化 Runner;不负责把两者做持久化迁移:
- LangBot 与 SDK 的稳定协议合同(Protocol v1
- Host-side `AgentEventEnvelope` / `AgentBinding` 模型
@@ -30,7 +30,7 @@
## 当前已集成与后续扩展
截至 2026-09-05`dev/4.11.x` 已合并 EBA 与 AgentRunner 插件化。下面按当前代码划分实现边界:
截至 2026-09-05`dev/4.11.x` 已合并 EBA 与 Runner 插件化。下面按当前代码划分实现边界:
- **已实现的平台事件路由**`RuntimeBot` 负责事件转换后的 observer 广播、`event_bindings` 匹配和 Pipeline / Agent / discard 单目标分派;EventRouter 是逻辑职责,不是另一个独立服务。
- **已实现的持久化与 UI**:独立 Agent、Bot 事件绑定、处理器工作台、Runner 市场安装、事件范围与工具权限、路由诊断和调试入口。
@@ -48,22 +48,22 @@
调度基数、Agent 复用、插件实例无状态、Pipeline adapter 和 fan-out 边界的规范来源是 [PROTOCOL_V1.md](./PROTOCOL_V1.md) §13;README 不复写这些约束。
## Pipeline 与 AgentRunner 的关系
## Pipeline 与 Runner 的关系
**Pipeline 与 Agent 是 EBA 中平级的处理器;`QueryEntryAdapter` 只适配 Pipeline 内部的 AgentRunner 调用。**
**Pipeline 与 Agent 是 EBA 中平级的处理器;`QueryEntryAdapter` 只适配 Pipeline 内部的 Runner 调用。**
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。
EBA 先根据 `target_type` 选择 Pipeline 或 Agent。Pipeline 目标执行完整 Stage 链;当 Pipeline 的 AI Stage 调用 runner 时,`run_from_query()``QueryEntryAdapter``Query` 转换为 `AgentEventEnvelope` + `AgentBinding`,再委托到统一的 `run(event, binding, ...)`。Agent 目标则直接从自己的持久配置构造 binding。两条路径可以复用同一套 Runner Host capabilities,但 Pipeline 本身不会被投影或持久化为 Agent。
下一轮测试路径、状态定义和 smoke 记录见 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md)。
下一轮测试路径、状态定义和 smoke 记录见 [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md)。
## 术语表
| 术语 | 含义 |
| --- | --- |
| Protocol v1 | Host 调用 AgentRunner 的 runner 可见合同:discovery、`AgentRunContext`、result stream、Host pull API 和错误模型。 |
| Protocol v1 | Host 调用 Runner 的 runner 可见合同:discovery、`RunnerContext`、result stream、Host pull API 和错误模型。 |
| Processor | EBA 的处理器上位概念;当前平级类型为 Pipeline 与 Agent。 |
| Agent | 目标产品层配置对象,保存 runner id、runner config 和资源/状态/投递策略;不等于插件实例。 |
| AgentConfig | Host 内部的单次 AgentRunner 调用配置投影,可由 Pipeline AI Stage 或持久 Agent 生成;投影本身不会创建 Agent。 |
| AgentConfig | Host 内部的单次 Runner 调用配置投影,可由 Pipeline AI Stage 或持久 Agent 生成;投影本身不会创建 Agent。 |
| AgentBinding / binding | Host 在一次事件运行前解析出的有效绑定,决定调用哪个 runner 以及带什么策略。 |
| envelope | Host 内部事件封装,即 `AgentEventEnvelope`runner 看到的是由它投影出的 `ctx.event`。 |
| descriptor / manifest | runner discovery 的能力和配置描述;manifest 来自插件,descriptor 是 Host 校验后的注册表视图。 |
@@ -76,18 +76,18 @@ EBA 先根据 `target_type` 选择 Pipeline 或 Agent。Pipeline 目标执行完
| 文档 | 关注点 |
| --- | --- |
| [PROTOCOL_V1.md](./PROTOCOL_V1.md) | **🔒 唯一 schema 事实源**。LangBot Host 与 SDK / Runtime / AgentRunner 的协议合同:版本协商、discovery、run context、result stream、proxy actions、错误和 adapter 边界。 |
| [PROTOCOL_V1.md](./PROTOCOL_V1.md) | **🔒 唯一 schema 事实源**。LangBot Host 与 SDK / Runtime / Runner 的协议合同:版本协商、discovery、run context、result stream、proxy actions、错误和 adapter 边界。 |
| [HOST_SDK_INFRASTRUCTURE.md](./HOST_SDK_INFRASTRUCTURE.md) | LangBot 宿主能力与分层架构、Host 内部模型(`AgentEventEnvelope` / `AgentBinding` / Descriptor / 各 Store)、runner 发现、绑定、资源授权、状态、存储、生命周期和调用链。 |
| [AGENT_CONTEXT_PROTOCOL.md](./AGENT_CONTEXT_PROTOCOL.md) | Agent-owned context 方向:事件到来时 LangBot 传什么,agent 如何按需拉取更多历史 / state、如何访问 sandbox/workspace 文件,以及如何支持 KV cache 友好的上下文管理。 |
| [EXTENSION_SCOPE_MATRIX.md](./EXTENSION_SCOPE_MATRIX.md) | AgentRunner 外化与外部 EBA / Agent Platform / Runtime Control Plane 的扩展边界矩阵,说明哪些是本分支底座、哪些由外部分支接入。 |
| [EXTENSION_SCOPE_MATRIX.md](./EXTENSION_SCOPE_MATRIX.md) | Runner 外化与外部 EBA / Agent Platform / Runtime Control Plane 的扩展边界矩阵,说明哪些是本分支底座、哪些由外部分支接入。 |
| [EVENT_BASED_AGENT.md](./EVENT_BASED_AGENT.md) | 已集成的事件路由、处理器分派、平台工具和结构化交互边界。 |
| [eba-productization-release.md](./eba-productization-release.md) | EBA 适配器与 AgentRunner 插件化合并后的产品化 / 发布计划,说明非技术用户快速上手差距、Bot 与处理器边界、未来 Solution 分发标的,以及多 namespace SaaS 支持要求。 |
| [eba-productization-release.md](./eba-productization-release.md) | EBA 适配器与 Runner 插件化合并后的产品化 / 发布计划,说明非技术用户快速上手差距、Bot 与处理器边界、未来 Solution 分发标的,以及多 namespace SaaS 支持要求。 |
| [RUNTIME_CONTROL_PLANE_V2.md](./RUNTIME_CONTROL_PLANE_V2.md) | Agent Platform v2 / runtime 管控面决策:`AgentRun` / `AgentRunEvent` / run control 已作为 Host 事实源落地,最小 runtime heartbeat/claim lease 已落地;完整 runtime registry / daemon 管控仍是后续可选阶段。 |
| [OFFICIAL_RUNNER_PLUGINS.md](./OFFICIAL_RUNNER_PLUGINS.md) | 官方 runner 插件迁移,包括 local-agent 和外部 runner。它是下游落地计划,不是 LangBot 基础能力设计的前置约束。 |
| [RUN_STEERING_AND_CHECKPOINT.md](./RUN_STEERING_AND_CHECKPOINT.md) | 运行中消息注入(steering / follow-up)与压缩摘要持久化(compaction checkpoint)的设计与落地状态记录;schema 仍以 PROTOCOL_V1 为准。 |
| [STATUS.md](./STATUS.md) | 当前实现状态、spec 与实现已知差距、runner 验收状态和历史高价值记录。 |
| [PLATFORM_ACTION_TOOLS.md](./PLATFORM_ACTION_TOOLS.md) | 当前事件工具、平台动作和普通工具的配置、投射及执行授权。 |
| [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md) | Agent Runner QA 指南:保留最高价值测试路径,指导 agent 开展下一轮 WebUI / runner smoke 验证。 |
| [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md) | Runner QA 指南:保留最高价值测试路径,指导 agent 开展下一轮 WebUI / runner smoke 验证。 |
| [SECURITY_HARDENING.md](./SECURITY_HARDENING.md) | 安全发布级 hardening 的后续发布门槛:路径隔离、权限边界、secret、资源配额、MCP / skill 投影和审计。 |
## 工作拆分
@@ -103,7 +103,7 @@ EBA 先根据 `target_type` 选择 Pipeline 或 Agent。Pipeline 目标执行完
- resource authorization 与 `run_id` 级权限校验
- host-owned state / storage / event log / transcript 能力
- sandbox/workspace 文件 staging 与 read/write/exec 能力
- SDK `AgentRunner``AgentRunContext``AgentRunResult``AgentRunAPIProxy`
- SDK `Runner``RunnerContext``RunnerResult``RunnerAPIProxy`
协议合同详见 [PROTOCOL_V1.md](./PROTOCOL_V1.md)。
@@ -141,7 +141,7 @@ EBA dispatch 的基数和 fan-out 边界仍以 PROTOCOL_V1 §13 为准;新增
### 5. Runtime Control Plane v2Foundation Partial
当前 AgentRunner v1 主线仍以 `event -> binding -> runner.run(ctx) -> result stream` 为 runner 可见合同。Host 侧已经新增持久 `AgentRun` / `AgentRunEvent`、result persistence、cancel/finalize/query 等通用 run control primitives,并提供受权限保护的最小 runtime register/heartbeat/list、claim/renew/release 和 reconcile 原语。
当前 Runner v1 主线仍以 `event -> binding -> runner.run(ctx) -> result stream` 为 runner 可见合同。Host 侧已经新增持久 `AgentRun` / `AgentRunEvent`、result persistence、cancel/finalize/query 等通用 run control primitives,并提供受权限保护的最小 runtime register/heartbeat/list、claim/renew/release 和 reconcile 原语。
在这些 Host 能力之上,可以构建独立 agent 管控面插件;插件负责 UI、策略和编排体验,runtime/task 的事实源仍由 Host 持有。完整 daemon supervisor、任务唤醒/长轮询/WebSocket、跨 Host 分布式锁、provider 登录态诊断和产品化业务队列仍是后续工作。
@@ -1,10 +1,10 @@
# Agent Platform / Runtime Control Plane Decision Note
本文档记录 AgentRunner 插件化之后,LangBot 如何继续演进成 Agent Platform 基础设施层。这里讨论的是 Host capability layer,不是 `AgentRunner Protocol v2`,也不是把某个具体 Agent Platform 产品写进 LangBot core。
本文档记录 Runner 插件化之后,LangBot 如何继续演进成 Agent Platform 基础设施层。这里讨论的是 Host capability layer,不是 `Runner Protocol v2`,也不是把某个具体 Agent Platform 产品写进 LangBot core。
> 本文是当前决策版。协议数据结构仍以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) 为准;测试执行入口见 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md);扩展边界见 [EXTENSION_SCOPE_MATRIX.md](./EXTENSION_SCOPE_MATRIX.md)。
> 本文是当前决策版。协议数据结构仍以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) 为准;测试执行入口见 [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md);扩展边界见 [EXTENSION_SCOPE_MATRIX.md](./EXTENSION_SCOPE_MATRIX.md)。
>
> 实现状态说明:本文描述的是 Runtime Control Plane v2 的目标能力和分阶段落地建议。当前 AgentRunner 插件化主线已经具备 event-first context、run-scoped authorization、EventLog / Transcript / State / sandbox 文件等 Host capability,并已落地持久 `AgentRun` / `AgentRunEvent` ledger、run control actions、最小 runtime heartbeat/claim lease 和 admin reconcile 原语。完整 Agent Platform 产品形态、daemon supervisor、runtime wakeup channel 和分布式 runtime 管控仍未完成。当前实现状态以 [STATUS.md](./STATUS.md) 为准。
> 实现状态说明:本文描述的是 Runtime Control Plane v2 的目标能力和分阶段落地建议。当前 Runner 插件化主线已经具备 event-first context、run-scoped authorization、EventLog / Transcript / State / sandbox 文件等 Host capability,并已落地持久 `AgentRun` / `AgentRunEvent` ledger、run control actions、最小 runtime heartbeat/claim lease 和 admin reconcile 原语。完整 Agent Platform 产品形态、daemon supervisor、runtime wakeup channel 和分布式 runtime 管控仍未完成。当前实现状态以 [STATUS.md](./STATUS.md) 为准。
## 1. 当前决策
@@ -14,7 +14,7 @@ LangBot 后续定位应更像 **Agent Host / infrastructure provider / transfer
- **Agent Platform 产品形态做成插件**。插件负责 agent 管理、策略、业务队列、UI、编排、多 agent 协作和产品体验。
- **Agent Platform 所需的基础事实源做进 Host**。当前 Host 已保存 event、state、transcript、sandbox 文件边界、active run 权限快照、持久 run/result ledger、审计关联和通用控制状态。
- **最小 runtime registry / heartbeat / claim lease 已作为 Host 原语落地,但不等于完整 daemon worker 管控**。远程 harness / daemon 的进程托管、wakeup channel、provider 登录态诊断和分布式调度仍可以先由 AgentRunner 插件和 SDK remote layer 自己维护。
- **最小 runtime registry / heartbeat / claim lease 已作为 Host 原语落地,但不等于完整 daemon worker 管控**。远程 harness / daemon 的进程托管、wakeup channel、provider 登录态诊断和分布式调度仍可以先由 Runner 插件和 SDK remote layer 自己维护。
- **不把业务调度写进 Host**。Host 提供通用 run/result/control primitivesPlatform 插件决定哪些事件触发哪些 agent、如何排队、如何分配、是否 fan-out。
推荐分层:
@@ -30,16 +30,16 @@ Agent Platform plugin
Agent management UI / project-task model / event routing policy
Business queue / multi-agent orchestration / runtime selection policy
AgentRunner plugin / external harness runtime
Runner plugin / external harness runtime
Connects ACP / remote daemon / local subprocess / HTTP API
Executes and converts provider-native events to AgentRunResult
Executes and converts provider-native events to RunnerResult
```
## 2. Platform 与非 Platform 的区别
当前 LangBot 已经具备 Agent Host 的核心特征:
- 抹平不同 AgentRunner。
- 抹平不同 Runner。
- 从 IM / Pipeline 入口触发 runner。
- 有 event-first context 方向。
- 有 Host-owned EventLog / Transcript / State 和 sandbox/workspace 文件边界。
@@ -116,7 +116,7 @@ metadata
### 3.3 RunEvent / RunResult
RunEvent 是一次 run 过程中产生的结果事件流,对应 runner 返回的 `AgentRunResult`。它不同于 EBA/EventLog 的输入事件:
RunEvent 是一次 run 过程中产生的结果事件流,对应 runner 返回的 `RunnerResult`。它不同于 EBA/EventLog 的输入事件:
```text
message.delta
@@ -151,8 +151,8 @@ Runtime / daemon 表示执行位置或执行能力,例如某台机器上的 Cl
当前决策:
- Host 不在第一阶段维护完整 runtime registry。
- AgentRunner 插件可以通过 SDK remote layer 与 daemon 保持连接、心跳和执行通道。
- 外部 harness / agent 不应直接访问 LangBot Host 或数据库。访问 LangBot 资源必须通过 daemon / AgentRunner plugin / SDK runtime / `AgentRunAPIProxy` / scoped MCP bridge,并接受 run-scoped authorization 校验。
- Runner 插件可以通过 SDK remote layer 与 daemon 保持连接、心跳和执行通道。
- 外部 harness / agent 不应直接访问 LangBot Host 或数据库。访问 LangBot 资源必须通过 daemon / Runner plugin / SDK runtime / `RunnerAPIProxy` / scoped MCP bridge,并接受 run-scoped authorization 校验。
- 如果后续多个插件都需要共享 runtime 状态,再把薄的 `RuntimeLease` / registry 下沉为 Host 通用能力。
## 4. Host 应新增的最小能力
@@ -222,7 +222,7 @@ metadata_json
- append 必须幂等,支持远程 daemon / plugin 重试。
- 未知 result type 可保存但 Host 只对已知类型执行副作用。
- 大 payload 仍应进入 sandbox/workspace,不直接塞入 result event。
- `usage_json` 保存 `AgentRunResult.usage` 原样结构;缺失表示 unknown,不等于 0。
- `usage_json` 保存 `RunnerResult.usage` 原样结构;缺失表示 unknown,不等于 0。
### 4.3 Run Control API
@@ -258,7 +258,7 @@ event -> binding -> context -> runner invocation -> result normalization
需要补齐:
- run 开始时创建 `AgentRun`
- 每个 `AgentRunResult` 进入 `AgentRunEvent`
- 每个 `RunnerResult` 进入 `AgentRunEvent`
- `run.completed` / 正常 generator 结束时标记 completed。
- `run.failed` / exception / timeout 标记 failed 或 timeout。
- terminal result 携带 usage 时,写入 `AgentRunEvent.usage_json` 并汇总到 `AgentRun.usage_json`
@@ -266,7 +266,7 @@ event -> binding -> context -> runner invocation -> result normalization
### 4.5 Usage / Cost Accounting
SDK 侧 `AgentRunResult` 已提供可选 `usage` 字段,用于把不同 runner / external harness / provider-native event 的 token usage 归一到同一个 run result envelope。
SDK 侧 `RunnerResult` 已提供可选 `usage` 字段,用于把不同 runner / external harness / provider-native event 的 token usage 归一到同一个 run result envelope。
语义:
@@ -309,7 +309,7 @@ RunCreateRequest / RunCreateResult
RunAppendResultRequest
```
这些是 Host control primitives,不替代 `AgentRunContext` / `AgentRunResult`
这些是 Host control primitives,不替代 `RunnerContext` / `RunnerResult`
### 5.2 Proxy Methods
@@ -327,17 +327,17 @@ finalize_run(run_id, status, error=None)
访问边界:
- 普通 AgentRunner 在同步 `run(ctx)` 内不一定需要直接调用这些 APIHost orchestrator 可自动记录。
- 普通 Runner 在同步 `run(ctx)` 内不一定需要直接调用这些 APIHost orchestrator 可自动记录。
- Platform 插件可以创建/查询/取消 run。
- AgentRunner 插件或 daemon bridge 可以 append/finalize 自己负责的 run。
- Runner 插件或 daemon bridge 可以 append/finalize 自己负责的 run。
- 外部 harness 仍不能直接调用 Host;必须经 SDK runtime / proxy / bridge。
### 5.3 Plugin-Daemon Heartbeat
远程 daemon 的初始心跳可以是 SDK / AgentRunner plugin 私有能力:
远程 daemon 的初始心跳可以是 SDK / Runner plugin 私有能力:
```text
daemon <-> AgentRunner plugin / SDK remote layer <-> LangBot plugin runtime <-> Host
daemon <-> Runner plugin / SDK remote layer <-> LangBot plugin runtime <-> Host
```
Host 第一阶段只需要知道:
@@ -365,7 +365,7 @@ Platform 插件不应负责:
- 在 Host Run Ledger 落地后,私有保存通用 run/result 事实源。
- 绕过 Host 直接写 transcript/state 或越权访问 sandbox/workspace 文件。
- 让外部 harness 直接访问 LangBot DB 或 Host 内部资源。
- 把某个业务队列语义强塞进 AgentRunner Protocol v1。
- 把某个业务队列语义强塞进 Runner Protocol v1。
## 7. 与 EBA 的关系
@@ -395,18 +395,18 @@ EventGateway
这两条路径最终应共享 Host run/result/state 事实源和 sandbox/workspace 文件边界。当前阶段可共享的是 event/transcript/state、sandbox 文件和同步执行链路;持久 run/result ledger 需要 Runtime Control Plane v2 Phase 1 补齐。区别在于是否有 Platform 插件参与产品化调度和业务队列。
## 8. 与 AgentRunner Protocol v1 的关系
## 8. 与 Runner Protocol v1 的关系
本设计不改变 v1 的 runner 可见合同:
```text
AgentRunContext -> AgentRunner.run(ctx) -> AgentRunResult stream
RunnerContext -> Runner.run(ctx) -> RunnerResult stream
```
必须保持:
- `AgentRunContext` 不塞入 daemon/worker/pod 细节。
- `AgentRunResult` 仍是 runner 输出的统一事件流。
- `RunnerContext` 不塞入 daemon/worker/pod 细节。
- `RunnerResult` 仍是 runner 输出的统一事件流。
- 普通 runner 不需要知道 task queue / runtime registry。
- 远程 harness 可以自管 session、tool loop、MCP、上下文压缩,但访问 LangBot 资源必须通过 SDK proxy / bridge。
- Runtime-managed execution 是 placement / transport 选择,不是普通 runner 协议的强制概念。
@@ -422,7 +422,7 @@ AgentRunContext -> AgentRunner.run(ctx) -> AgentRunResult stream
- `AgentRun` 表。
- `AgentRunEvent` 表。
- Orchestrator 自动创建/更新 run。
- Journal 持久化每个 `AgentRunResult`
- Journal 持久化每个 `RunnerResult`
- Run 查询和事件分页 API。
- SDK entities + proxy 方法。
@@ -517,9 +517,9 @@ Tests: 40+ 个文件
- Host 不写业务调度策略,但要保存通用状态、结果、权限和审计。
- EBA event 不是 queuequeue 是执行生命周期问题。
- 业务 queue 可以先在 Platform 插件里;执行 queue 只有在复用需求明确后再下沉 Host。
- Daemon registry 不应污染 AgentRunner Protocol v1。
- Daemon registry 不应污染 Runner Protocol v1。
- 外部 harness 不直接访问 LangBot Host 或 DB。
- 所有 LangBot 资源访问必须走 SDK runtime / `AgentRunAPIProxy` / scoped MCP bridge。
- 所有 LangBot 资源访问必须走 SDK runtime / `RunnerAPIProxy` / scoped MCP bridge。
- Docker / remote / local subprocess 只是 runtime placement,不是 runner 协议差异。
## 11. 非目标
@@ -528,8 +528,8 @@ Tests: 40+ 个文件
- 完整 Multica 式 runtime registry。
- Host 内置项目管理、任务板、agent team、workflow 产品逻辑。
- 把 daemon heartbeat / worker liveness 放进 `AgentRunContext`
- 把业务 queue 定义为 AgentRunner Protocol 字段。
- 把 daemon heartbeat / worker liveness 放进 `RunnerContext`
- 把业务 queue 定义为 Runner Protocol 字段。
- 让 Platform 插件私有保存 run/result 事实源。
- 让外部 agent/harness 直连 Host 内部资源。
@@ -16,7 +16,7 @@ local-agent 已移植 Pi 的事件生命周期、并行工具语义、hook 扩
### 1.1 问题
IM 场景下用户在 agent 运行中追加消息非常常见(补充信息、纠正方向、"算了别查了")。
EBA 先按事件选择一个 Pipeline 或 Agent 处理器;进入 AgentRunner 后,当前调用链是 `one AgentBinding -> one run_id -> one runner`
EBA 先按事件选择一个 Pipeline 或 Agent 处理器;进入 Runner 后,当前调用链是 `one AgentBinding -> one run_id -> one runner`
PROTOCOL_V1 §13):同会话的新消息要么等待当前 run 结束后触发新 run,
要么并发触发独立 run。两种行为都无法把新消息送进**正在执行的 tool loop**
用户体验是"agent 自顾自跑完过期任务,然后才看到新消息"。
@@ -59,7 +59,7 @@ pi-agent-core 区分两个队列,注入时机都在 turn 边界,不打断进
已落地的协议面(最终定义归 PROTOCOL_V1):
1. `ContextAccess.available_apis` 增加 steering pull 能力位。
2. `AgentRunAPIProxy` 增加 steering 拉取 action:默认 `mode=all`Host 保序返回全部
2. `RunnerAPIProxy` 增加 steering 拉取 action:默认 `mode=all`Host 保序返回全部
pending 输入;`one-at-a-time` 仅作为 runner 主动节流选项。
3. dispatch 层的"认领"规则:`message.received` 可被同 conversation 的 active run
吸收,原事件写 EventLog / Transcriptdispatch 行为写入 EventLog metadata。
@@ -1,4 +1,4 @@
# Agent Runner Security Boundary
# Runner Security Boundary
本文档记录 agent-runner 插件化后的安全边界和最小护栏。
@@ -6,7 +6,7 @@
**当前结论:不采用高强度监管模型。**
LangBot 的目标不是托管一个强隔离、不可信 code runner 平台。AgentRunner 插件,尤其是 ACP / Claude Code / Codex / OpenCode / Kimi Code 这类外部 harness,默认视为 **operator-owned execution**:用户或部署者显式配置并承担其文件系统、进程、网络、workspace、provider 登录态和 native tool 风险。
LangBot 的目标不是托管一个强隔离、不可信 code runner 平台。Runner 插件,尤其是 ACP / Claude Code / Codex / OpenCode / Kimi Code 这类外部 harness,默认视为 **operator-owned execution**:用户或部署者显式配置并承担其文件系统、进程、网络、workspace、provider 登录态和 native tool 风险。
LangBot 需要负责的是保护 **LangBot 自己持有的资源**,包括模型、知识库、LangBot tools、history、event、state、plugin/workspace storage、sandbox/workspace 文件访问等。只要这些资源访问是 run-scoped、permission-scoped、可校验、可诊断的,当前阶段即可接受。
@@ -171,7 +171,7 @@ LangBot 需要提供基本可控性:
截至 2026-06-15,已有实现覆盖:
- SDK typed AgentRunner manifest、capabilities、permissions。
- SDK typed Runner manifest、capabilities、permissions。
- Host resource builder 按 manifest permissions 和 binding policy 生成 `ctx.resources`
- Active run session snapshot 和 `caller_plugin_identity` 校验。
- History / event / state / tool / knowledge runtime action 的 run-scoped 校验。
@@ -204,7 +204,7 @@ LangBot 需要提供基本可控性:
可以对外说明:
> AgentRunner 插件通过 run-scoped authorization 和 scoped MCP gateway 保护 LangBot 持有资源。外部 code harness 的执行环境由用户或部署平台负责隔离;LangBot 当前不提供 managed sandbox。
> Runner 插件通过 run-scoped authorization 和 scoped MCP gateway 保护 LangBot 持有资源。外部 code harness 的执行环境由用户或部署平台负责隔离;LangBot 当前不提供 managed sandbox。
不能对外说明:
+9 -9
View File
@@ -1,19 +1,19 @@
# AgentRunner Pluginization Status
# Runner Pluginization Status
本文档是 `docs/agent-runner-pluginization/` 的状态事实源。协议 schema 仍以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) 为准;测试步骤以 [AGENT_RUNNER_QA_GUIDE.md](./AGENT_RUNNER_QA_GUIDE.md) 为准;安全发布门槛以 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md) 为准。
本文档是 `docs/agent-runner-pluginization/` 的状态事实源。协议 schema 仍以 [PROTOCOL_V1.md](./PROTOCOL_V1.md) 为准;测试步骤以 [RUNNER_QA_GUIDE.md](./RUNNER_QA_GUIDE.md) 为准;安全发布门槛以 [SECURITY_HARDENING.md](./SECURITY_HARDENING.md) 为准。
状态快照日期:2026-09-05。代码基线为 LangBot `dev/4.11.x` / `a4d36aa2d` 和 SDK `dev/4.11.x` / `f1da058`;本文是本地检视快照,不代表远端最新状态或正式发布批准。
## 当前版本与验收边界
- Core 声明版本 `4.11.0``pyproject.toml` / `uv.lock` 仍依赖 `langbot-plugin==0.5.3`SDK 源码声明版本 `0.5.5`。本机 Core 实际导入旁边 SDK 的可编辑源码,不能用这个组合的测试通过证明 registry 安装可复现。
- 检视时 SDK 有四个未提交文件:`api/agent_tools/asset_gateway.py``api/agent_tools/external_tools.py``api/entities/builtin/agent_runner/resources.py`(均位于 `src/langbot_plugin/`),以及 `tests/api/test_agent_tools_mcp_bridge.py`。这些改动增加 `platform_tools` 分类发现、可选 schema 和 gateway 引导。下面的 SDK 测试包含这些工作区改动;正式配套版本尚需冻结。
- 检视时 SDK 有四个未提交文件:`api/agent_tools/asset_gateway.py``api/agent_tools/external_tools.py``api/entities/builtin/runner/resources.py`(均位于 `src/langbot_plugin/`),以及 `tests/api/test_agent_tools_mcp_bridge.py`。这些改动增加 `platform_tools` 分类发现、可选 schema 和 gateway 引导。下面的 SDK 测试包含这些工作区改动;正式配套版本尚需冻结。
- 本轮仅重新执行下列定向测试与 TypeScript 检查,没有重跑全量 backend、真实平台、provider、浏览器 E2E 或 Cloud 部署门禁。后文旧日期的成功记录仍是历史证据。
| 2026-09-05 验证 | 结果 |
| --- | --- |
| Core`tests/unit_tests/agent``tests/unit_tests/api/service/test_agent_service.py``tests/unit_tests/platform/test_routing_rules.py``tests/unit_tests/api/service/test_maintenance_service.py` | 561 passed74 warnings |
| SDK`tests/api/entities/builtin/agent_runner``tests/api/proxies``tests/api/test_agent_tools_mcp_bridge.py``tests/runtime/plugin/test_mgr_agent_runner.py``tests/runtime/plugin/test_dependency_environment.py``tests/runtime/plugin/test_restart_coordinator.py` | 362 passed10 warnings |
| SDK`tests/api/entities/builtin/runner``tests/api/proxies``tests/api/test_agent_tools_mcp_bridge.py``tests/runtime/plugin/test_mgr_runner.py``tests/runtime/plugin/test_dependency_environment.py``tests/runtime/plugin/test_restart_coordinator.py` | 362 passed10 warnings |
| Web`pnpm exec tsc --noEmit` | pass |
| Web`pnpm test:unit` | 62 passed2 failed |
@@ -31,7 +31,7 @@
| 领域 | 状态 | 说明 |
| --- | --- | --- |
| SDK manifest schema | Done | `AgentRunnerManifest` 包含 typed `capabilities` / `permissions`;未知 capability / permission key 禁止进入 typed model。 |
| SDK manifest schema | Done | `RunnerManifest` 包含 typed `capabilities` / `permissions`;未知 capability / permission key 禁止进入 typed model。 |
| Runner discovery | Done | Runtime 返回 typed manifestHost registry 校验单个 runner,失败 warning + skip,不影响其它 runner。 |
| Host resource authorization | Done | `ctx.resources``ctx.context.available_apis` 由 manifest permissions 与 binding policy / run scope 求交后生成。 |
| Run authorization snapshot | Done | active run session 冻结 run-scoped resources 与 available APIsruntime handler 按 snapshot 校验 pull API。 |
@@ -61,8 +61,8 @@
| Runner | 状态 | 最近证据 |
| --- | --- | --- |
| `plugin:langbot-team/LocalAgent/default` | Unit-pass; Marketplace UI pass; Debug Chat E2E pass | 2026-07-12 隔离 first-run 实例从真实 AgentRunner catalog 安装 `langbot-team/LocalAgent` 0.1.0Host 注册 `plugin:langbot-team/LocalAgent/default`,Wizard 自动选中并解锁后续操作。2026-07-15 `2026-07-15-08-44-10-770-08-00-sandbox-skill-authoring-edit-existing-e2e` 使用真实 `gpt-5.5` 完成 Skill 创建、注册、同 Query 激活、已激活包编辑与脚本执行;三阶段 UI、浏览器诊断和结构化文件系统检查全部通过,每阶段恰好新增一个 Bot 气泡,p95 14.6 秒、错误率 0。 |
| `plugin:langbot-team/ACPAgentRunner/default` | Unit-pass; Debug Chat E2E pass | 2026-07-15 从本地 0.1.4 发布包安装并注册 PascalCase runnerremote-ssh Claude ACP 通过反向隧道调用 run-scoped `langbot_get_current_event`,97.8 秒返回可见结果;Host 将增量 delta 和 `message.completed` 聚合为一个完整 Bot 气泡。 |
| `plugin:langbot-team/LocalAgent/default` | Unit-pass; Marketplace UI pass; Debug Chat E2E pass | 2026-07-12 隔离 first-run 实例从真实 Runner catalog 安装 `langbot-team/LocalAgent` 0.1.0Host 注册 `plugin:langbot-team/LocalAgent/default`,Wizard 自动选中并解锁后续操作。2026-07-15 `2026-07-15-08-44-10-770-08-00-sandbox-skill-authoring-edit-existing-e2e` 使用真实 `gpt-5.5` 完成 Skill 创建、注册、同 Query 激活、已激活包编辑与脚本执行;三阶段 UI、浏览器诊断和结构化文件系统检查全部通过,每阶段恰好新增一个 Bot 气泡,p95 14.6 秒、错误率 0。 |
| `plugin:langbot-team/ACPRunner/default` | Unit-pass; Debug Chat E2E pass | 2026-07-15 从本地 0.1.4 发布包安装并注册 PascalCase runnerremote-ssh Claude ACP 通过反向隧道调用 run-scoped `langbot_get_current_event`,97.8 秒返回可见结果;Host 将增量 delta 和 `message.completed` 聚合为一个完整 Bot 气泡。 |
| `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 | Human-input unit-pass; credential E2E pending | `langbot-agent-runner/dify-agent` 已实现 `workflow_paused`、原子字段/确认交互、plugin-storage continuation、Dify submit/events 恢复与再次暂停;真实 Dify 凭据 E2E 待执行。 |
| n8n / Coze / DashScope / Langflow / Tbox / DeerFlow / WeKnora | Unit-pass; credential smoke optional | 2026-06-13 plugin layout / parser tests 通过;真实服务凭据 smoke 非每轮必跑。 |
@@ -71,9 +71,9 @@
| 范围 | 状态 | 最近证据 |
| --- | --- | --- |
| LangBot Runtime Control Plane v2 foundation | Unit-pass; EBA release gate 5/5 pass; AgentRunner preflight pass | 2026-07-12 `eba-functional-20260712-release-gate-rerun` 通过 Quick Start 场景筛选、隔离实例 Runner Marketplace 安装、Runner 健康状态、事件路由 dry-run / 合成派发,以及真实 OneBot `group.member_joined` → Agent → `send_group_msg` 链路。2026-07-15 AgentRunner release preflight 16 项通过、0 warningfixture contract、5 类 behavior matrix、ledger schema / async DB readiness / 100-run stress / 120-run 8-worker contention / claim-lease-auth concurrency、SDK runtime chaos 探针全部通过。 |
| LangBot Runtime Control Plane v2 foundation | Unit-pass; EBA release gate 5/5 pass; Runner preflight pass | 2026-07-12 `eba-functional-20260712-release-gate-rerun` 通过 Quick Start 场景筛选、隔离实例 Runner Marketplace 安装、Runner 健康状态、事件路由 dry-run / 合成派发,以及真实 OneBot `group.member_joined` → Agent → `send_group_msg` 链路。2026-07-15 Runner release preflight 16 项通过、0 warningfixture contract、5 类 behavior matrix、ledger schema / async DB readiness / 100-run stress / 120-run 8-worker contention / claim-lease-auth concurrency、SDK runtime chaos 探针全部通过。 |
| Host Skill / native tool integration | Unit-pass; WebUI E2E pass | 2026-07-15 provider / native / Skill / monitoring 定向测试 67 项通过,Pipeline / Chat / Wrapper 定向测试 61 项通过,Skills CLI 105 项通过;真实 Debug Chat 验证 `register_skill` 后同 Query `activate` 成功,监控工具调用不再把 SQL 行误取为字符串,结构化 JSON 文件检查不依赖格式空格,非流式多阶段 runner 结果只生成一个最终 Bot 气泡。 |
| SDK AgentRunner control entities / proxy | Unit-pass | 2026-06-23 SDK `tests/api/entities/builtin/agent_runner``tests/api/proxies``tests/api/test_agent_tools_mcp_bridge.py``tests/runtime/plugin/test_mgr_agent_runner.py``tests/runtime/test_pull_api_handlers.py``tests/runtime/io/handlers/test_plugin_handler.py`、EBA event entities 和 message tests 通过,覆盖 typed entities、AgentRunAPIProxy、MCP bridge、runtime manager 与 pull API handlers。 |
| SDK Runner control entities / proxy | Unit-pass | 2026-06-23 SDK `tests/api/entities/builtin/runner``tests/api/proxies``tests/api/test_agent_tools_mcp_bridge.py``tests/runtime/plugin/test_mgr_runner.py``tests/runtime/test_pull_api_handlers.py``tests/runtime/io/handlers/test_plugin_handler.py`、EBA event entities 和 message tests 通过,覆盖 typed entities、RunnerAPIProxy、MCP bridge、runtime manager 与 pull API handlers。 |
## 历史高价值记录
@@ -7,7 +7,7 @@
- **Bot**:平台连接、凭据和事件路由入口。用户在机器人上决定“发生什么时,使用哪个处理器”。
- **Processor**:可复用处理逻辑的上位概念,当前类型为 Agent 与 Pipeline。
- **Pipeline**:保留完整 Stage 链的消息处理器,提供预处理、AI、后处理、扩展和输出控制。
- **Agent**:独立配置对象,选择 AgentRunner 插件并配置事件范围、运行器与工具权限,可被多个 Bot 引用。
- **Agent**:独立配置对象,选择 Runner 插件并配置事件范围、运行器与工具权限,可被多个 Bot 引用。
- **Workflow**:后续编排方向,当前尚无完整执行产品。
- **Solution**:后续分发单元,包含处理器、路由模板、依赖、变量和文档。
+8 -8
View File
@@ -1,6 +1,6 @@
# Event Based Agents 架构设计总览
> Product revision (2026-09-07): [Event processors and Pipeline plugin compatibility](./09-event-processors.md) defines an explicitly bound EventProcessor alongside Pipeline and Agent. It supersedes the automatic EBA observer product model below; the new component and UI are planned, not yet implemented.
> Product revision (2026-09-07): [Event processors and Pipeline plugin compatibility](./09-event-processors.md) defines an explicitly bound Runner alongside Pipeline and Agent. It supersedes the automatic EBA observer product model below; the new component and UI are planned, not yet implemented.
> 当前状态(2026-09-05):平台事件、Bot `event_bindings`、独立 Agent、Pipeline / Agent 平级路由及 WebUI 已集成到 `dev/4.11.x`。实现入口为 `pkg/platform/botmgr.py::RuntimeBot` 与 `pkg/agent/runner/`。下文“当前架构的局限性”“现有架构”描述改造前背景;EventBus / EventRouter 图表示职责划分,不表示存在同名独立服务。当前实现和验收以 [STATUS.md](../agent-runner-pluginization/STATUS.md) 为准,平台动作使用[授权工具](../agent-runner-pluginization/PLATFORM_ACTION_TOOLS.md)。
@@ -52,9 +52,9 @@ MessageAggregator (消息聚合)
QueryPool → Controller → Pipeline (固定阶段链)
│ │
│ ▼
AgentRunner Host orchestrator
│ Runner Host orchestrator
│ ▼
│ plugin AgentRunner
│ plugin Runner
adapter.reply_message() / adapter.send_message()
@@ -83,7 +83,7 @@ EventBus (统一事件总线)
EventRouter (读取 Bot 的 event_bindings)
├─→ Pipeline target — 完整 Stage 链,仅消息事件
├─→ Agent target — 独立 Agent,经插件 AgentRunner 执行
├─→ Agent target — 独立 Agent,经插件 Runner 执行
└─→ discard — 明确丢弃
@@ -150,9 +150,9 @@ pkg/platform/adapters/
### 3.4 事件响应目标与观察者
Pipeline 与 Agent 是长期并存、场景不同的同级处理器。Pipeline 保留完整 Stage 链,面向消息处理;Agent 是独立配置对象,选择一个已安装的插件 AgentRunner,并可声明消息或非消息事件能力。Bot 的 `event_bindings` 只负责把事件绑定到既有 Pipeline、独立 Agent 或 `discard`
Pipeline 与 Agent 是长期并存、场景不同的同级处理器。Pipeline 保留完整 Stage 链,面向消息处理;Agent 是独立配置对象,选择一个已安装的插件 Runner,并可声明消息或非消息事件能力。Bot 的 `event_bindings` 只负责把事件绑定到既有 Pipeline、独立 Agent 或 `discard`
插件 EventListener 是观察者:事件先广播给有权限的监听器,随后路由器再选择一个响应目标。Webhook、Dify、n8n 等外部执行方式若需要作为响应者,应由对应 AgentRunner 插件表达,而不是增加另一套 Host Handler 主链。
插件 EventListener 是观察者:事件先广播给有权限的监听器,随后路由器再选择一个响应目标。Webhook、Dify、n8n 等外部执行方式若需要作为响应者,应由对应 Runner 插件表达,而不是增加另一套 Host Handler 主链。
现有 Pipeline 不会被转换为 AgentPipeline 内的 runner 配置也不会复制到独立 Agent。用户需要 Agent 时自行创建并绑定。
@@ -174,7 +174,7 @@ Pipeline 与 Agent 是长期并存、场景不同的同级处理器。Pipeline
| 2 | 适配器特有 API | 统一抽象 + `call_platform_api` 透传 | 通用 API 覆盖大部分场景,透传机制保证灵活性,避免每个适配器导出独立的类型化 API 包 |
| 3 | 向后兼容策略 | 兼容层适配 | 保留旧事件类型和 API 作为新系统的 alias/wrapper,现有插件无需修改 |
| 4 | 处理器配置存储 | Bot 表使用 `event_bindings`,目标引用原始 Pipeline 或独立 Agent UUID | 路由关系不复制处理器配置,Pipeline/Agent 各自保持事实源 |
| 5 | Agent 处理器定位 | 独立 Agent + 插件 AgentRunner | Host 不再内置具体 runner;不同 AgentRunner 通过统一协议接入 |
| 5 | Agent 处理器定位 | 独立 Agent + 插件 Runner | Host 不再内置具体 runner;不同 Runner 通过统一协议接入 |
| 6 | 事件命名方式 | 命名空间式(`message.received` | 清晰的分类层级,便于通配匹配(`message.*`),与 WebUI 配置天然对应 |
## 5. 文档索引
@@ -194,7 +194,7 @@ Pipeline 与 Agent 是长期并存、场景不同的同级处理器。Pipeline
| 仓库 | 改动范围 |
|------|----------|
| **langbot-plugin-sdk** | 事件定义、实体模型、API 接口、适配器基类、通信协议扩展 |
| **LangBot**(后端) | 适配器实现、事件路由引擎、Bot/Agent 实体、AgentRunner Host 编排 |
| **LangBot**(后端) | 适配器实现、事件路由引擎、Bot/Agent 实体、Runner Host 编排 |
| **LangBot**(前端) | Bot 事件处理器编排面板 |
| **langbot-wiki** | 新架构文档、插件开发指南更新、适配器开发指南 |
| **langbot-plugin-demo** | 示例更新(使用新事件和 API) |
+1 -1
View File
@@ -499,7 +499,7 @@ class PlatformSpecificEvent(Event):
8. 目标处理事件
│ Pipeline → 进入完整 Pipeline 流水线(仅消息事件)
│ Agent → Host 编排已安装的插件 AgentRunner
│ Agent → Host 编排已安装的插件 Runner
│ discard → 不产生响应
9. 处理器执行完毕,可能通过 Host 授权 API 执行响应动作
+10 -10
View File
@@ -1,6 +1,6 @@
# 事件路由与编排
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound EventProcessor instances, a third peer processor type alongside Agent and Pipeline.
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound Runner instances, a third peer processor type alongside Agent and Pipeline.
> 状态:当前实施模型(2026-07-12)。本文以 Pipeline / Agent 平级并存为准,不再保留早期 `pipeline / agent / webhook / plugin` 四种 Handler 草案。
@@ -16,10 +16,10 @@ Pipeline 与 Agent 是平级处理器:
| 处理器 | 配置事实源 | 执行路径 | 事件范围 |
| --- | --- | --- | --- |
| Pipeline | Pipeline 表与完整 Stage 配置 | MessageAggregator -> QueryPool -> RuntimePipeline | 消息事件,首版为 `message.received` |
| Agent | Agent 表中的 runner 与 runner config | AgentRunner Host orchestrator -> plugin AgentRunner | Agent/Runner 声明支持的消息或非消息事件 |
| Agent | Agent 表中的 runner 与 runner config | Runner Host orchestrator -> plugin Runner | Agent/Runner 声明支持的消息或非消息事件 |
| discard | 无处理器配置 | 明确结束路由 | 任意事件 |
插件 EventListener 不是第三种响应目标。Webhook、Dify、n8n、Coze 等外部系统需要响应事件时,由对应 AgentRunner 插件承接。
插件 EventListener 不是第三种响应目标。Webhook、Dify、n8n、Coze 等外部系统需要响应事件时,由对应 Runner 插件承接。
## 2. 数据模型
@@ -34,7 +34,7 @@ class Agent(Base):
description: str
emoji: str
kind: str # 固定为 "agent"
component_ref: str # AgentRunner id
component_ref: str # Runner id
config: dict # runner + runner_config
supported_event_patterns: list[str]
```
@@ -57,7 +57,7 @@ class Agent(Base):
}
```
Runner id 来自已安装插件的 AgentRunner manifest。Host 不维护 LocalAgent、Dify 或其他具体实现的内置分支。
Runner id 来自已安装插件的 Runner manifest。Host 不维护 LocalAgent、Dify 或其他具体实现的内置分支。
### 2.2 EventBinding
@@ -129,20 +129,20 @@ Platform adapter
-> authorized Plugin EventListener observers
-> EventRouter
-> Pipeline target -> full Pipeline stage chain
-> Agent target -> AgentRunner Host orchestrator
-> Agent target -> Runner Host orchestrator
-> discard -> stop
-> Host delivery/platform API
```
### 4.1 Pipeline target
消息事件按原有方式构造 Query,经 MessageAggregator、QueryPool 和完整 Pipeline Stage 链执行。Pipeline 可以继续使用 AgentRunner 作为 AI stage 的实现,但 Pipeline 本身不会因此变成 Agent。
消息事件按原有方式构造 Query,经 MessageAggregator、QueryPool 和完整 Pipeline Stage 链执行。Pipeline 可以继续使用 Runner 作为 AI stage 的实现,但 Pipeline 本身不会因此变成 Agent。
### 4.2 Agent target
Host 读取独立 Agent 的 Runner id/config,构造 event-first context、run-scoped resources 与 delivery policy,再调用插件 AgentRunner。Runner 输出由 Host 统一归一化、记录和投递。
Host 读取独立 Agent 的 Runner id/config,构造 event-first context、run-scoped resources 与 delivery policy,再调用插件 Runner。Runner 输出由 Host 统一归一化、记录和投递。
AgentRunner 可通过 SDK/Python `AgentRunAPIProxy.call_tool` 或 SDK-owned scoped MCP bridge 回调 Host 能力。两条路径都映射到 `PluginToRuntimeAction.CALL_TOOL`,使用相同的 run authorization、Host execution Query、ToolManager 和 Box session 规则。Box session 是 Host canonical scope 的固定长度安全哈希;同一平台会话稳定、不同 scope 隔离、缺少 identity 时 fail closedRunner 不配置 sandbox scope。
Runner 可通过 SDK/Python `RunnerAPIProxy.call_tool` 或 SDK-owned scoped MCP bridge 回调 Host 能力。两条路径都映射到 `PluginToRuntimeAction.CALL_TOOL`,使用相同的 run authorization、Host execution Query、ToolManager 和 Box session 规则。Box session 是 Host canonical scope 的固定长度安全哈希;同一平台会话稳定、不同 scope 隔离、缺少 identity 时 fail closedRunner 不配置 sandbox scope。
### 4.3 Observer side effects
@@ -153,7 +153,7 @@ AgentRunner 可通过 SDK/Python `AgentRunAPIProxy.call_tool` 或 SDK-owned scop
1. Pipeline 与 Agent 保留各自的持久化、编辑和执行语义。
2. 处理器聚合页面可以统一展示二者,但不会创建第三份处理器记录。
3. 旧 Pipeline 仍是 Pipeline;其 runner config 不迁移、不复制为独立 Agent。
4. 需要 Agent 的用户新建 Agent、选择已安装 AgentRunner,再建立 event binding。
4. 需要 Agent 的用户新建 Agent、选择已安装 Runner,再建立 event binding。
5. 一个 Bot 可按不同事件同时绑定 Pipeline 与 Agent。
## 6. WebUI 约束
+1 -1
View File
@@ -1,6 +1,6 @@
# 插件 SDK 改造
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound EventProcessor instances, a third peer processor type alongside Agent and Pipeline.
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound Runner instances, a third peer processor type alongside Agent and Pipeline.
## 1. 概述
+11 -11
View File
@@ -1,6 +1,6 @@
# EBA 分阶段实施计划
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound EventProcessor instances, a third peer processor type alongside Agent and Pipeline.
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound Runner instances, a third peer processor type alongside Agent and Pipeline.
> 更新:2026-09-05。P0P4 的主要实现已落入 `dev/4.11.x`,P5 仍需按当前版本验收;下文工作项用于维护实现边界,不表示全部待开发。文件名沿用早期设计,但这里的“迁移”仅指代码架构逐步接入 EBA,不代表 LangBot 3.x 数据库或配置升级。当前提交、定向测试及发布缺口见 [STATUS.md](../agent-runner-pluginization/STATUS.md)。
@@ -11,15 +11,15 @@ EBA 跨越 SDK、平台适配器、LangBot Host、WebUI 与插件生态,按可
- LangBot 4.x 不支持从 3.x 数据库或配置升级;不保留 legacy migration chain、旧 JSON 模板或旧 Runner 字段读取。
- Pipeline 与 Agent 平级且长期并存,分别保留持久化模型与执行链。
- 现有 Pipeline 不迁移为 AgentPipeline 内的 runner config 不复制到 Agent。
- 用户需要 Agent 时新建独立 Agent并选择已安装的 AgentRunner。
- 用户需要 Agent 时新建独立 Agent并选择已安装的 Runner。
- Host 不按 LocalAgent id 做运行时、Box 或 WebUI 特判。
- AgentRunner 的 SDK/Python 与 scoped MCP bridge 回调共享 Host 授权与事件 session 规则。
- Runner 的 SDK/Python 与 scoped MCP bridge 回调共享 Host 授权与事件 session 规则。
## 2. 阶段总览
| 阶段 | 目标 | 主要仓库 | 完成条件 |
| --- | --- | --- | --- |
| P0 | SDK 事件、能力与 AgentRunner 协议 | `langbot-plugin-sdk` | typed entities、manifest、proxy、runtime action 通过测试 |
| P0 | SDK 事件、能力与 Runner 协议 | `langbot-plugin-sdk` | typed entities、manifest、proxy、runtime action 通过测试 |
| P1 | 平台适配器 EBA 化 | LangBot + SDK | 事件转换、能力声明、通用/透传 API 通过 adapter checklist |
| P2 | Host 观察者与响应者路由 | LangBot backend | observer 广播 + Pipeline/Agent/discard 单目标仲裁可运行 |
| P3 | 独立 Agent 与 Runner 注册 | LangBot backend + plugins | Agent CRUD、registry、run authorization、delivery 可运行 |
@@ -32,8 +32,8 @@ EBA 跨越 SDK、平台适配器、LangBot Host、WebUI 与插件生态,按可
- 定义规范化平台事件、actor/subject/conversation/delivery context。
- 定义 adapter `supported_events``supported_apis` 与平台透传 API。
- 定义 AgentRunner manifest、run context/result、resource handles 和 pull/callback API。
- 提供 `AgentRunAPIProxy` 与 SDK-owned scoped MCP bridge。
- 定义 Runner manifest、run context/result、resource handles 和 pull/callback API。
- 提供 `RunnerAPIProxy` 与 SDK-owned scoped MCP bridge。
- 保持协议传输与权限校验可测试,不把 Host 私有 Query 对象暴露给插件。
### 验收
@@ -76,7 +76,7 @@ adapter event
- Plugin EventListener 是 observer,不作为 priority fallback。
- Pipeline 只处理消息事件并复用完整 Stage 链。
- Agent 使用独立 Agent 配置和 AgentRunner Host orchestrator。
- Agent 使用独立 Agent 配置和 Runner Host orchestrator。
- edit/reaction 等事件的 observer 副作用能力按事件和 adapter 能力过滤。
- dry-run 与合成派发必须使用同一匹配器,避免 UI 预览与真实路由漂移。
@@ -86,13 +86,13 @@ adapter event
- 同一事件最多一个响应目标,但 observer 仍能收到事件。
- Pipeline 与 Agent 可以在同一个 Bot 的不同 binding 中同时生效。
## 6. P3:独立 Agent 与 AgentRunner
## 6. P3:独立 Agent 与 Runner
### 工作项
- `agents` 只保存 Agent;Pipeline 继续使用自己的表和 API。
- Agent config 使用 `runner.id``runner_config[runner_id]`
- registry 只展示已安装、有效的插件 AgentRunner。
- registry 只展示已安装、有效的插件 Runner。
- Host 构造 run-scoped resources、state、delivery 与 event log/transcript。
- SDK/Python `call_tool` 和 scoped MCP bridge 都回到同一个 Host ToolManager。
- Box session 由 Host 将 instance/workspace/bot/adapter/target/thread scope 规范化并哈希为固定长度 `lb-box-<sha256>`;同 scope 稳定、不同 scope 隔离、缺少 identity 时 fail closed。
@@ -117,7 +117,7 @@ adapter event
### 验收
- 页面不出现 LocalAgent 专属 banner、变量隐藏或 Box/Pipeline 注入逻辑。
- 空 Runner 市场状态给出可安装 AgentRunner 的正常路径。
- 空 Runner 市场状态给出可安装 Runner 的正常路径。
- Pipeline Debug Chat/Monitoring 与 Agent 运行日志分别可用。
## 8. P5:发布门禁
@@ -125,7 +125,7 @@ adapter event
### 自动化
- LangBot backend unit/integration tests 与 Ruff。
- SDK AgentRunner/proxy/MCP bridge tests。
- SDK Runner/proxy/MCP bridge tests。
- Web lint/build 与关键 Playwright cases。
- `skills/bin/lbs validate``skills/bin/lbs index --check`
- LocalAgent 与其他官方 Runner plugin package/test gate。
@@ -1,6 +1,6 @@
# Agent 与 Pipeline 统一编排(产品最终形态)
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound EventProcessor instances, a third peer processor type alongside Agent and Pipeline.
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound Runner instances, a third peer processor type alongside Agent and Pipeline.
> **状态**:历史方向稿(2026-06-12);2026-09-05 标记归档用途。本文的示意 schema、5.0 发布火车、SDK 0.5.0aX 配套与多租户“预留”描述不再作为实施合同。当前 4.11 产品形态见 [08-agent-page-and-event-orchestration.md](./08-agent-page-and-event-orchestration.md),协议见 [PROTOCOL_V1.md](../agent-runner-pluginization/PROTOCOL_V1.md),已完成与剩余事项见 [STATUS.md](../agent-runner-pluginization/STATUS.md)。保留正文仅用于解释早期设计取舍。
>
@@ -20,7 +20,7 @@
EventRouter(事件 → 处理器绑定)
├─→ 选中的处理器(响应者,单一仲裁)
│ ├─ Pipeline:保留现有实体和执行链,仅处理消息事件
│ └─ Agent:用户新建并选择 AgentRunner 插件,可接本地、低代码或外部 runtime
│ └─ Agent:用户新建并选择 Runner 插件,可接本地、低代码或外部 runtime
└─→ 插件 EventListener(观察者,N 个广播,可 prevent_default
```
@@ -51,7 +51,7 @@ EventRouter(事件 → 处理器绑定)
04 文档中的 pipeline / agent / webhook / plugin 四种 handler_type,本质上都是"对事件作出响应的逻辑",差别只在编写和部署方式。产品层统一展示和绑定这些处理器,但不会把既有 Pipeline 持久化为 Agent
- **产品**:用户只需理解"给 Bot 的事件绑定处理器",处理器可以是 Pipeline 或 Agent
- **工程**:路由层按 `target_type` 分发到 Pipeline 或 AgentAgent 的扩展集中到 AgentRunner 抽象;
- **工程**:路由层按 `target_type` 分发到 Pipeline 或 AgentAgent 的扩展集中到 Runner 抽象;
- **生态**:Agent 成为市场上可分发、可复用的一等公民。
### 2.2 收编映射
@@ -59,7 +59,7 @@ EventRouter(事件 → 处理器绑定)
| 原 handler_type04 文档) | 收编后 |
|---------------------------|--------|
| `pipeline` | 保留 Pipeline 实体;binding 使用 `target_type=pipeline` 和原 `pipeline_uuid`,进程内直接复用 MessageAggregator → QueryPool → Pipeline 机制 |
| `agent`RequestRunner | 用户新建独立 Agent,并选择对应 AgentRunner 插件;不读取或复制旧 Pipeline 内嵌 runner 配置 |
| `agent`RequestRunner | 用户新建独立 Agent,并选择对应 Runner 插件;不读取或复制旧 Pipeline 内嵌 runner 配置 |
| `webhook` | 外部 Agent 的一种:事件 POST 出去、响应解析为动作(保留 04 §5.4 的请求/响应格式) |
| `plugin`EventListener 分发) | **不收编**——角色不同,见 §2.3 |
@@ -76,7 +76,7 @@ EventRouter(事件 → 处理器绑定)
### 3.1 独立 Agent 与现有 Pipeline
Agent 与 Pipeline 都是一等处理器。用户创建 Agent、选择已安装的 AgentRunner,再把适合的事件绑定到 AgentPipeline 继续保存在 Pipeline 表中,以完整 Stage 链处理消息事件。两者可在同一处理器列表中以不同 `kind` 展示和选择;这种聚合展示不会创建额外记录,也不会在两种模型之间复制配置。
Agent 与 Pipeline 都是一等处理器。用户创建 Agent、选择已安装的 Runner,再把适合的事件绑定到 AgentPipeline 继续保存在 Pipeline 表中,以完整 Stage 链处理消息事件。两者可在同一处理器列表中以不同 `kind` 展示和选择;这种聚合展示不会创建额外记录,也不会在两种模型之间复制配置。
```python
class Agent(Base):
@@ -84,7 +84,7 @@ class Agent(Base):
uuid: str # 主键
name: str
kind: str # 固定为 "agent"Pipeline 使用自己的持久模型
component_ref: str # AgentRunner id,例如 plugin:<author>/<plugin>/<runner>
component_ref: str # Runner id,例如 plugin:<author>/<plugin>/<runner>
config: dict # JSON — runner id、runner config 与资源/状态/投递策略
# 多租户预留:归属主体字段(tenant/workspace),首版可空
```
@@ -156,7 +156,7 @@ class AgentChunk:
```
**流式**:复用 SDK 通信协议既有的 `chunk_status: continue/end` 机制,`handle()` 的每次 yield 对应一个 chunk。
**Pipeline 与 Agent 分流**Pipeline target 继续走 LangBot 进程内的 Pipeline 执行链;独立 Agent 经 AgentRunner 插件 runtime 分发。路由层通过 binding 的 `target_type` 明确区分二者。
**Pipeline 与 Agent 分流**Pipeline target 继续走 LangBot 进程内的 Pipeline 执行链;独立 Agent 经 Runner 插件 runtime 分发。路由层通过 binding 的 `target_type` 明确区分二者。
### 4.3 执行语义与可靠性
@@ -173,7 +173,7 @@ class AgentChunk:
| 版本 | 内容 | 备注 |
|------|------|------|
| 4.11(可选) | 现状成果:12 个 EBA 适配器、插件全事件订阅、`call_platform_api` | 对用户不可见的管道工程 + 插件新能力,不动产品概念 |
| **5.0** | 产品形态首发:EventRouter + event→处理器绑定 + WebUI 编排 + 旧 Bot 路由迁移 + 独立 Agent / AgentRunner 插件 + SDK Agent 组件契约(可标 experimental | `use_pipeline_uuid` 仅改写为指向原 Pipeline 的 binding,不生成 Agent;配 SDK 0.5.0 正式版;走 beta 周期 |
| **5.0** | 产品形态首发:EventRouter + event→处理器绑定 + WebUI 编排 + 旧 Bot 路由迁移 + 独立 Agent / Runner 插件 + SDK Agent 组件契约(可标 experimental | `use_pipeline_uuid` 仅改写为指向原 Pipeline 的 binding,不生成 Agent;配 SDK 0.5.0 正式版;走 beta 周期 |
| 5.x | 工作流 Agent(工作流引擎线挂入)、Agent 市场生态、剩余适配器(satori 等)、Agent 插件化收尾 | 验证开放注册机制 |
| 多租户 | 独立评估:仅数据隔离 → 5.x 部署选项;伴随权限/计费/产品定位变化 → 6.0 | 前置条件是 §4.3 的归属主体预留已落实 |
@@ -1,6 +1,6 @@
# 处理器页面与事件编排产品设计
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound EventProcessor instances, a third peer processor type alongside Agent and Pipeline.
> Implementation update (2026-09-08): the EventListener observer-broadcast proposal below is superseded by [Event processors](09-event-processors.md). Legacy EventListener hooks run only inside Pipeline. New EBA handlers use explicitly created and bound Runner instances, a third peer processor type alongside Agent and Pipeline.
> 状态:当前实现说明(2026-09-05),对应 `dev/4.11.x`。P0P3 已集成;发布验收见 [STATUS.md](../agent-runner-pluginization/STATUS.md)。
>
@@ -12,7 +12,7 @@ LangBot 的处理逻辑分成两种同级形态:
| 形态 | 定位 | 可处理事件 | 典型用户 |
| --- | --- | --- | --- |
| Agent | runner 驱动的事件优先处理器,承载 AgentRunner / 外部 runner | `message.*``group.*``friend.*``bot.*``feedback.*``platform.*` 等声明范围 | 需要直接处理多类平台事件或接入外部 agent runtime 的用户 |
| Agent | runner 驱动的事件优先处理器,承载 Runner / 外部 runner | `message.*``group.*``friend.*``bot.*``feedback.*``platform.*` 等声明范围 | 需要直接处理多类平台事件或接入外部 agent runtime 的用户 |
| Pipeline | 可视化、可控、可组合的消息处理流水线,执行完整 Stage 链 | 仅 `message.*`,首版等价于 `message.received` | 需要预处理、AI、后处理、扩展和输出控制的消息场景 |
处理器页面负责统一管理这两种处理单元:
@@ -38,7 +38,7 @@ LangBot 的处理逻辑分成两种同级形态:
- Pipeline:沿用原 Pipeline 配置页,包括 AI、触发、安全、输出、扩展、Debug、Monitoring
- Agent:基础信息由详情入口编辑,主配置分为运行器、运行器配置、事件与工具;事件范围、自动事件工具、平台级动作和普通工具白名单在同一配置流程内维护。
处理器详情复用 `ProcessorDetailWorkbench`Agent 与 Pipeline 保留各自的配置、调试和日志语义。`AgentRunnerSelect` 提供已安装 Runner 和市场安装入口,安装状态可恢复;Runner 配置来自动态 metadata,不按 LocalAgent id 定制 Host 表单。调试事件选择位于输入区域;Bot 的平台事件调试位于机器人配置中,路由 dry-run 只解释匹配结果。
处理器详情复用 `ProcessorDetailWorkbench`Agent 与 Pipeline 保留各自的配置、调试和日志语义。`RunnerSelect` 提供已安装 Runner 和市场安装入口,安装状态可恢复;Runner 配置来自动态 metadata,不按 LocalAgent id 定制 Host 表单。调试事件选择位于输入区域;Bot 的平台事件调试位于机器人配置中,路由 dry-run 只解释匹配结果。
`/home/pipelines` 继续提供 Pipeline 直接编辑路径;共享处理器入口当前使用 `/home/agents`。URL 是实现路径,不代表 Agent 包含 Pipeline。
@@ -174,8 +174,8 @@ Bot 使用 `event_bindings` JSON 字段持久化路由。当前未引入独立
- EBA 事件先广播插件 observer。
- 然后按 `event_bindings` 的事件模式、filters、priority 和顺序选择一个处理器。
- Pipeline 目标通过 MessageAggregator 进入完整 Pipeline Stage 链;Agent 目标直接进入 AgentRunner 链路。
- 非消息事件只选择声明支持该事件的 Agent,不调用 PipelineAgentRunner 输出有平台 reply target 时会投递回平台。
- Pipeline 目标通过 MessageAggregator 进入完整 Pipeline Stage 链;Agent 目标直接进入 Runner 链路。
- 非消息事件只选择声明支持该事件的 Agent,不调用 PipelineRunner 输出有平台 reply target 时会投递回平台。
## 7. 不做的事
+47 -179
View File
@@ -1,30 +1,18 @@
# Event processors and Pipeline plugin compatibility
Status: implemented in the 4.11 development branches of LangBot and the Plugin SDK,
2026-09-08. The Host uv configuration pins the matching SDK commit. Deploy both
revisions together; older SDK releases do not contain this component. Switch the
development source pin to a published SDK release before a stable PyPI release.
This design supersedes the automatic EBA EventListener observer broadcast in
the earlier EBA documents. Existing Pipeline plugin behavior remains supported.
# Runner components and Pipeline plugin compatibility
## Product boundary
Three processor types appear together in the Processors area:
| Product | Implementation | Event entry |
| --- | --- | --- |
| Pipeline | Pipeline stages and an agent-capable Runner | Received messages |
| Agent | A Runner with `spec.usages: [agent]` | Configured events |
| Plugin processor | A Runner with `spec.usages: [event]` | Events declared in `spec.events` |
| Product | Implementation | Event entry | Flow ownership |
| --- | --- | --- | --- |
| Pipeline | Existing Pipeline stages and configuration | Received messages | Pipeline stages, including legacy plugin hooks |
| Agent | A configured plugin AgentRunner | Supported EBA events | The selected runner |
| Event processor | A configured plugin EventProcessor | Supported EBA events | Plugin Python handlers |
Use **Event processor** as the product label and **EventProcessor** as the SDK
component name. The localized description should explain that the plugin defines
the processing logic. It must not suggest an LLM, prompt, or visual workflow is
required.
An installed component is a reusable implementation. A processor instance is a
user-created configuration of that component. A Bot event binding selects an
instance, not an installed plugin package directly.
Runner is the only component for these execution styles. `spec.usages` can contain
both `agent` and `event`; these are selection capabilities, not mutually exclusive
execution modes. An installed component is reusable code. Users create processor
instances, select a Runner and configure it, then bind Bot events to the instance.
Installation alone never subscribes a component to incoming events.
## Legacy EventListener contract
@@ -57,168 +45,48 @@ information must be distinguished from fields that were dropped during conversio
Direct Agent and Event processor execution must not synthesize Pipeline lifecycle
hooks. Those hooks describe actual Pipeline stages.
## EventProcessor SDK contract
## SDK and runtime
Introduce a distinct component kind instead of changing what an existing
EventListener manifest means. One package may contain both kinds; only the legacy
EventListener participates in Pipeline hook dispatch.
`lbp comp Runner` generates `components/runner`. Every component uses
`plugin:author/plugin/name` as its identity. Names are unique within a plugin.
The component can override `async run(ctx)` and yield RunnerResult objects, or
register typed platform callbacks through `@self.handler(EventClass)` in
`initialize()`. Default run dispatches an exact handler, falling back to EBAEvent.
A custom run can delegate to this dispatch with `await super().run(ctx)`.
Retain the familiar authoring shape:
Both styles share RunnerContext, invocation-bound ctx.api, logs, replies, deadlines,
cancellation, worker isolation and the run ledger. ctx.event is the envelope;
ctx.platform_event is the typed platform payload. Each invocation owns its context;
never put the current context or run ID on a shared component or plugin instance.
```python
from langbot_plugin.api.definition.components.event_processor import EventProcessor, EventProcessorContext
from langbot_plugin.api.entities.builtin.platform.events import MemberJoinedEvent
class WelcomeProcessor(EventProcessor):
async def initialize(self):
await super().initialize()
The runtime emits completion on normal return unless the Runner already emitted a
terminal result. Exceptions fail the run and retain preceding results. Cancelling
the result stream cancels execution. There is no implicit retry or hidden model
loop. Returned text and logs do not send platform messages: replies are explicit
ctx.reply / ctx.reply_stream actions. Pipeline retains its configured output stage.
@self.handler(MemberJoinedEvent)
async def on_join(ctx: EventProcessorContext):
await ctx.reply(f"Hello, {ctx.event.member.nickname}")
```
`self.plugin` continues to expose ordinary plugin APIs. ctx.api carries run-scoped
resource grants and records tool actions. Workspace and installation authorization
remain Host-enforced. Run identity and API operation scope are separate concepts.
Handlers receive typed EBA events directly. Do not maintain a second, incomplete
mapping into plugin-only EBA wrapper classes. Preserve complete public event
fields; compact log previews must not become the execution payload. Include the
generic platform-specific event contract for adapter-specific events.
## Selection and observability
The context belongs to one invocation and exposes the event, processor/run
identifiers, instance configuration, logging, and authorized Host APIs. It has no
fabricated Pipeline Query. Reuse Host run tracking, deadlines, installation
authority, platform capabilities, and delivery records where appropriate.
Both product selectors discover the same Runner catalog and filter by usage.
Validate usage again before execution. Event-capable Runners must declare events;
users can route a subset, but cannot expand the manifest capability. Unconfigured
instances expose no event subscriptions. Workspace ownership, plugin scope and
instance identity are checked for routing, execution, cancellation and run reads.
A handler returning normally completes its invocation. There is no implicit LLM
loop, automatic second processor, or hidden retry of side effects. An exception
marks the run failed and retains the associated log. New processing handlers do
not use prevent_default to control another processor; routing has already chosen
the current processor. The legacy methods keep their existing Pipeline meaning.
Plugin processor details keep event debugging on the left and configuration/logs
on the right. Component settings use the existing schema form. Logs and action
results remain distinct from actual platform delivery; debug delivery is Mock.
Agent-native interactions stay on the Agent product path; typed handlers consume
platform events. Legacy Pipeline lifecycle hooks remain on the Pipeline path.
## Activation and routing
## Validation
The activation sequence is explicit:
1. Install a plugin containing an EventProcessor component.
2. Create an Event processor in the Processors area.
3. Open its detail page, select a plugin component, and save its configuration.
4. Bind a Bot event to that processor instance in the existing event routing UI.
Installation and processor creation alone do not subscribe to Bot events.
The component declares the event types it handles; Bot bindings select the subset
of supported events to deliver. One package may supply multiple components, and
multiple instances may use the same component with independent configuration.
Extend the existing single-target route arbitration with `event_processor`.
There is no automatic EBA broadcast to installed EventListeners. Keep Pipeline hook dispatch inside the Pipeline path. Existing observer
plugins must explicitly adopt the new component and be bound by the user; do not
create subscriptions during migration.
An unconfigured instance has no supported events and cannot execute. Validate
component availability, event compatibility, Workspace ownership, and instance
identity when configuring the instance and again at invocation. A disabled or
unavailable plugin leaves the instance visible with an actionable unavailable
status. It must not silently fall back to Agent or Pipeline.
## Compact UI
Creation adds a third type next to Agent and Pipeline and asks only for basic
instance information. Select the plugin component in the detail-page header.
Show component-defined configuration in the right pane, with Configuration and
Logs tabs. Keep unsaved values when switching tabs, and open Logs after a debug
run finishes. The component selector remains in the page header.
If no component is installed, show a relevant plugin installation entry point;
installing still does not create a binding.
The detail page keeps event debugging on the left while the right pane switches
between configuration and logs. A compact run list shows event type, time, status and known
processing duration. Selecting a row shows that run's identity, input, logs,
actions and outcome below. There is no shared timeline between unrelated runs.
The additive `created_at_ms`, `started_at_ms`, and `finished_at_ms` fields retain
Host lifecycle precision for elapsed-time display.
Keep payloads and error details collapsed until expanded. Distinguish attempted
delivery from confirmed delivery and display the actual destination.
Place component identity, availability, bindings, and configuration in a compact
secondary area. Do not add a prompt editor, model selector, or flow designer.
The plugin implements the processing flow in code.
## Delivery sequence and acceptance
1. Repair and regression-test Pipeline EventContext handling and legacy payload
conversion independently of the new processor feature.
2. Add the SDK component, context, manifest/scaffolding, and explicit invocation
contract; verify registration, event coverage, and process isolation.
3. Add Host instance management, event routing, execution tracking, and matching
HTTP/MCP/skill surfaces. Turn off automatic EBA observer dispatch in this step.
4. Add creation, binding, availability, logs, and delivery trace UI with i18n.
5. Exercise a real packaged plugin through installation, explicit instance
creation, Bot binding, invocation, logging, and reply delivery.
Acceptance must prove that installation alone invokes no handlers; one matching
binding invokes exactly the chosen component; instance configuration and run
history remain separate; all declared EBA events retain their fields; unavailable
components fail visibly; and legacy plugins keep the documented Pipeline hook
order and behavior. Unit tests alone do not establish a successful live plugin
installation or platform delivery.
## Implemented transport and APIs
`lbp comp EventProcessor` scaffolds a component in `components/event_processor`.
Its manifest uses `kind: EventProcessor` and `spec.events`, for example
`[group.member_joined]`. `spec.config` defines instance parameters. A component
that calls `ctx.reply()` declares `spec.permissions.tools: [detail, call]`.
References use `event_processor:author/plugin/component`, separate from
`plugin:author/plugin/runner`. Both kinds share the existing run transport,
installation authorization, deadlines and run ledger. The trusted Host selects
the component kind; the worker invokes only that exact kind and name.
There is no model invocation in the EventProcessor base class.
`EventProcessorContext` provides `event`, `run_id`, `config`, `api`, `log()` and
`reply()`. `api` is the existing run-scoped Host proxy. Use `ctx.config` for instance
parameters; plugin installation configuration remains separate. Handlers may
register the `EBAEvent` base class as a catch-all. An exact typed handler takes
precedence over that fallback. Multiple handlers for the same type run in their
registration order, within one invocation.
HTTP instance management uses `/api/v1/agents` with `kind: event_processor`.
Metadata at `/api/v1/agents/_/metadata` lists installed `event_processors`.
Creation accepts `component_ref` and `parameters`; the Host derives the supported
event patterns from the component. Bot bindings use `target_type: event_processor`
and the created instance UUID as `target_id`.
- `GET /api/v1/agents/{id}/runs?before_id=...` lists this instance's runs.
- `GET /api/v1/agents/{id}/runs/{run_id}/events?after_sequence=...` pages its logs
and action results. A run from another instance or Workspace is rejected.
- The corresponding MCP tools are `get_processor_metadata`, `list_processor_runs`
and `get_processor_run_events`, alongside processor CRUD.
- `/api/v1/agents/{id}/debug` accepts a full typed EBA event in `data`. Platform
actions use Mock; other authorized tools retain their configured behavior.
The detail page polls run updates, keeps payload details collapsed and separates
logs from platform delivery. Completed handlers produce no synthetic reply text.
## Verification (2026-09-08)
- SDK API, scaffolding and Plugin Runtime suites: 684 passed.
- Host runner, service, controller, MCP and adapter regression suites: 971 passed.
- Pipeline and registry regression suites: 243 passed, one environment-dependent skip.
- Frontend unit suite: 74 passed; TypeScript and changed-file lint checks passed.
- Real packaged-plugin tests cover installation, component-kind separation,
invocation, mock platform delivery, instance isolation and persisted logs.
- Authenticated Edge testing created an instance and a loopback OneBot bot, saved
a member-join binding, injected one native notice and received exactly one
`send_group_msg` response. The detail page displayed the completed run,
localized action name, destination and returned message ID. No external IM
account or live model was involved.
- Browser regression covers expanding long payloads, reaching the last log and
pagination without duplication. Eight unrelated existing browser failures were
reproduced against the pre-change commit; the full suite is not green.
- Repository-wide lint also retains the pre-existing duplicate `send_image_msg`
in the WeCom customer-service library and existing formatting failures outside
this change. The i18n check has the same pre-existing diagnostics as its baseline.
Native Agent interaction-resumption is not enabled for EventProcessor bindings;
its input contract is the platform EBA event collection, not a synthetic Agent
continuation. Plugins should handle platform events through their typed handlers.
SDK tests cover both execution styles, event matrices, concurrent contexts,
termination, cancellation and permissions. Packaged CLI tests generate, build and
execute the published component. Core tests cover usage-filtered discovery, event
routing, Workspace authorization and real plugin-runtime transport. RunnerDemo
provides multi-step actions, configuration isolation and controlled failures.
+7 -7
View File
@@ -13,7 +13,7 @@
┌──────────────────────────────────────────────────────────────────┐
│ LangBot 主进程 │
│ │
AgentRunner ──> SDK call_tool / scoped MCP bridge │
│ Runner ──> SDK call_tool / scoped MCP bridge │
│ │ │ │
│ └────────────────> ToolManager ──> NativeToolLoader │
│ │ │ │ │
@@ -87,8 +87,8 @@
**核心设计原则**:
- Box Runtime 作为独立进程运行,通过 Action RPC 与 LangBot 主进程通信,两者复用 SDK 的 IO 层(Handler → Connection → Controller
- 一个 session_id 对应一个容器/沙箱实例。同一 session 内可并存多条 mount 与多个 managed process
- AgentRunner 无权指定 session scope。SDK/Python `call_tool` 与 scoped MCP bridge 都发出同一个 `PluginToRuntimeAction.CALL_TOOL`,最终由 Host 的 ToolManager 执行,并使用当前 run 保存的同一个 execution Query
- Box 内托管的 stdio MCP server 使用独立的长期 `mcp-shared` session;它不是 AgentRunner 本次事件的 sandbox session(详见 [box-session-scope.md](./box-session-scope.md)
- Runner 无权指定 session scope。SDK/Python `call_tool` 与 scoped MCP bridge 都发出同一个 `PluginToRuntimeAction.CALL_TOOL`,最终由 Host 的 ToolManager 执行,并使用当前 run 保存的同一个 execution Query
- Box 内托管的 stdio MCP server 使用独立的长期 `mcp-shared` session;它不是 Runner 本次事件的 sandbox session(详见 [box-session-scope.md](./box-session-scope.md)
---
@@ -140,7 +140,7 @@ BoxService
**输出截断**: 默认 4000 字符上限,保留前 60% + 后 40%,中间插入 `[...truncated...]`
**Session 所有权**: `resolve_box_session_id(query)` 只接受 Host 已确定的私有 scope 或 Query launcher/session identity,并输出 `lb-box-` + 64 位小写 SHA-256 十六进制摘要(固定 71 个 ASCII 字符)。哈希输入是 canonical JSON,包含 instance、workspace、bot、platform adapter、target type/id 与 thread;原始用户、群组、conversation 或 event id 不会出现在 Box session id 中。相同 Host scope 稳定复用,不同 target/thread/workspace/bot/adapter/instance 相互隔离;缺少可用 identity 时 fail closed。Pipeline、Agent 或 AgentRunner 配置都不能覆盖该规则。
**Session 所有权**: `resolve_box_session_id(query)` 只接受 Host 已确定的私有 scope 或 Query launcher/session identity,并输出 `lb-box-` + 64 位小写 SHA-256 十六进制摘要(固定 71 个 ASCII 字符)。哈希输入是 canonical JSON,包含 instance、workspace、bot、platform adapter、target type/id 与 thread;原始用户、群组、conversation 或 event id 不会出现在 Box session id 中。相同 Host scope 稳定复用,不同 target/thread/workspace/bot/adapter/instance 相互隔离;缺少可用 identity 时 fail closed。Pipeline、Agent 或 Runner 配置都不能覆盖该规则。
**Skill 挂载合并**: `execute_tool()` 调用时,`build_skill_extra_mounts(query)` 会把当前 pipeline-bound 的所有 skill 的 `package_root` 作为 `extra_mounts` 加入 BoxSpec,挂在 `/workspace/.skills/<name>`。LLM 通过 `activate` 工具显式激活某个 skill 后,工具调用才允许引用这个 skill 的虚拟路径。
@@ -421,7 +421,7 @@ ToolManager.initialize()
3. 若 skill 是 Python 项目(有 `requirements.txt``pyproject.toml`),命令会被 venv bootstrap 包裹(在 skill 挂载点内创建 `.venv`
4. 调用 `box_service.execute_tool()` → 走 Host 从当前事件生成的 session_id 与已组装好的 `extra_mounts`**不再为每 skill 起独立 session**
AgentRunner 可以直接通过 SDK/Python `AgentRunAPIProxy.call_tool` 调用这些工具,也可以让外部 harness 通过 SDK-owned scoped MCP bridge 回调。两条入口都发送 `PluginToRuntimeAction.CALL_TOOL`,共享同一个 run authorization、Host session 中保存的 execution Query、ToolManager 与 `resolve_box_session_id(query)` 规则;Runner 不能提交自定义 Box session id。Pipeline run 保存原 Query;纯 EBA run 由 Host 构造 `pipeline_config=None``pipeline_uuid=None` 的最小 Query。
Runner 可以直接通过 SDK/Python `RunnerAPIProxy.call_tool` 调用这些工具,也可以让外部 harness 通过 SDK-owned scoped MCP bridge 回调。两条入口都发送 `PluginToRuntimeAction.CALL_TOOL`,共享同一个 run authorization、Host session 中保存的 execution Query、ToolManager 与 `resolve_box_session_id(query)` 规则;Runner 不能提交自定义 Box session id。Pipeline run 保存原 Query;纯 EBA run 由 Host 构造 `pipeline_config=None``pipeline_uuid=None` 的最小 Query。
### 4.3 MCP-in-Box (`mcp_stdio.py`, 354 行)
@@ -442,7 +442,7 @@ initialize()
每条 MCP server 是同一 session 中的一个 managed process,独立的 `process_id`、独立 attach URL,互不阻塞。
这里的 `mcp-shared` 只承载 LangBot 管理的 stdio MCP server 进程。AgentRunner 的 scoped MCP bridge 是回调 Host 工具的协议入口,不会把事件运行的 exec/read/write 改到 `mcp-shared`
这里的 `mcp-shared` 只承载 LangBot 管理的 stdio MCP server 进程。Runner 的 scoped MCP bridge 是回调 Host 工具的协议入口,不会把事件运行的 exec/read/write 改到 `mcp-shared`
---
@@ -582,7 +582,7 @@ volumes:
### Session scope
Pipeline 与 AgentRunner 配置不再暴露 sandbox session 模板。Host 将当前平台会话/事件 scope 规范化后哈希成固定长度的 `lb-box-<sha256>`;相同 scope 稳定复用,不同 scope 隔离,缺少 identity 时拒绝执行。SDK/Python 与 scoped MCP bridge 的工具调用遵守同一规则。详见 [box-session-scope.md](./box-session-scope.md)。
Pipeline 与 Runner 配置不再暴露 sandbox session 模板。Host 将当前平台会话/事件 scope 规范化后哈希成固定长度的 `lb-box-<sha256>`;相同 scope 稳定复用,不同 scope 隔离,缺少 identity 时拒绝执行。SDK/Python 与 scoped MCP bridge 的工具调用遵守同一规则。详见 [box-session-scope.md](./box-session-scope.md)。
### REST API
+11 -11
View File
@@ -7,7 +7,7 @@
## 1. Decision
The LangBot Host owns the Box session used by an event run. A Pipeline, Agent,
or AgentRunner cannot choose a global, per-user, per-conversation, or per-query
or Runner cannot choose a global, per-user, per-conversation, or per-query
sandbox mode.
`BoxService.resolve_box_session_id(query)` always returns this shape:
@@ -81,7 +81,7 @@ Host scope or launcher/session identity is also rejected. There is no
## 3. Host execution Query
AgentRunner callbacks need a Host-owned Query view because model/tool loaders
Runner callbacks need a Host-owned Query view because model/tool loaders
already consume that type. The Query is internal and is never exposed as a
Runner-controlled object.
@@ -96,11 +96,11 @@ Runner-controlled object.
This gives Pipeline and pure EBA execution the same Host tool path without
inventing a fake Pipeline for an independent Agent.
## 4. AgentRunner callback paths
## 4. Runner callback paths
AgentRunner implementations may use either callback transport:
Runner implementations may use either callback transport:
1. SDK/Python runners call `AgentRunAPIProxy.call_tool`.
1. SDK/Python runners call `RunnerAPIProxy.call_tool`.
2. External harnesses call the SDK-owned scoped MCP bridge.
Both transports emit the same `PluginToRuntimeAction.CALL_TOOL`. The Host then
@@ -108,8 +108,8 @@ validates the same run authorization, restores the same execution Query, and
dispatches to the same ToolManager and BoxService.
```text
AgentRunner
+-- AgentRunAPIProxy.call_tool --------+
Runner
+-- RunnerAPIProxy.call_tool --------+
| |
+-- SDK-owned scoped MCP bridge -------+--> PluginToRuntimeAction.CALL_TOOL
--> run authorization
@@ -119,7 +119,7 @@ AgentRunner
--> lb-box-<sha256>
```
An AgentRunner is not required to use MCP. Local Python runners can use the SDK
An Runner is not required to use MCP. Local Python runners can use the SDK
directly; code-agent harnesses can use the bridge. The transports do not define
different authorization or sandbox semantics.
@@ -143,16 +143,16 @@ This is separate from the scoped MCP bridge above:
| Path | Purpose | Session rule |
| --- | --- | --- |
| AgentRunner scoped MCP bridge | Call authorized Host tools for one active run | Host-owned `lb-box-<sha256>` from the run execution Query |
| Runner scoped MCP bridge | Call authorized Host tools for one active run | Host-owned `lb-box-<sha256>` from the run execution Query |
| MCP-in-Box stdio server | Keep configured MCP server processes running | Dedicated persistent `mcp-shared` session |
Calling a sandbox tool through the AgentRunner bridge never redirects the run
Calling a sandbox tool through the Runner bridge never redirects the run
workspace into `mcp-shared`. Conversely, an MCP server's managed-process
lifecycle does not inherit the current event scope.
## 7. Configuration and compatibility
There is no Box session scope field in Pipeline metadata, AgentRunner config,
There is no Box session scope field in Pipeline metadata, Runner config,
or the public Pipeline/Runner API. Operators configure the Box subsystem itself
(`box.enabled`, backend/runtime settings, profiles, mount allowlists, quotas,
and workspace roots), not per-Runner session templates.
+1 -1
View File
@@ -62,7 +62,7 @@
| Backend selection | 良好 | 显式 backend 优先级、local 探测顺序、配置变更触发 reselect |
| MCP Box 集成 | 良好 | config model、路径重写、payload、shared-session 多 process |
| Native tool loader | 良好 | 6 工具(exec/read/write/edit/glob/grep)、路径穿越拦截 |
| AgentRunner 工具入口 | 良好 | SDK proxy 与 MCP bridge 都映射到 `PluginToRuntimeAction.CALL_TOOL`Host action 测试覆盖 run-scoped execution Query 与纯 EBA native exec |
| Runner 工具入口 | 良好 | SDK proxy 与 MCP bridge 都映射到 `PluginToRuntimeAction.CALL_TOOL`Host action 测试覆盖 run-scoped execution Query 与纯 EBA native exec |
| Skill 系统 | 良好 | 加载、Tool Call 激活、marker、路径解析、authoring CRUD、HTTP service |
---
+6 -6
View File
@@ -3,24 +3,24 @@
> 更新日期: 2026-06-29
> 分支: `mcp_resources`
> PR: langbot-app/LangBot#2215
> 主题: MCP Resources 在 LangBot 中的产品价值、AgentRunner 集成方式与后续架构方向
> 主题: MCP Resources 在 LangBot 中的产品价值、Runner 集成方式与后续架构方向
## 结论
PR #2215 对 LangBot 有明确价值:它补齐了 MCP 协议中 Resources 这一重要能力,让 MCP server 不再只暴露 tools,也可以暴露文档、代码片段、配置、日志、图片等上下文资源。管理端可以发现和预览资源,Agent 也可以通过当前实现按需列出和读取资源。
但当前 AgentRunner 层的接入方式更接近一个可用的第一阶段方案,而不是最终架构。现在 MCP Resources 被包装成两个 synthetic tools
但当前 Runner 层的接入方式更接近一个可用的第一阶段方案,而不是最终架构。现在 MCP Resources 被包装成两个 synthetic tools
- `langbot_mcp_list_resources`
- `langbot_mcp_read_resource`
这让模型可以通过 function calling 主动探索资源,落地成本低,也复用了已有 `ToolManager` / `LocalAgentRunner` 的工具调用链路。不过从 MCP 规范和主流实现来看,Resources 更适合作为一种一等上下文来源,而不是长期隐藏在工具列表里。
这让模型可以通过 function calling 主动探索资源,落地成本低,也复用了已有 `ToolManager` / `LocalRunner` 的工具调用链路。不过从 MCP 规范和主流实现来看,Resources 更适合作为一种一等上下文来源,而不是长期隐藏在工具列表里。
建议保留当前 synthetic tools 作为探索能力,同时把后续主线设计调整为:MCP Resources 是 pipeline / conversation / message 级别可选择、可固定、可审计的上下文输入。
## 当前实现判断
当前 AgentRunner 集成路径如下:
当前 Runner 集成路径如下:
```text
Pipeline 绑定 MCP server
@@ -28,7 +28,7 @@ Pipeline 绑定 MCP server
-> Preproc 为 local-agent 加载工具
-> ToolManager.get_all_tools()
-> MCPLoader 注入 synthetic resource tools
-> LocalAgentRunner 将工具 schema 传给模型
-> LocalRunner 将工具 schema 传给模型
-> 模型发起 list/read tool call
-> ToolManager.execute_func_call()
-> MCPLoader 调 MCP session.list_resources/read_resource
@@ -178,7 +178,7 @@ LangBot 后续应支持模板发现、参数填写、实例化和绑定。否则
- 支持 resource templates。
- 支持资源订阅更新。
- 支持 chunk、summary、RAG 化接入。
- 为 DifyAgentRunner、LocalAgentRunner 等不同 runner 定义统一资源上下文接口。
- 为 DifyRunner、LocalRunner 等不同 runner 定义统一资源上下文接口。
## 最终建议
@@ -68,7 +68,7 @@ Anthropic、Google 和 LiteLLM 的官方文档域名在本次环境中被浏览
- `LLMModel.extra_args` 是 JSON 字段,Web 端已有通用高级参数编辑器。
- `LiteLLMRequester` 会按“模型级 `extra_args`,再调用级 `extra_args`”的顺序合并参数。
- LiteLLM 已统一处理多个 Provider 的 `reasoning_effort``thinking` 和返回的 `reasoning_content`
- `LocalAgentRunner` 的非流式、流式、工具调用和 fallback 路径都经过 `RuntimeProvider.invoke_llm*()`
- `LocalRunner` 的非流式、流式、工具调用和 fallback 路径都经过 `RuntimeProvider.invoke_llm*()`
- `remove-think` 已能控制 `<think>` 或独立 reasoning 内容是否进入展示文本。
- Gemini 工具调用所需的 `provider_specific_fields` / thought signature 已有保留逻辑和单元测试。