场景
群里来了新人,机器人在旁边一句不说;有人申请把机器人加为好友,请求挂在那里没人处理;机器人被拉进新群,也没有任何动作。
问题往往不在适配器,而在通路本身:只有消息能走进去。4.10 的机器人只有一个入口字段组:use_pipeline_name、use_pipeline_uuid、pipeline_routing_rules(本次实测(2026-10-16):v4.10.11 实例 bots 表的列结构)。而 pipeline_routing_rules 能筛选的字段是 launcher_type、launcher_id、message_content、message_has_element------全部是消息上的条件(源码 src/langbot/pkg/persistence/alembic/versions/0009_migrate_event_bindings.py:35-52 里保留了这些旧字段名)。
以一个 QQ 群机器人为例:白天自动答问,新人入群要发欢迎语,好友申请要人工审核。4.10 里只能「把消息按会话或内容分给不同流水线」,另外两类事件没有去处。
4.11 里怎么做
4.11 把「机器人 → 一条流水线」换成了「机器人 → 事件绑定(event binding)」:一个机器人持有一组绑定,每条绑定回答三个问题------什么事件、什么条件下、交给谁。
数据模型(4.11 新增) 。绑定存在 bots 表新增的 JSON 列里:event_bindings、plugin_processors(源码 src/langbot/pkg/entity/persistence/bot.py:55-56),没有单独的路由表。同一次升级里,4.10 的三个旧列被 0011_drop_legacy_bot_routing.py 删除。单条绑定的字段(官方文档 docs/event-based-agents/04-event-routing.md:69-73,运行时另有 order):
event_pattern:事件类型。支持精确匹配、namespace.*与全局*三种写法(源码src/langbot/pkg/platform/botmgr.py:152-159)。filters:过滤条件,字段为chat_type、chat_id、message_text、message_element_types,运算符含eq、neq、contains、not_contains、starts_with、regex;条件之间是「与」关系。target_type+target_uuid:目标,取值pipeline、agent、discard(丢弃)三类,UI 上就是「流水线 / Agent / 丢弃」。priority:整数,越大越优先。enabled:为假时直接淘汰。order:列表顺序。保存时按数组下标写入(源码src/langbot/pkg/api/http/service/bot.py:257),UI 上拖动排序即改这个值。
仲裁顺序 。同一个事件最终只会有一个响应目标:先淘汰 enabled: false,再做事件类型匹配,然后是「流水线只接受消息事件」的目标校验,再逐条判断 filters,最后按 (priority, -order) 降序排序取第一条(源码 botmgr.py:274-345,其中 :330 收集、:335 排序;官方文档 04-event-routing.md:115-119)。落选的那条会被记为 lower_priority,不会静默消失------拖动排序与调大优先级是一回事。
事件命名(4.11 新增) 。事件类型是 {namespace}.{action} 形式的字符串(官方文档 docs/event-based-agents/01-event-system.md:5),常用的有 message.received、message.edited、message.deleted、message.reaction、group.member_joined、group.member_left、friend.request_received、bot.invited_to_group、feedback.received。平台专有事件统一归到 platform.{adapter}.{action},例如 platform.telegram.chat_member_updated(:447-451)。具体支持取决于适配器/平台,请先核对支持矩阵。
与 4.10 的差异要分清 :适配器不是 4.11 新增的。实测 v4.10.11 与 v4.11.0 的 http_bot.py 字节完全相同(27029 字节),4.10 早已有 aiocqhttp、kook、wecombot 等适配器。4.11 真正新增的是事件绑定的数据模型与事件路由 这套机制:适配器把事件发出来,绑定决定交给谁。哪个适配器会发出哪些事件由适配器自身声明;没有声明 supported_events 的老适配器只会发出 message.received(源码 EventBindingsEditor.tsx 的 DEFAULT_EVENTS 注释)。具体支持取决于适配器/平台,请先核对支持矩阵。
升级不是空的 :4.10 的旧路由规则会被机械转换。0009_migrate_event_bindings.py 把 use_pipeline_uuid 变成一条绑定,把 pipeline_routing_rules 每条规则变成一条绑定(键:launcher_type→chat_type、launcher_id→chat_id、message_content→message_text、message_has_element→message_element_types,运算符 eq→contains、neq→not_contains,源码 :38-52);绑定继续指向原来的流水线 UUID,不创建 Agent、不复制 Runner 配置。该迁移的 downgrade 是空实现(源码 :133 注释 not reversible)。随后 0035_pipeline_received_only.py 再把这类绑定的 message.* 收窄成 message.received。
动手:步骤
先起一个全新 4.11 实例(容器名、端口、数据目录可按需调整;挂载目录请先建好):
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
首次启动会跑完数据库迁移再监听端口;浏览器打开 http://127.0.0.1:15400,用初始管理员 admin@langbot.local 登录(密码为本地演示值,请自行替换)。接着:
- 进「机器人」,新建或选中一个机器人(这里用的是 HTTP 通用接入适配器)。
- 在机器人详情页找到「事件路由」卡片,标题下写着「设置收到事件后交给哪个处理器」。
- 新建的机器人默认已经有一条
message.received路由,目标是流水线;卡片顶部「支持的事件」按适配器声明的能力分组(这里只有「消息 · 1」)。

