场景
一个 4.10.11 的实例上跑着一条「客服问答流水线」,Runner 用的是内置的 local-agent;机器人「官网客服机器人」通过 http_bot 适配器接进来,再靠一条旧的流水线路由规则把消息送到这条流水线。
把同一份 data 目录交给 4.11.0 启动之后,你会同时看到两件互相矛盾的事:
- 数据库看起来「自己就好了」------表在、数据在、旧流水线也还在列表里;
- 但流水线一打开就是不对的状态:它的 Runner 指向一个 4.11 里已经不存在的东西,迁移预览页告诉你这条流水线「需要安装插件」。
如果你按 4.10 的直觉直接上手改配置,很容易把「结构格式怎么变」和「运行配置怎么搬」混成一件事。

这篇只讲一句话:升级有两条不同的路径。数据库结构(schema)由 Alembic 在启动时自动迁移;Runner 配置只能通过一个需要你明确确认的迁移 API 走完。把这两条分开看,迁移这件事就没有那么玄。
4.11 里怎么做
路径一:schema 在启动时自动迁移
4.11 可以直接对 4.10.11 的 data 目录启动,启动过程中会自动把 Alembic 迁到 head。本次实测(2026-10-16)的结果:
alembic_version从0023_bot_scoped_sessions迁到0037_metadata_text,跨 14 个 revision ,表数变为 50;- 从启动到首个 HTTP 200 大约 80 秒。这个阶段慢不等于卡死,不要看到服务还没起来就反复重启。
日志里的关键序列(本次实测(2026-10-16),data/logs/):
csharp
[INFO] : Initializing database type: sqlite...
[INFO] : Alembic migrations completed at head.
[INFO] : Loading models from db...
[INFO] : Loading bots from db...
[INFO] : Loading pipelines from db...
[WARNING] : Pipeline stage ConversationMessageTruncator is not registered; skipping
[INFO] : Loading knowledge bases from db...
那条 WARNING 要单独说清楚,因为它最容易被误读成「迁移失败」:
- 来源:
源码 src/langbot/pkg/pipeline/pipelinemgr.py:838; - 含义:流水线记录里存着一个 4.10.11 时代自带的阶段名,4.11 的注册表里没有同名阶段,于是跳过它继续加载;
- 实测影响:不阻断启动,其余阶段照常加载,这条流水线依然能跑完端到端请求(见下文「验证」)。
bot 路由这一块也是自动迁的。4.11 删掉了 bots 表上的 use_pipeline_name / use_pipeline_uuid / pipeline_routing_rules 三列,改为 event_bindings 与 plugin_processors:
源码 src/langbot/pkg/persistence/alembic/versions/0009_migrate_event_bindings.py:1-5的 docstring 写得很明确:绑定继续引用原流水线 UUID,这个迁移不创建 Agent 行、也不复制 Runner 配置;源码 src/langbot/pkg/persistence/alembic/versions/0011_drop_legacy_bot_routing.py随后删除上述三列;源码 src/langbot/pkg/persistence/alembic/versions/0035_pipeline_received_only.py再把旧的通配路由message.*收窄为message.received(实测库里就是message.received)。
换句话说:Alembic 管的是「表和路由长什么样」,它不负责把内置 Runner 换成插件 Runner。
路径二:Runner 配置迁移必须由你确认
Runner 那条路径走的是一个专门的迁移 API,源码里的注释写得很直接:
python
"""User-confirmed migration only; deliberately not API-key/MCP accessible."""
(源码 src/langbot/pkg/api/http/controller/groups/pipelines/migration.py:1)
两个端点都需要 USER_TOKEN:
GET /api/v1/pipelines/_/migration/preview------ 只读预览,权限Permission.RESOURCE_VIEW(源码 src/langbot/pkg/api/http/controller/groups/pipelines/migration.py:17);POST /api/v1/pipelines/_/migration/execute------ 真正执行,权限Permission.RESOURCE_MANAGE(源码 src/langbot/pkg/api/http/controller/groups/pipelines/migration.py:26)。
预览会告诉你:哪几条旧流水线待迁移、目标 Runner 是谁、有没有阻塞项。本次实测(2026-10-16)的预览结果:
- 1 条旧流水线「客服问答流水线」,
legacy_runner: "local-agent"; - 状态
needs_plugin,阻塞原因plugin_missing; - 目标插件
langbot-team/LocalAgent0.2.1 ,target_runner_id: plugin:langbot-team/LocalAgent/default; planner_version: "5";changed_paths包含ai.runner.runner、ai.runner.id、ai.runner_config、ai.local-agent等;- warnings 含
local.box_state_reset、migration.history_reset、migration.legacy_sections_archived、migration.output_policy_copied等(本次实测只记录了这几条,完整列表以接口返回为准)。

