构建你的第一个插件
本教程引导你编写一个最小 Bub 插件,用 echo 响应覆写 model 阶段,将其安装到活动环境,并确认框架已识别。
该插件无需模型凭据,可同时作为冒烟测试和真实插件的起点模板。
你需要准备:
- 已在
uv管理的环境中 安装 Bub - 在 workspace 之外有一个空闲目录用于 scaffold 插件包
1. 搭建包结构
Section titled “1. 搭建包结构”创建包结构:
mkdir bub-echo-plugin
cd bub-echo-plugin
mkdir -p src/bub_echo_plugin
touch src/bub_echo_plugin/__init__.py
创建 pyproject.toml。[project.entry-points."bub"] 段是让插件可被发现的关键:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "bub-echo-plugin"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["bub>=0.1"]
[project.entry-points."bub"]
echo = "bub_echo_plugin.plugin:echo_plugin"
[tool.hatch.build.targets.wheel]
packages = ["src/bub_echo_plugin"]
2. 实现插件
Section titled “2. 实现插件”创建 src/bub_echo_plugin/plugin.py。插件是任何方法被 @hookimpl 装饰的对象:
from __future__ import annotations
from bub import hookimpl
class EchoPlugin:
@hookimpl
def build_prompt(self, message, session_id, state):
if hasattr(message, "content"):
return str(message.content)
if isinstance(message, dict):
return str(message.get("content", ""))
return str(message)
@hookimpl
def run_model(self, prompt, session_id, state):
text = prompt if isinstance(prompt, str) else str(prompt)
return f"[echo:{session_id}] {text}"
echo_plugin = EchoPlugin()
build_prompt 是 firstresult hook —— 第一个非 None 的返回值胜出。run_model 同样是 firstresult,所以本实现完全覆写了内置 agent。
3. 创建插件环境
Section titled “3. 创建插件环境”从插件目录把插件包及其依赖同步到该插件项目的 .venv:
uv sync
uv sync 默认以 editable 方式安装当前插件包。下面的 uv run bub ... 命令会在同一个包含插件 entry point 的环境中运行 Bub。
如果你想把插件安装到已有 Bub checkout 的虚拟环境中,请先激活目标虚拟环境,再运行 uv pip install -e .。
4. 验证 Bub 已加载
Section titled “4. 验证 Bub 已加载”请求 Bub 输出 hook 报告:
uv run bub hooks
你应当在 build_prompt 与 run_model hook 项下看到 echo 与 builtin 并列。
接着运行一次单次 turn:
uv run bub run "hello from plugin tutorial"
outbound 消息应当包含:
[echo:cli:local] hello from plugin tutorial
如果响应来自真实模型,说明插件未加载——请在插件项目中重跑 uv sync,或确认插件已安装到运行 bub 的虚拟环境中,然后重新检查 bub hooks。
- Build plugins — 包结构、生命周期与发现细节。
- Hooks 参考 — 每条 hookspec 及其签名。
- Distribution — 将插件与 skill 一起打包发布。