场景
一个研发团队已经把 Claude Code 和 Codex 用顺手了:本地能读仓库、跑命令、连 MCP 服务。他们希望同事在企业微信、飞书、钉钉群里直接调用这套能力。
在 4.10 上这件事难做干净,难点不在接入侧:平台适配器早就有了,4.10.11 就带着 openclaw_weixin、lark、dingtalk 等适配器(源码 src/langbot/pkg/platform/sources/)。难的是处理侧 :4.10.11 的 Runner 是内置的固定几种,就是 src/langbot/pkg/provider/runners/ 下那 9 个文件(localagent.py、difysvapi.py、cozeapi.py、n8nsvapi.py、langflowapi.py、dashscopeapi.py、deerflowapi.py、tboxapi.py、weknoraapi.py)。想接 Claude Code,只能改 LangBot 的代码,或者在体系外再包一层 HTTP 服务。
4.11 把这件事翻了过来:Runner 自己变成了插件。平台侧只是事件来源------具体支持取决于适配器/平台,请先核对支持矩阵。

4.11 里怎么做
4.11 新增 :内置 Runner 的实现被整个删掉了。同一个路径 src/langbot/pkg/provider/runners/ 在 v4.10.11 下有 10 个文件(含 __init__.py,9 个真实 Runner),在 v4.11.0 下已不存在 ;src/langbot/pkg/provider/ 只剩 modelmgr/、session/、tools/(git ls-tree 两版本对比)。Runner 改由插件运行时装提供。
Runner 是一个插件组件 。运行时装通过 LIST_RUNNERS 把已安装插件里的 Runner 报给宿主,宿主侧由 RunnerRegistry 发现、校验并缓存(源码 src/langbot/pkg/agent/runner/registry.py:20,24,152)。Runner 的 id 由宿主生成,形状固定为 plugin:author/plugin_name/runner_name(源码 src/langbot/pkg/agent/runner/id.py:24-27),并且协议边界只接受 plugin: 前缀------非插件 id 直接抛错(源码 src/langbot/pkg/agent/runner/id.py:52-57;协议文档 PROTOCOL_V1.md §13 也写明 RunnerDescriptor.source 只允许 plugin)。
清单即契约 。每个 Runner 声明一份 manifest:id、name、label、description、capabilities、permissions、config_schema、metadata(官方文档 docs/agent-runner-pluginization/PROTOCOL_V1.md §4.2)。注意两点易混:capabilities 只是给界面和资源投影用的类型化布尔字段,不是 权限授予;permissions 才是访问上限,要与绑定策略求交(同上 §4.2)。
官方 Runner 插件与 id :ClaudeCodeAgent → plugin:langbot-team/ClaudeCodeAgent/default,CodexAgent → plugin:langbot-team/CodexAgent/default(官方文档 docs/agent-runner-pluginization/OFFICIAL_RUNNER_PLUGINS.md:33-34,该文档同时给出 LocalAgent、DifyAgent、CozeAgent、N8nAgent、LangflowAgent、DeerFlowAgent、DashScopeAgent、TboxAgent、WeKnoraAgent、ACPRunner 的对应 id)。
4.11 新增的适配器层 :src/langbot/pkg/platform/adapters/ 这个目录在 v4.10.11 下不存在,4.11 里它按平台拆成 12 个包(lark、dingtalk、telegram、discord、slack、kook、wecom、wecombot、wecomcs、officialaccount、qqofficial、aiocqhttp),每个包里是 manifest.yaml、adapter.py、event_converter.py 等;飞书的 manifest 自己声明为 kind: MessagePlatformAdapter,描述写着「支持事件驱动编排」(源码 src/langbot/pkg/platform/adapters/lark/manifest.yaml:1-4,13)。但入站侧的文件清单没变:v4.10.11 → v4.11.0 之间 src/langbot/pkg/platform/sources/ 下 22 个文件全部是修改,没有新增也没有删除。
配置落在哪里 :流水线的 AI 阶段有两个字段------ai.runner.id 存 Runner id,ai.runner_config[<runner_id>] 存这个 Runner 自己的配置(源码 src/langbot/templates/metadata/pipeline/ai.yaml:6-18);同一个流水线换 Runner,配置按 runner id 分开存。
动手:步骤
先起一个 4.11 实例。Runner 插件跑在独立的插件运行时装容器里,所以是两个容器(以下为本地演示值,请自行替换):
bash
docker network create lang7-411
docker run -d --name lang7-411-core --network lang7-411 --restart on-failure -e TZ=Asia/Shanghai \
-e BOX__ENABLED=false -e SPACE__DISABLE_TELEMETRY=true -p 15400:5300 -p 15480-15485:2280-2285 \
-v "$PWD/deploy/411/data:/app/data" rockchin/langbot:v4.11.0
docker run -d --name lang7-411-runtime --network lang7-411 --network-alias langbot_plugin_runtime --restart on-failure \
-e TZ=Asia/Shanghai -e SPACE__DISABLE_TELEMETRY=true -v "$PWD/deploy/411/data/plugins:/app/data/plugins" \
rockchin/langbot:v4.11.0 uv run --no-sync -m langbot_plugin.cli.__init__ rt
管理员初始账号是 admin@langbot.local,密码为本地演示值,请自行替换。
第 1 步:从插件市场装 Runner 插件。 界面路径是「扩展」→「扩展市场」(源码 web/src/i18n/locales/zh-Hans.ts:337-341),选中 Runner 插件点安装。命令行等价的是 POST /api/v1/plugins/install/marketplace,请求体 {plugin_author, plugin_name},返回 {task_id},任务名 plugin-install-marketplace(源码 src/langbot/pkg/api/http/controller/groups/plugins.py:923-960)。这条路径装出来的记录里 install_source 就是 marketplace。
本文实例实际装的是 langbot-team/LocalAgent;Claude Code / Codex 两个插件走同一个入口,仓库在 langbot-app/langbot-plugins 的 Runner/claude-code-agent、Runner/codex-agent 目录下。
第 2 步:确认装到了哪里。 这里最容易踩空:产物不在 你挂载的 plugins/ 目录里,而是在插件运行时装容器内的内容寻址目录 /app/data/plugin-runtime/artifacts/sha256/<digest>/code/,里面是 manifest.yaml、main.py、pkg/、components/、CERTIFICATION.md;宿主挂载的 plugins/ 目录保持为空(本次实测,2026-10-16)。该目录名里的 <digest> 就是数据库记下的 artifact_digest。
装完的判定条件有三条:
- 接口:
GET /api/v1/plugins返回的{plugins: [...]}里出现该插件(源码src/langbot/pkg/api/http/controller/groups/plugins.py:387-397)。 - 数据:
plugin_settings表新增一行,主键是(workspace_uuid, plugin_author, plugin_name),字段含installation_uuid、artifact_digest(长度约束 64)、runtime_revision、install_source、enabled(源码src/langbot/pkg/entity/persistence/plugin.py:12-35,46-51)。 - 日志:插件运行时装会依次打印
Mounting plugin langbot-team/LocalAgent...→Plugin ... mounted→Initializing Runner component: default→Component default initialized, instance type: DefaultRunner→Plugin langbot-team/LocalAgent initialized(本次实测)。
注意最后一行:运行时装实例化的是一个组件实例 (这里叫 DefaultRunner),Runner 能力挂在它上面。

