Skill 热加载听起来像一个技术动作:把新文件加载进来,不重启服务。真正做起来会发现,加载本身反而不是最难的。
难的是这些问题:
- 老任务还在跑,新版本能不能直接替换?
- 新 Skill 依赖的库和旧版本冲突怎么办?
- 卸载 Skill 时,线程、连接、缓存有没有清干净?
- 新版本出问题,能不能快速切回旧版本?
所以热加载不是“动态加载文件”,而是一套运行时发布机制。
本文要点
- 热加载的重点是不中断服务地升级 Skill。
- 真正的难点是隔离、状态、卸载和回滚。
- 正在执行的任务不要强行切到新版本。
- 没有监控和回滚,就不要开放生产热加载。
为什么需要热加载
如果 Agent 平台只有几个固定 Skill,重启发布也能接受。
但当平台开始支持很多团队、很多业务线时,问题就来了。一个团队想更新“文章发布 Skill”,另一个团队正在跑“代码审查 Skill”。如果每次更新都要重启整个平台,会影响所有人。
热加载的价值是让 Skill 像插件一样独立升级:
- 新增 Skill 不影响已有 Skill。
- 更新 Skill 不打断正在执行的任务。
- 出问题可以只回滚某个 Skill。
- 不同项目可以暂时使用不同版本。
这很适合多租户 Agent 平台,但前提是底层隔离做得足够好。
难点在哪里
第一个难点是依赖隔离。
两个 Skill 可能依赖同一个库的不同版本。如果共享同一套运行环境,新版本可能把旧版本冲坏。解决办法是给 Skill 独立运行空间,至少做到依赖、配置和资源边界清楚。
第二个难点是状态一致。
一个任务开始时使用 Skill v1,执行到一半时 v2 发布了。这个任务应该继续用 v1,而不是中途切到 v2。否则同一个任务前后行为可能不一致。
第三个难点是资源清理。
Skill 可能打开连接、启动定时器、注册事件监听器。卸载时如果不清理,系统会慢慢泄漏资源。热加载系统一定要有 start、stop、dispose 这类生命周期钩子。
第四个难点是失败隔离。
新 Skill 加载失败,不能拖垮整个平台。某个 Skill 执行异常,也不应该影响其他 Skill。
正确生命周期
热加载应该像一次小型发布,而不是直接覆盖文件。
推荐流程如下。
第一步,上传新版本。平台先保存新版本,但不立即使用。
第二步,静态校验。检查 manifest、权限声明、依赖版本、输入输出格式、危险操作。
第三步,加载到隔离环境。新版本在独立空间启动,不能直接影响线上流量。
第四步,影子运行。拿真实输入跑新版本,但真实结果仍然使用旧版本。比较两边差异。
第五步,小流量切换。先让少量任务使用新版本,观察错误率、耗时和用户反馈。
第六步,全量切换。确认稳定后,新任务使用新版本。老任务继续用启动时绑定的版本。
第七步,延迟卸载旧版本。等老任务结束后,再释放旧版本资源。
怎么回滚
回滚要提前设计,不能出事后再想。
一个可回滚的 Skill 平台至少要做到:
- 每个 Skill 版本都有唯一编号。
- 新旧版本可以短时间共存。
- 路由层可以把新任务切回旧版本。
- 已经执行中的任务不强行迁移。
- 回滚后能验证核心功能是否恢复。
回滚触发条件也要写清楚。比如:
- 错误率超过 5%。
- P95 耗时超过旧版本 2 倍。
- 人工接管率明显上升。
- 出现安全或权限异常。
这些阈值不一定固定,但一定要提前定义。
什么时候不要用
热加载不是所有系统都需要。
如果你的平台只有少量内部 Skill,发布窗口可控,重启成本也低,普通发布流程可能更简单。
如果 Skill 会修改数据库结构、改变核心权限模型、影响全局配置,也不适合直接热加载。这类变更需要完整发布流程和人工审批。
如果没有监控、没有版本隔离、没有回滚能力,更不应该在生产环境开放热加载。否则你只是把“重启风险”换成了“运行时不可控风险”。
结论
Skill 热加载的核心不是加载,而是安全地替换能力。
能不能加载新文件只是第一步。真正决定质量的是:旧任务怎么处理、依赖怎么隔离、资源怎么释放、失败怎么回滚。把这些问题想清楚,热加载才是平台能力;想不清楚,它就是线上事故入口。