跳转到内容

打包插件

把想要复用或分享的应用行为放进插件。Python 包在 bub 入口点组中声明目标,Bub 导入这个目标,并注册其中的 hook 实现。你也可以在自己的服务中复用现有插件,继续使用宿主自己的调用入口。

完整的入门例子见编写第一个插件。这篇指南说明打包自己的插件时,需要选择哪些形式。

可移植的 Agent Plugins 使用另一种格式,包括 plugin.json、skills 和 MCP servers。Agent Plugins 集成通过一个 Python 插件加载这些包。

插件需要安装 Bub中说明的应用依赖。本指南使用 bub[app]>=0.6.0 作为包依赖。更新已有插件时,参见升级到 0.6.0。

[project.entry-points."bub"]
myplugin = "bub_myplugin.plugin"

键 myplugin 是诊断信息中的插件名称,值是要导入的 Python 对象。

选择一种目标形式:

目标 注册方式 适用情况
bub_myplugin.plugin 注册模块 hooks 是模块级函数
bub_myplugin.plugin:plugin 注册实例 hooks 需要共享对象状态
bub_myplugin.plugin:MyPlugin 将 BubFramework 传给类或工厂,注册返回值 hooks 需要访问 framework

模块形式在模块顶层定义 hooks:

from bub import hookimpl


@hookimpl
def build_prompt(message, session_id, state):
    return "Describe this workspace."

实例形式在目标模块中创建对象:

from bub import hookimpl


class MyPlugin:
    @hookimpl
    def build_prompt(self, message, session_id, state):
        return "Describe this workspace."


plugin = MyPlugin()

所有可调用目标都会收到 framework,类也一样。构造函数或工厂需要接收这个参数:

from bub import BubFramework, hookimpl


class MyPlugin:
    def __init__(self, framework: BubFramework) -> None:
        self.framework = framework

    @hookimpl
    def build_prompt(self, message, session_id, state):
        return f"Describe the workspace at {self.framework.workspace}."

这些例子会替换提示词。请在改变应用行为中选择真正适合任务的 hook。

如果包内定义了 @tool 函数,在入口点模块中导入工具模块,确保 agent 创建前已完成注册:

from . import tools  # noqa: F401

应用创建 BubAgent 时会获取已注册工具的快照。添加应用工具会说明注册、延迟加载和代码模式。

可编辑安装允许你直接修改 Python 源码,无需重新构建包。安装目标必须是运行 Bub 的同一个环境。

使用 uv 项目时,在插件目录运行:

uv sync
uv run bub hooks

如果安装到已有且已激活的应用环境,使用 uv pip install -e .,然后在该环境中运行 bub hooks。

bub hooks 可以确认注册结果。实际运行一次 hook 要处理的任务,再检查优先级和返回值。Bub 先注册内置 hooks,再注册入口点插件。同等优先级通常按注册顺序的逆序调用;tryfirst 和 trylast 会影响顺序。调用规则说明了哪个实现先运行。

如果插件没有出现,检查入口点组名、当前环境,以及启动日志中的导入错误。修改包元数据后,需要重新安装包。

发布前,构建 wheel 并安装到独立环境,确认入口点能加载,并用一个实际任务检查 hook。如果要同时发布 skills 或多个插件,参见打包 Bub 应用。