把 Claude Code 和 Codex 接进微信、飞书、钉钉:LangBot Runner 插件实战

场景

一个研发团队已经把 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)。

验证

按顺序做四项:

  1. 接口层 :GET /api/v1/plugins 返回的数组里能找到 langbot-team/LocalAgent,且 enabled 为真。
  2. 数据层 :查 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
  1. 运行时装容器内 :ls /app/data/plugin-runtime/artifacts/sha256/<digest>/code/ 应该看到 manifest.yaml、main.py、pkg/、components/、CERTIFICATION.md;同时宿主挂载目录 plugins/ 仍是空的。找不到文件说明你看错了层。
  2. 流水线层 :读回流水线配置,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)。

相关推荐
Elasticsearch1 小时前
Jina AI:Elasticsearch 集成
elasticsearch
吃饱了得干活11 小时前
用 PageHelper 同步数据到 ES:能跑,但这几个坑得先知道
后端·elasticsearch
吃饱了得干活12 小时前
从 LIKE 查询到毫秒级搜索:Elasticsearch 核心原理与 Java 实战
后端·elasticsearch
Flynt12 小时前
我把真实的 ES 查询怼到 7059 星的 Rust 搜索引擎上:1366/1369 的兼容承诺,裂了 3 个缝
elasticsearch·搜索引擎·rust
goehou13 小时前
Agent 接飞书实战:回调验签、事件去重与异步回复(附踩坑)
实战·飞书·agent·mcp·im集成
TST-魚爷16 小时前
易视讯会议摄像头 + 全向麦克风实操讲解稿
android·电脑·钉钉·腾讯会议·zoom会议
七夜zippoe17 小时前
Agent 接入企业微信/钉钉:渠道对接实
ai·钉钉·企业微信·agent·渠道对接
AscendKing19 小时前
Docker Compose 一键部署 SkyWalking 10.2.0 + Elasticsearch8.11,分布式链路追踪完整实战
elasticsearch·docker·skywalking·链路追踪·微服务监控