第 3 步:在流水线里选 Runner。 打开流水线编辑,切到「AI 能力」(源码 web/src/i18n/locales/zh-Hans.ts:1941),里面的阶段卡片叫「运行方式」(源码 src/langbot/templates/metadata/pipeline/ai.yaml:7-9),字段叫「运行器」,是个必填下拉(同文件 :14-18)。选中的值在配置里是完整 runner id,例如 plugin:langbot-team/LocalAgent/default。换成 Claude Code 就选对应的 plugin:langbot-team/ClaudeCodeAgent/default。
选中后,该 Runner 的配置项以 ai.runner_config[<runner_id>] 写进流水线配置。本文实例里 LocalAgent 那一段(节选):timeout: 300、max-tool-iterations: 100、tool-execution-mode: serial、context-window-tokens: 200000、enable-all-tools: true,以及 tools: []、knowledge-bases: []、mcp-resources: [];其中 enable-all-tools、tools、mcp-resources、mcp-resource-agent-read-enabled 这几个键不在插件自己的 default.yaml 表单里,是 Host 注入的(本次实测,2026-10-16)。

第 4 步:把平台接成事件来源。 在企业微信、飞书、钉钉这类适配器里填好凭据,事件进来后经事件绑定送到流水线,最后由你选的那个 Runner 负责处理。平台接入本身不区分 Runner------同一个机器人可以按事件类型指向不同流水线,各自的 Runner 也可以不一样。
Claude Code / Codex Runner 的配置项(命令行名、超时、会话复用等)在插件 README 里有完整的字段表:command 默认 claude / codex,timeout 默认 300 / 1800 秒,reuse-session 默认 true,另有 workspace、ssh-target、mcp-servers-json 等(官方文档:langbot-plugins 仓库 Runner/claude-code-agent、Runner/codex-agent 的 README)。
验证
按顺序做四项:
- 接口层 :
GET /api/v1/plugins返回的数组里能找到langbot-team/LocalAgent,且enabled为真。 - 数据层 :查
plugin_settings表确认 digest 与 revision 已落库,预期形态(本文实例的实测值):
sql
SELECT plugin_author, plugin_name, artifact_digest, runtime_revision, install_source, enabled
FROM plugin_settings;
-- langbot-team|LocalAgent|2d2ce17055d70dd7736e6902595be3262992fd1598a00bd9d79d19fef1c16329|1|marketplace|1
- 运行时装容器内 :
ls /app/data/plugin-runtime/artifacts/sha256/<digest>/code/应该看到manifest.yaml、main.py、pkg/、components/、CERTIFICATION.md;同时宿主挂载目录plugins/仍是空的。找不到文件说明你看错了层。 - 流水线层 :读回流水线配置,
ai.runner.id必须以plugin:开头(规则见源码web/src/app/home/pipelines/pipeline-config-safety.ts:7-25),并且ai.runner_config里存在以该 id 为键的对象。再跑一条真实消息,确认回复来自你装的 Runner。
边界与注意
- 平台只是事件来源。 入站侧
src/langbot/pkg/platform/sources/的文件集合与 4.10.11 相同(22 个文件全部是修改、无增删),4.11 新增的是platform/adapters/事件适配层;能不能在某平台跑,由适配器和事件绑定决定,而不是 Runner。官方文档 docs/event-based-agents/01-event-system.md 里有一张「各平台事件支持矩阵」,文档自己注明该表是初步评估、以各平台文档为准。 - 市场安装要能连上市场服务。 走市场安装时,运行时会去
{space_url}/api/v1/marketplace/plugins/download/{author}/{name}/{version}下载包(源码src/langbot/pkg/plugin/connector.py:1795-1797),记录里install_source=marketplace。内网隔离环境要么打通这条出网,要么改用 GitHub / 本地包安装(install_source随之变成github/local)。 - 产物是内容寻址的,别去挂载目录里找。 市场侧记录的 digest 与你本地装的不一定是同一个(同一版本可能被重新打包),比对以
plugin_settings.artifact_digest为准------本文实例里这两个 LocalAgent 0.2.1 digest 就不同(本次实测)。 - 外部 CLI Runner 默认是很放权的。
ClaudeCodeAgent的dangerously-skip-permissions默认为true(README 说明是因为 LangBot 目前没有交互式审批流,可设为false恢复 Claude Code 自身检查);CodexAgent默认approval-policy=never、sandbox-mode=danger-full-access。两者都应只放在受信工作区、受限的系统账号下(官方文档 langbot-plugins README)。 - 外部 harness 路径的成熟度 :协议文档明确写了外部 harness runner「当前是 MVP / dev path」,它只证明协议可以接入,不代表发布级安全边界已经完备,也不代表 Docker 部署形态已达发布级(官方文档
PROTOCOL_V1.md§13)。 - 结构化交互不是「挂起等待」 :两个 CLI Runner 都会把
ask_user_question这类请求转成interaction.requested交给适配器渲染成卡片,用户回答期间 CLI 进程是被停掉的,回答提交后作为下一轮用户输入重新开始一次运行并恢复原会话(官方文档 langbot-plugins README)------「中途问一句」不会让进程一直挂着。 - 安装记录里的认证字段要对得上 :本文实例的
install_info._certification实测为verification: "invalid"、certificate_id: null,而市场侧同一版本是certificate_status: "issued"。这是两边记录的差异,别假设本地校验一定通过(本次实测,2026-10-16;认证与签名见本系列第 4 篇)。
小结与下一步
4.11 的这一刀切得很干净:Runner 不再是 LangBot 自带的东西,而是你从插件市场装、在应用里配、在流水线里选的一个组件。平台负责把事件送进来,Runner 负责怎么处理------本地 CLI(Claude Code、Codex、ACP 路径),或者 Dify、Coze、n8n、Langflow、DeerFlow 这些服务型 Runner。
主参考:置顶的迁移文档 docs/pipeline-migration-config-map.zh-CN.md,它同时列了迁移器要求的最低 Runner 插件版本;版本与发布说明见 v4.11.0 release。如果只想先看有哪些 Runner 插件可装,可以直接翻 langbot-plugins 的 Runner/ 目录。
下一步:如果实例是从 4.10 升上来的,旧配置怎么落到新形状是第 3 篇的内容------迁移会同时改动 ai.runner.runner、ai.runner.id 与 ai.runner_config。需要托管环境可另行了解 Cloud(https://space.langbot.app)。