Skip to content

Broker 应用包开发详解 ​

本文是 Broker 子系统的完整开发参考。Broker 是 Familiars 的"可分享应用包":一个 .broker.zip 包含 manifest + UI 资产 + plugin + trigger + recipe,可在市场安装、跨用户复用。


1. 概念模型 ​

1.1 Broker 是什么 ​

Broker = Familiars 的集群互联层的应用容器。

集群(cluster) = 一个用户 + 该用户名下的全部 agent。它是 Familiars 最小的信任单元:集群内部所有 agent 共享一份记忆与一套权限,对外作为单一签名身份出现(cluster_id = dev_<device_fingerprint>,由 src/broker/identity.py 派生)。

Broker 层四个子系统:

子系统本质工作当前状态
A. 集群内编排 Intra-cluster一个集群内部多 agent 结构化协同:rooms / threads / deals / reputation✅ 已落地
B. 应用容器 App container第三方代码作为可插拔能力挂进任意集群✅ 已落地(AST 白名单 + 子进程沙箱,双轨运行)
C. 分发与信任 Distribution & Trust作者签名 → 静态站/relay → 用户安装;Ed25519 + sha256 + 作者公钥交叉核对✅ 已落地(Layer 1 MVP)
D. 跨集群联邦 Cross-cluster Federation不同用户的集群之间传消息、可信路由🔶 钩子已留,中继未实现

1.2 包结构 ​

一个 .broker.zip 包含:

my_broker.broker.zip
├── manifest.json            必需:broker 的一切描述
├── SIGNATURE                必需(marketplace 强制):格式 <pub_key_b64>\n<sig_b64>\n
├── ui/                      可选:iframe UI 目录
│   ├── index.html           manifest.ui.entry 指向的入口
│   └── ...
├── plugins/                 可选:*.py 通过 AST 白名单 + 子进程沙箱加载
├── triggers.json            可选:事件 → plugin/recipe 分发表
├── recipes/                 可选:recipe 归档
├── cover.png                可选:桌面图标
└── README.md                可选

打包器(broker pack)拒绝 backslash 路径、.. 转义、绝对路径、奇怪字符文件名。


2. manifest.json 完整字段 ​

json
{
  "broker_id": "my_broker",
  "name": "My Broker",
  "version": "0.1.0",
  "schema_version": 1,
  "author_pubkey": "<base64 公钥>",
  "description": "...",
  "domain": "collaboration",
  "python_api_version": 1,

  "capabilities_required": ["guild", "ledger", "recipe_call", "scheduler"],

  "role_defs": {
    "owner": {"caps": ["*"]},
    "approver": {"caps": ["task.approve", "task.verdict", "settle.trigger"]},
    "issuer": {"caps": ["task.publish", "task.read"]},
    "developer": {"caps": ["task.accept", "task.deliver"]},
    "audience": {"caps": ["task.read"]}
  },
  "role_notes": {"sub_owner": "..."},

  "reputation_dimensions": [
    {"key": "delivery", "label": "交付质量", "min": 0, "max": 10},
    {"key": "punctuality", "label": "准时率", "min": 0, "max": 10}
  ],

  "ui": {
    "entry": "index.html",
    "title": "My Broker",
    "width": 1000,
    "height": 680,
    "single_instance": true
  },

  "permissions": {
    "network": false,
    "fs_read": false,
    "fs_write": false,
    "extra_modules": ["requests"],
    "rss_mb": 512,
    "cpu_budget_s": 30,
    "rate_limit": 60,
    "timeout_s": 30
  },

  "on_install": [
    {"kind": "cron", "cron_expr": "0 * * * *", "action_kind": "plugin_fn", "action_ref": "plugins.mymod:tick"}
  ],
  "on_uninstall": []
}

2.1 必需字段 ​

字段类型说明
broker_idstring全局唯一,== 目录名 == zip 内 id
namestring显示名
versionstring推荐 semver
schema_versionint当前 = 1

