FaustBot 插件开发指南¶
本文档介绍如何开发 FaustBot 插件,包括插件可以做什么、技术栈选择、设计原则和发布流程。
目录¶
插件能做什么¶
FaustBot 插件可以在以下层面扩展和修改系统:
1. Agent 行为¶
| 能力 | 说明 |
|---|---|
| 添加工具 | 为 Agent 注册新的可调用工具(如搜索、API 调用) |
| 注入 Prompt | 在 Agent 系统提示中注入插件专属指令 |
| 拦截消息 | 在用户消息到达 Agent 前进行修改或过滤 |
| 拦截工具调用 | 在工具调用前后修改参数或结果 |
| 抑制事件 | 阻止特定 Agent 事件发送到前端 |
2. 记忆系统¶
| 能力 | 说明 |
|---|---|
| 拦截记忆读取 | 重写查询、重排结果 |
| 拦截记忆写入 | 修改写入内容或元数据 |
| 写入 VFS | 将数据写入虚拟文件系统供 Agent 检索 |
3. 触发器系统¶
| 能力 | 说明 |
|---|---|
| 创建触发器 | 生成事件触发器让 Agent 自动响应 |
| 过滤触发器 | 在触发器追加或触发时进行过滤 |
4. 前端界面¶
| 能力 | 说明 |
|---|---|
| 注册 UI 小组件 | 在主界面添加自定义小组件(徽章、面板等) |
| 注入前端脚本 | 加载自定义 JS/CSS 修改前端行为 |
| 接入配置中心保存 | 面板草稿交给配置中心右上角的「保存 / 应用 / 重新加载」,不要自建保存按钮 |
| 前后端通信 | 通过 communicate 接口与后端交互 |
5. 定时任务¶
| 能力 | 说明 |
|---|---|
| 定时执行 | 基于 interval 或 cron 定期执行回调 |
| 心跳钩子 | 每约 10 秒接收一次心跳通知 |
6. 配置与数据¶
| 能力 | 说明 |
|---|---|
| 注册配置项 | 在配置中心添加插件专属配置 |
| 持久化存储 | 使用 data/ 目录或 VFS 存储数据 |
| 读写 Agent 文件 | 通过 VFS 读写 Agent 的 COREMEMORY.md 等文件 |
技术栈¶
后端(Python)¶
| 组件 | 技术 | 说明 |
|---|---|---|
| 插件框架 | pluggy | Hook 注册与调度 |
| 异步运行时 | asyncio | 异步任务、定时器 |
| HTTP 客户端 | aiohttp / requests | API 调用、数据拉取 |
| 数据存储 | SQLite / JSON | 本地数据持久化 |
| Agent 集成 | LangChain | 工具定义(@tool 装饰器) |
| 日志 | faust_backend.logger | 统一日志接口 |
前端(JavaScript)¶
| 组件 | 技术 | 说明 |
|---|---|---|
| 模块系统 | ES Module | import/export |
| UI 框架 | 原生 DOM API | 无框架依赖 |
| 通信 | window.api / window.faustAppUI | IPC + HTTP |
| 样式 | CSS | 自定义样式表 |
依赖管理¶
- 后端依赖:通过
register_pip_deps()声明,加载时自动安装 - 前端依赖:无外部依赖,使用原生 API
VFS 优先原则¶
核心规则¶
尽可能多使用 VFS 虚拟文件系统,而不是徒增工具。
什么是 VFS¶
VFS(Virtual File System)是 FaustBot 的虚拟文件系统,使用 faustbot:// 协议访问。插件可以通过 VFS 向 Agent 暴露数据,而无需注册额外工具。
VFS 路径约定¶
faustbot://plugins/{plugin-id}/ # 插件主目录
faustbot://plugins/{plugin-id}/index.md # 插件索引文档
faustbot://plugins/{plugin-id}/data.json # 插件数据文件
VFS vs 工具¶
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| Agent 需要读取插件数据 | VFS | Agent 已有 read 工具,无需新增 |
| Agent 需要搜索插件内容 | VFS | Agent 已有 search 工具,支持 VFS 范围 |
| Agent 需要执行操作 | 工具 | 需要自定义逻辑,无法通过文件读取实现 |
| 前端需要获取数据 | communicate | 前端专用接口 |
| 定时更新数据 | VFS + 心跳 | 定时写入 VFS,Agent 按需读取 |
VFS 使用示例¶
# 写入插件文档(Agent 可通过 read("faustbot://plugins/my-plugin/index.md") 读取)
ctx.vfs_write("/plugins/my-plugin/index.md", "# My Plugin\n\n功能说明...")
# 写入动态数据
ctx.vfs_write("/plugins/my-plugin/data.json", json.dumps({"items": [...]}))
# 写入符号链接(每次读取时动态生成)
ctx.vfs_write_symbolic(
"/plugins/my-plugin/dynamic.md",
lambda path: f"# 动态数据\n\n更新时间: {time.time()}"
)
# Agent 读取时自动支持
# Agent: read("faustbot://plugins/my-plugin/index.md")
# Agent: search("关键词", scopes=["/plugins/my-plugin/"])
为什么不用工具¶
- 工具名冲突:插件工具名与内置工具冲突时,插件工具会被跳过
- Token 消耗:工具定义会占用 Agent 上下文窗口
- 复杂度:VFS 数据自动支持搜索,无需额外实现
- 一致性:所有插件数据统一通过 VFS 暴露,Agent 无需学习新工具
插件类型与模板¶
新风格插件(推荐)¶
继承 FaustPlugin 基类,使用 pluggy hook:
from faust_backend.plugin_system import FaustPlugin, PluginContext, hookimpl
class Plugin(FaustPlugin):
def startup(self, ctx: PluginContext) -> None:
ctx.vfs_write("/plugins/my-plugin.md", "# My Plugin")
@hookimpl
def heartbeat(self, ctx: PluginContext) -> None:
# 定期更新 VFS 数据
pass
def get_plugin():
return Plugin()
旧风格插件(兼容)¶
使用 on_load/on_unload,无 pluggy 集成:
from faust_backend.plugin_system import PluginManifest, PluginContext
class Plugin:
manifest = PluginManifest(plugin_id="my-plugin", name="My Plugin")
def on_load(self, ctx: PluginContext) -> None: pass
def on_unload(self, ctx: PluginContext) -> None: pass
def get_plugin():
return Plugin()
选择建议¶
| 场景 | 推荐风格 |
|---|---|
| 新开发插件 | 新风格(FaustPlugin) |
| 需要 pluggy hook | 新风格(FaustPlugin) |
| 兼容旧系统 | 旧风格 |
| 简单工具提供 | 旧风格 |
Plugin Market¶
概述¶
Plugin Market 是 FaustBot 的插件分发平台,由独立仓库 FaustBotPluginMarket 维护,支持从在线市场安装/更新、打包和分享插件。
市场地址¶
- 索引地址:https://raw.githubusercontent.com/liwusen/FaustBotPluginMarket/main/plugins.json
- GitHub 仓库:https://github.com/liwusen/FaustBotPluginMarket
- 市场页面:GitHub Pages(见仓库 README)
安装/更新插件¶
通过 deeplink(市场页面"安装"按钮):
faustbot://syncPlugin?id=my-plugin
若插件已存在会直接覆盖更新(安装前有一次安全确认弹窗)。
通过 API:
# 从市场安装/更新(存在即覆盖)
curl -X POST http://localhost:13900/faust/admin/plugin-market/sync \
-H "Content-Type: application/json" \
-d '{"plugin_id": "my-plugin"}'
# 检查已安装插件是否有更新
curl http://localhost:13900/faust/admin/plugin-market/check-updates
# 从本地 ZIP 安装
curl -X POST http://localhost:13900/faust/admin/plugins/install-zip \
-H "Content-Type: application/json" \
-d '{"zip_path": "D:/path/my-plugin.zip"}'
# 打包插件为 ZIP
curl -X POST http://localhost:13900/faust/admin/plugins/package-zip \
-H "Content-Type: application/json" \
-d '{"plugin_id": "my-plugin"}'
发布到 Market¶
发布流程完全由 issue 驱动,无需提交 PR:
- 将插件打包为 zip(顶层为
<plugin_id>/目录,内含plugin.json),上传到任意 https 直链(如你自己仓库的 Release) - 在 FaustBotPluginMarket 用 "Submit Plugin" issue 模板提交插件元数据与 zip 链接
- 维护者审核后为 issue 添加
approved标签 - GitHub Action 自动校验、重打包并发布到市场仓库自己的 Release,同时更新
plugins.json索引 - 更新插件时提交新 issue 并提升版本号即可
市场索引格式¶
{
"updated_at": "2026-01-01T00:00:00Z",
"plugins": [
{
"id": "my-plugin",
"name": "My Plugin",
"description": "插件描述",
"author": "作者",
"version": "1.0.0",
"download_url": "https://github.com/liwusen/FaustBotPluginMarket/releases/download/plugin-my-plugin-v1.0.0/my-plugin.zip",
"homepage": "https://...",
"tags": ["utility", "ai"],
"source_issue": 1,
"published_at": "2026-01-01T00:00:00Z"
}
]
}
最佳实践¶
架构设计¶
- VFS 优先:数据暴露优先使用 VFS,而非注册工具
- 单一职责:每个插件专注一个功能
- 配置驱动:通过配置项控制行为,避免硬编码
数据存储¶
- 小数据:使用
data/目录存储 SQLite 或 JSON - Agent 可读数据:写入 VFS(
/plugins/{id}/) - 动态数据:使用
vfs_write_symbolic动态生成
前端集成¶
- 小组件:使用
registerWidget注册 UI 小组件(managed缺省为true,定位/显隐/缩放由小组件管理器统一处理,无需自写 rAF 布局循环;详见 plugin-api-reference.md) - 配置中心面板:面板上的草稿用
window.pluginUI.registerPersistence({ plugin, save })交给配置中心右上角的「保存 / 应用 / 重新加载」,并用setDirty()报告未保存状态;不要在面板里再放一个独立的保存按钮(详见 plugin-api-reference.md 的「配置中心统一保存」) - 通信:通过
communicate_handler处理前端请求 - 样式:使用独立 CSS 文件,避免全局样式污染
安全性¶
- 输入验证:验证所有外部输入
- 错误处理:捕获异常,避免崩溃
- 权限最小化:只请求必要的权限
性能¶
- 异步操作:使用
asyncio处理 I/O 密集任务 - 节流心跳:在
heartbeat中避免频繁操作 - 缓存数据:避免重复计算或拉取
相关文档¶
- 插件 API Reference - 完整的 Hook 和 API 参考
- Agent 基础 - 理解 Agent 和工具系统
- 配置说明 - 配置中心使用指南