- 点「添加行为」,从常用场景里挑一个(回复收到的消息、欢迎新成员、审核好友请求等),或者用「添加路由」自己填事件与目标。
- 在新增的路由行上选事件与处理器:弹层里可以选已有的流水线或 Agent,也可以「创建新处理器」。下面这张图就是把行加了进去、还没保存的样子。

- 需要条件时展开「触发条件」,字段是会话类型 / 会话 ID / 消息文本 / 消息元素,条件是「全部满足才触发」。
- 拖动路由行即改
order,改「优先级」即改priority;关掉「启用」即停用。 - 保存后回到「检查路由」(dry run)核对一遍再正式接流量。
升级来的实例不用手工重配:把 4.10.11 的 data 目录复制一份,用同样的 docker run 指向它即可,旧路由规则会按上面的映射自动落成绑定。迁移前后的字段对照见置顶文档 pipeline-migration-config-map.zh-CN.md。
验证
三种方式,从快到慢:
- 卡片里的「检查路由」:选一个事件类型跑一次合成派发,它会逐条列出每条绑定的结果------已命中/已投递/已丢弃,以及被淘汰的原因,例如
event_pattern_mismatch(事件类型不匹配)、filters_mismatch(条件不满足)、lower_priority(顺序被压过)、processor_incompatible(流水线被指向非消息事件)。dry run 与真实派发用的是同一套匹配器(源码botmgr.py:361diagnose_eba_event_binding)。 - 「匹配记录」:机器人内存里最近的匹配明细。它重启后清空,不是持久日志;长期观测请用操作日志。
- 直接看库:
sqlite3 deploy/411/data/langbot.db "select name, event_bindings from bots"。一条升级来的绑定长这样(本次实测(2026-10-16)):{"event_pattern":"message.received","target_type":"pipeline","target_uuid":"2e59bbf9-...","filters":[],"priority":0,"enabled":true,"description":"Migrated from default pipeline binding","order":0}。只要target_uuid指向的流水线还在,这条路由就是通的。
边界与注意
- 一个事件只有一个响应目标。绑定之间是仲裁关系:即使两条都匹配,也只有排第一的那条执行。
- 流水线目标只吃
message.received。给非消息事件绑流水线,运行时会直接判定processor_incompatible,理由是「Pipeline targets only support message events」(源码botmgr.py:162、:315-317;UI 上也会提示「流水线 仅可用于 message.received 事件」)。想在入群时发欢迎语,目标要选 Agent 或插件事件处理器。 - 通配符被收窄过 。老库里写的
message.*被0035改写成message.received;如果你手工把新绑定写成message.*,模式层面它能匹配其他message.*事件,但只要目标是流水线,仍然会在目标校验那一步失败。 - 适配器与事件不是一一对应 。具体支持取决于适配器/平台,请先核对支持矩阵。官方文档里的矩阵表(
docs/event-based-agents/01-event-system.md:453-476)自述为「初步评估」,上量前请按自己用的平台逐个确认,拿不准的事件先写 待确认。 - 插件事件处理器是另一条并行通路 。卡片下方的「插件处理器」不属于仲裁:它自动接收插件声明的事件,与上方事件路由独立执行(源码
botmgr.py:285在仲裁中显式跳过它们,:1012起单独读取plugin_processors)。别把「插件已订阅事件」当成「机器人已处理事件」。 - 迁移的不可逆点 :绑定表的转换没有回退实现(
0009的 downgrade 为空),旧列由0011删除;Runner 配置的迁移是另一个用户确认的接口,需要你显式确认后才会执行。升级前请留好data目录备份。
小结与下一步
如果你正从 4.10 升上来,先读置顶的迁移字段对照表:pipeline-migration-config-map.zh-CN.md;想确认这个版本的完整变更范围,看 v4.11.0 release 页。事件类型与字段定义以官方文档 01-event-system.md 为准。本系列下一篇讲 Runner 插件:怎么从插件市场把 Runner 装进来,并在流水线里选中它。
如果你现在没有可用的部署环境,可以先用 LangBot Space(space.langbot.app)了解界面形态;它的能力边界请以站内说明为准。