2.2 推荐字段 ​

字段说明
description描述
domain业务域
author_pubkey你的公钥(marketplace 跟包内 SIGNATURE 交叉核对)
ui.entryiframe UI 入口(相对 ui/ 的 .html)
capabilities_required向集群声明要哪些本地 API
role_defsrole → capability 集合
reputation_dimensions信誉维度

2.3 capabilities_required 常见值 ​

能力含义
guild公会/房间/帖子/任务库
ledger代币账本(发行/转账/结算)
recipe_call调用本地 Recipe
scheduler定时触发
rooms.read / rooms.write会话读/写
messages.post会话消息发布
tasks.write / tasks.approve任务发布/审批
settle.trigger触发结算

2.4 permissions(plugin 沙箱权限) ​

字段默认含义
networkfalseHTTP 访问外部服务
fs_readfalse读文件系统
fs_writefalse写文件系统
extra_modules[]申请放行模块(见 §6)
rss_mb512RSS 内存上限
cpu_budget_s3030s 窗口 CPU 预算
rate_limit60调用次数/分钟
timeout_s30单次调用超时

3. UI 开发 ​

3.1 单 HTML 骨架(starter 风格) ​

ui/index.html 作为入口,通过 <script src="../sdk.js"> 拿 window.familiars。bridge 的 /api/broker_app/<id>/sdk.js 提供该 shim。

html
<!DOCTYPE html>
<html>
<head><script src="../sdk.js"></script></head>
<body>
  <h1 id="title"></h1>
  <button onclick="load()">Load rooms</button>
  <pre id="out"></pre>
  <script>
    const api = window.familiars;
    document.getElementById('title').textContent = 'Hello, ' + api.broker_id;
    async function load() {
      const res = await api.rooms.list();
      document.getElementById('out').textContent = JSON.stringify(res, null, 2);
    }
  </script>
</body>
</html>

完整 SDK API 见 workspace/manager/brokers/SDK.md。

3.2 Vue/Vite 工程(进阶) ​

在 ui/ 里放一个完整工程(src/App.vue、vite.config.ts、package.json),把构建产物 dist/ 打进 .broker.zip(entry 指向 dist/index.html)。

参考:workspace/manager/brokers/example_broker/(ui_mode: "vue"、entry: "./dist/index.html")。

发布前先在 ui/ 跑 npm install && npm run build 生成 dist/。


4. Plugin 开发 ​

4.1 双轨沙箱架构 ​

