跳转到内容

插件化架构与自动发现

插件化架构与自动发现

学习目标

理解 Nanobot 如何通过 pkgutil 扫描和 entry-point 插件实现四大子系统(工具、频道、技能、命令)的自动注册。

前置知识

下文假设你已理解上述概念,直接聚焦 Nanobot 的具体实现。

项目实践

工具自动发现

ToolLoader 通过 pkgutil 扫描 nanobot.agent.tools 包下的所有模块:

loader = ToolLoader()
registered = loader.load(ctx, self.tools)

自动发现的工具包括:

  • read_file, write_file, edit_file — 文件系统操作
  • exec — Shell 执行
  • web_search, web_fetch — 网络搜索和抓取
  • subagent — 子 Agent 生成
  • long_task — 长期任务
  • image_generation — 图像生成
  • cron — 定时任务

手动注册的工具(因为需要运行时状态引用):

self.tools.register(MyTool(runtime_state=self, modify_allowed=...))

频道自动发现

频道通过 pkgutil 扫描 nanobot.channels 包 + entry-point 插件双通道注册:

# 内置频道
for module in pkgutil.walk_packages(channels_path, prefix=channels_path + "."):
# 导入并注册 Channel 类
# 插件频道
for entry_point in iter_entry_points("nanobot.channels"):
channel_class = entry_point.load()

支持的频道:Telegram、Discord、Slack、飞书、微信、WhatsApp、Email、Matrix、QQ、企业微信、钉钉、MS Teams、MoChat、Signal、WebSocket 等 18 个。

技能自动发现

内置技能目录 nanobot/skills/ 下的每个子目录是一个技能:

技能功能
cron定时任务和提醒
githubGitHub 集成
image-generation图像生成
long-goal持续目标管理
memory记忆操作
skill-creator技能创建
summarize文本摘要
weather天气查询
tmuxtmux 集成

可通过 disabled_skills 配置禁用特定技能。

命令注册

命令通过 CommandRouter 注册,内置命令在 register_builtin_commands() 中批量注册:

self.commands = CommandRouter()
register_builtin_commands(self.commands)

支持优先命令(is_priority,如 /stop)和普通命令。

设计取舍

为什么用 pkgutil 而非 importlib.metadata

原因:pkgutil 扫描适用于包内模块的发现,不需要安装为独立包。entry-point 用于第三方插件的扩展。两者结合覆盖了内置和外部两种场景。

参考来源