「确认」在协议层是强制的,不是界面上的礼貌:
- 不带确认的
POST /execute {"items":[]}→ HTTP 400confirmation_required(源码 src/langbot/pkg/api/http/service/pipeline_migration.py:131-133); - 只有带上
confirmed的请求才会放行,例如{"all":true,"confirmed":true,"install_plugins":true}(源码 src/langbot/pkg/api/http/service/pipeline_migration.py:420-429)。
执行完成之后,旧配置并没有被丢掉,而是被归档 :pipeline_migration_snapshots 落下一行,source_snapshot 是迁移前的完整配置 JSON,另有 source_fingerprint / target_fingerprint(sha256)、planner_version、state: active(本次实测(2026-10-16):source_snapshot 长 3053 字节)。
顺便澄清一个容易搞混的点:http_bot 适配器不是 4.11 新增的。4.10.11 与 4.11.0 的 http_bot.py 字节完全相同 (27029 字节,diff -u 输出为空),签名契约也一致(本次实测(2026-10-16))。升级后它还能接消息,是「本来就有的东西被保留」,不是「新功能」(具体支持取决于适配器/平台,请先核对支持矩阵)。
动手:步骤
0. 先复制一份 data 目录
升级是对数据目录发生的,所以先复制,原实例保持不动:
bash
cp -a /path/to/410/data /path/to/411-upgrade/data
1. 用 4.11 的镜像启动
4.11 需要两个容器:核心容器 + 插件 runtime 容器(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
升级场景就是把 -v 指向你复制出来的那个目录,容器名与端口按需改。启动后先等约 80 秒,让 Alembic 跑完再访问界面。
管理员账号 admin@langbot.local,密码 LangBot411!demo(本地演示值,请自行替换)。
2. 读预览
bash
curl -s -H "Authorization: Bearer <USER_TOKEN>" \
http://127.0.0.1:15400/api/v1/pipelines/_/migration/preview
3. 确认并执行
先看「不确认」会怎样(预期 400):
bash
curl -s -o /dev/null -w '%{http_code}\n' -X POST \
-H "Authorization: Bearer <USER_TOKEN>" -H 'Content-Type: application/json' \
-d '{"items":[]}' \
http://127.0.0.1:15400/api/v1/pipelines/_/migration/execute
# 400
再带确认执行(预期 200,响应里含 pipeline_uuids 与 task_id):
bash
curl -s -X POST -H "Authorization: Bearer <USER_TOKEN>" -H 'Content-Type: application/json' \
-d '{"all":true,"confirmed":true,"install_plugins":true}' \
http://127.0.0.1:15400/api/v1/pipelines/_/migration/execute

4. 确认落盘
bash
sqlite3 /path/to/411-upgrade/data/langbot.db \
"select state, planner_version, length(source_snapshot) from pipeline_migration_snapshots;"
验证
端到端证明「迁移后的流水线真的能通」:拿保留下来的 http_bot 机器人打一条真实请求。
POST /bots/<uuid>/sync,请求体:
json
{"query": "只回复两个字:收到"}
请求要带签名头(签名契约:对 "{timestamp}." + 原始请求体字节 做 HMAC-SHA256,十六进制结果前加 sha256=);签名密钥 legacy-inbound-secret(本地演示值,请自行替换)。
预期响应形态(本次实测(2026-10-16)):
json
{"message":[{"text":"收到","type":"Plain"}],"reply_to":"in_ef4b42dcd79444368c420a053b30f00e"}
实测耗时 4.14 s 。这条链路是:保留下来的 http_bot 机器人 → 事件绑定(message.received)→ 迁移后的流水线(Runner = plugin:langbot-team/LocalAgent/default)→ 本地 Ollama qwen3:0.6b。

还要复核两点:alembic_version 应等于 0037_metadata_text;pipeline_migration_snapshots 应有 1 行、state = active。
边界与注意
- 快照不等于回滚按钮 。
source_snapshot只是把迁移前的配置归档了下来,它不是公开下载,也不代表已经提供了恢复界面(官方文档 docs/pipeline-migration-config-map.zh-CN.md)。迁移前请自行导出数据库。 - 配置迁移不等于运行状态无损迁移 。原有远端会话、对话历史、Box 文件、未结束的表单令牌都不会自动导入,迁移前要接受新会话与状态重置(
官方文档 docs/pipeline-migration-config-map.zh-CN.md的相应小节)。 - 升级后运维要自己补 :实测该实例
GET /api/v1/system/info显示wizard_status: "none",升级后请自行确认工作区/账号可用性(本次实测(2026-10-16)沿用 4.10 的账号密码仍可登录)。 /reset的 500 是两版共有缺陷,不是迁移回归 :POST /bots/<uuid>/reset在 4.10.11 与 4.11.0 上都返回 HTTP 500,派发到源码 src/langbot/pkg/platform/sources/http_bot.py:373 → :395,报AttributeError: 'HttpBotAdapter' object has no attribute 'ap'(两版行号一致)。/sync不受影响。/sync的回复投递方式会因部署而异 :本次实测里,4.10.11 那个部署把回复通过签名回调送出、/sync响应里的message是空数组;4.11 这个部署则把回复直接放进/sync响应。这是观察到的部署级差异,具体成因未核实,请以你自己部署的实际响应为准。- 插件认证信息两边记录不一致,如实列出 :本实例
plugin_settings.install_info._certification为verification: "invalid"、admission_code: CERTIFIED_PLUGIN_OSS_UNTRUSTED_DEDICATED、runtime_profile: dedicated、certificate_component_model: stateless-v1、certificate_id: null;而市场侧同一版本记录为certificate_status: "issued"、certificate_id: cert:86f25832...。两处记录不一致,本文不宣称已验证有效签名,需要你按自己的合规要求自行核对。 - 迁移规划器文档自身有一处不一致:开头写「本文对应迁移规划器 v4」,后文又写「宽松迁移规则(planner v5)」;实测预览返回
planner_version: "5"。 - 插件产物落地位置容易找错:实测它在 runtime 容器内
/app/data/plugin-runtime/artifacts/sha256/<digest>/code/,宿主挂载的plugins/目录保持为空(本次实测(2026-10-16))。 - 涉及平台能力(某适配器支持哪些事件类型、某平台侧如何配置)时,具体支持取决于适配器/平台,请先核对支持矩阵。
小结与下一步
动手之前先读这两份:
- 置顶迁移文档:pipeline-migration-config-map.zh-CN.md ------ 字段去向与语义变更的完整清单,退出前请对照一遍你关心的字段;
- 版本页面:v4.11.0 release ------ 本次对比范围就是
v4.10.11 → v4.11.0。
想看内置 Runner 变成插件之后怎么安装、怎么在流水线里选,接着读本系列讲 Runner 插件的那篇;想直接省掉自托管这一步,可以看看云端 space.langbot.app 是否适合你的场景(是否可用取决于你的部署与账号情况,请自行核对,本文不作承诺)。插件源码与市场条目可在 langbot-plugins 查看。