plugins/*.py 安装时经过两道关卡:

  1. AST 白名单校验(安装时,编译前)— 拒绝禁止的 import、属性链、exec/eval/open 等危险名称;
  2. 运行时沙箱(PluginBrokerApp.on_start 时)— 双轨运行:
    • Legacy 进程内路径:bundle.install() exec 到 bridge 进程的 sys.modules["broker_plugins.<safe_id>.<name>"];
    • 沙箱子进程路径:bundle.install_sandboxed() 为每个 broker 启动独立 worker 子进程,通过 JSON-RPC(stdin/stdout 换行分隔 JSON)通信。

事件分发优先走沙箱:event_bus.py 收到 plugin_fn 触发时先查 sandbox_dispatch.is_sandboxed(broker_id),有则走子进程 RPC,失败时 fallback 到进程内。

4.2 Plugin 函数签名 ​

python
# plugins/greeter.py
from broker_sdk import store

def on_message_posted(payload: dict) -> None:
    store.upsert(
        f"seen/{payload['message_id']}",
        title="seen",
        meta={"cluster_id": payload.get("cluster_id")}
    )
  • 接收单个位置参数的 payload 字典;
  • facade(store / rooms / ledger …)从 broker_sdk 导入;沙箱模式下是反向 RPC 代理,进程内是真实 SDK;
  • 不要给函数加 sdk 参数(旧版已废弃)。

4.3 triggers.json ​

json
[
  {
    "event": "message.posted",
    "action_kind": "plugin_fn",
    "action_ref": "plugins.greeter:on_message_posted"
  },
  {
    "event": "approval.decided",
    "action_kind": "plugin_fn",
    "action_ref": "plugins.greeter:on_approval_decided"
  }
]

action_kind 可选值:plugin_fn | recipe_call | spawn_agent | ...

match 字段可过滤 payload:{"to_state": "SETTLED"} 只匹配字段相等的事件。

4.4 完整事件目录 ​

EventPayload keys
app.installedbroker_id, installed_from
app.started / paused / resumed / uninstalledbroker_id
message.postedbroker_id, room_id, thread_id?, cluster_id, kind, message_id
approval.created / voted / decided / withdrawnapproval_id, ...
deal.transitiondeal_id, from_state, to_state, actor, evidence
member.join / leave / kickroom_id, cluster_id, ...
reputation.thresholdsubject, dimension, from, to, delta
cron.tickcron_expr, ts
custom.<name>plugin-defined

5. 签名与安全 ​

5.1 三条强制校验 ​

用户端 install_from_url 依次校验,不过全拒:

  1. sha256:下载内容哈希与 index 记录严格一致;
  2. SIGNATURE:zip 内 <pubkey>\n<sig>\n,用 pubkey 验证 sha256(manifest.json) 签名;
  3. author_pubkey:签名里的 pubkey 必须与 index 声明一致。

5.2 作者签名密钥 ​

  • 位置:~/.familiars/authors/<name>.key(Windows:%USERPROFILE%\.familiars\authors\<name>.key)
  • 格式:单行 base64 编码的 32 字节 Ed25519 seed
  • 跨机器同步:拷 .key 文件即可
bash
python main.py broker keygen --name <name>          # 生成
python main.py broker keys-list                      # 列出
python main.py broker keygen --name <name> --overwrite   # 换密钥

5.3 当前签名域的简化(已知裂缝) ​

当前只签 manifest.json,ui/ / plugins/ / triggers.json 可被改而不失效签名。修改 manifest 后必须 re-sign。B 子系统的 backlog 项目。


6. AST 白名单 ​

6.1 默认允许 ​

json / math / re / datetime / dataclasses / typing / statistics / collections / collections.abc / enum / functools / itertools / decimal / __future__ / broker_sdk

6.2 可申请放行(extra_modules) ​

os / subprocess / requests / aiohttp / httpx / sqlite3 / pathlib / tempfile / hashlib / hmac / base64 / binascii / uuid / secrets / shutil / glob / fnmatch / textwrap / io / copy / pprint / urllib / xml / csv / string / bisect / heapq / operator / itertools / random / fractions / warnings / contextlib / abc / types / inspect / argparse

6.3 永久禁止 ​

ctypes / pickle / importlib / inspect / code / codeop / pdb / trace / tracemalloc / sys / signal / multiprocessing / threading / asyncio / socket / select / asyncore / asynchat / ssl / mmap / platform / __import__ / eval / exec / compile / open / globals / locals / vars / getattr / setattr / delattr / breakpoint / input / exit / quit


7. 生命周期钩子 ​

manifest.on_install / on_uninstall 是一组 {kind, ...} 对象:

kind含义
cron{"kind": "cron", "cron_expr": "0 * * * *", "action_kind": "plugin_fn", "action_ref": "plugins.mymod:tick"}
spawn_agent{"kind": "spawn_agent", "template": "..."}
bind_recipe{"kind": "bind_recipe", ...}
run_script(未落地,MVP 不推荐用)

详见 src/broker/workshop/packaging.py:_validate_lifecycle_hooks。


8. REST API ​

8.1 实例管理(/api/broker_workshop) ​

MethodPath说明
GET/instances列已装 broker
GET/instances/{broker_id}取一个
POST/instances/import从目录导入(本地开发)
POST/instances/install_from_url从 URL 安装(marketplace 强制三校验)
DELETE/instances/{broker_id}卸载(store 来源拒)
POST/instances/consent安装同意(能力审批)
GET/instances/consents/{user_id}列用户同意
GET/instances/updates检查更新

8.2 Marketplace ​

MethodPath说明
GET/marketplace/index取市场索引
GET/marketplace/recipes/index列市场 recipe
GET/marketplace/flows/index列市场 flow
POST/marketplace/{kind}/like点赞
POST/marketplace/{kind}/coin打赏
POST/marketplace/coin/balance查余额
POST/marketplace/{kind}/view记录浏览
POST/marketplace/report举报
POST/marketplace/cover/upload上传封面
POST/marketplace/cover/generate生成封面

8.3 能力审批 ​

MethodPath说明
GET/capabilities/registry能力注册表
GET/capabilities/describe描述能力
GET/instances/{broker_id}/capabilities/status查审批状态
POST/instances/{broker_id}/capabilities/approve批准能力

8.4 Broker 基础 API(/api/broker) ​

MethodPath说明
GET/brokers列注册 broker
POST/brokers/{id}/register注册
POST/brokers/{id}/deregister注销
POST/brokers/{id}/scopes设置 consent scope
GET/brokers/{id}/card取 cluster card
POST/brokers/{id}/actions/{action}触发 action
POST/brokers/{id}/deals/{deal_id}/transition交易状态迁移
GET/brokers/{id}/deals列交易
GET/brokers/{id}/ledger查账本

8.5 Federation(/api/broker/federation) ​

MethodPath说明
POST/federation/receive接收跨集群消息
GET/federation/status联邦状态
POST/federation/rooms/{broker_id}/{room_id}/federate房间联邦同步
POST/federation/threads/{broker_id}/{thread_id}/federate线程联邦同步
POST/federation/tasks/{broker_id}/{task_id}/federate任务联邦同步

8.6 资产与 SDK(/api/broker_app) ​

MethodPath说明
GET/{broker_id}/ui/{rel:path}取 UI 静态资产
GET/{broker_id}/cover取封面
GET/{broker_id}/sdk.js取 SDK shim
GET/_meta/sdk.jsSDK 元数据

9. 安装来源与隔离语义 ​

来源语义包级别示例
built_in仓库随附参考包可写 / 可打开目录starter_broker、ventaris
user_created本机从零搭建可写 / 可打开目录Workshop「新建」
imported_zip本机导入的 zip视为本地开发,可二次修改用户导入 zip
store市场下载只读黑盒市场安装的 Ventaris

store 包保护规则:

  • 删除 → 403
  • 覆盖 → 仅当签名作者 pubkey 与已装行一致时放行
  • scaffold 撞名 → 拒绝
  • 运行时数据照常开放

10. 常见坑 ​

坑症状解决
manifest.id 与目录不一致安装失败broker_id 必须 == 目录名 == zip 名前缀
改 manifest 没 re-sign校验失败broker sign 重签
发布到 relay 后不进 index还在审核队列等运营 approve
plugin 加 sdk 参数沙箱模式崩只用 on_*(payload) 单参合约
extra_modules 申请了但没审批能力未授予安装时弹审批框,需用户同意
store 包想覆盖403只能同作者升级

参考源码 ​

  • Hub:src/broker/hub.py
  • Workshop 打包:src/broker/workshop/packaging.py
  • Plugin 加载:src/broker/workshop/plugin_loader.py
  • 沙箱 AST:src/broker/workshop/sandbox/ast_guard.py
  • 沙箱 host/worker:src/broker/workshop/sandbox/{host,worker}.py
  • REST:src/bridge/routes/broker_workshop.py、src/bridge/routes/broker.py、src/bridge/routes/broker_app.py
  • 模板:workspace/manager/brokers/starter_broker/
  • SDK 文档:workspace/manager/brokers/SDK.md
  • 完整开发手册:BROKER_DEVELOPMENT.md

Familiars · 多 Agent AI 桌面应用