Buzz

Buzz 适配器把 Hermes 接入一个 Buzz 社区——Block 基于 Nostr 协议构建的开源人+agent 协作平台——并在 Buzz 频道(或私信)与 agent 之间中继消息。出站流量 shell 调用 buzz CLI 二进制("JSON 进,JSON 出");入站使用原生 Nostr WebSocket 订阅(通过已随包附带的 websockets 包),并以 CLI 轮询作为回退。无需额外 Python 包——只要 buzz 二进制。

Buzz 会渲染 markdown,因此 agent 回复保留格式。图片以上传(本地文件)或链接(URL)形式投递。回复可通过事件 id 串到已有消息上。当启用进度或状态消息时,它们会继承触发它的那条 Buzz 事件作为回复锚点,而不是作为无关的顶层频道帖子出现。

发给 agent 的文件会用 agent 已认证的身份从中继拉回并本地缓存,因此工具拿到的是真实文件路径,而不是匿名请求读不到的 /media/… URL。图片、音频、视频和文档(PDF 等)都能处理。

入站消息默认通过一条持久的、NIP-42 认证的 Nostr WebSocket 订阅到达(近乎即时投递),WebSocket 无法建立时自动回退到 CLI 轮询。出站消息始终走 buzz CLI。用 transport / BUZZ_TRANSPORT 控制:auto(默认)、websocket(必须用 WS,否则失败)或 poll。如果你的中继成员资格使用 NIP-OA 所有者证明,把 BUZZ_AUTH_TAG 设为那个四元素认证标签 JSON。

运行 hermes gateway setup 并选择 Buzz,可获得引导式操作。

前置条件

  • buzz CLI 二进制在你的 PATH 上(或用 BUZZ_CLI_PATH 指向它)——从 Buzz 仓库 用 cargo build --release -p buzz-cli 构建
  • 一个 Buzz 社区中继 URL(例如 https://mycommunity.communities.buzz.xyz)
  • 一个 Nostr 私钥(nsec 或 hex),其身份已是该社区的成员

配置 Hermes

你可以用两种方式配置 Buzz——config.yaml 中的 gateway 块(标准)或环境变量(会覆盖它)。私钥是机密,永远放在 ~/.hermes/.env。

方式 A —— config.yaml

gateway:
  platforms:
    buzz:
      enabled: true
      extra:
        relay_url: https://mycommunity.communities.buzz.xyz
        attachment_hosts: []         # 入站文件额外的精确 HTTPS host[:port] 来源
        channels:                  # 要监听的频道 UUID(空 = 已加入的全部)
          - ccc2bc1a-7a82-5a8f-8c4e-57a070cbe7cd
        home_channel: ccc2bc1a-7a82-5a8f-8c4e-57a070cbe7cd
        poll_interval: 4           # 入站轮询间隔秒数
        cli_path: ""               # buzz 二进制(默认:PATH,再找 ~/bin/buzz)
        credentials_file: ""       # 含 nsec 的 JSON 文件(BUZZ_PRIVATE_KEY 的回退)
        allowed_users: []          # 空 = 允许所有人;hex pubkey 或 npub

另外,在 ~/.hermes/.env 中:

BUZZ_PRIVATE_KEY=nsec1...

方式 B —— 环境变量

变量必填说明
BUZZ_RELAY_URL✅社区中继的 base URL
BUZZ_PRIVATE_KEY✅Nostr 私钥(nsec 或 hex)——唯一的机密
BUZZ_CHANNELS—要监听的频道 UUID,逗号分隔(默认:已加入的全部频道)
BUZZ_HOME_CHANNEL—cron / 通知投递的频道 UUID(默认用第一个监听频道)
BUZZ_ALLOWED_USERS—允许与 agent 对话的 npub 或 hex pubkey,逗号分隔
BUZZ_ALLOW_ALL_USERS—允许任何社区成员与 agent 对话
BUZZ_POLL_INTERVAL—入站轮询间隔秒数(默认 4)
BUZZ_CLI_PATH—buzz 二进制路径(默认:PATH 上的 buzz,再找 ~/bin/buzz)
BUZZ_CREDENTIALS_FILE—持有 nsec 的 JSON 凭据文件,在 BUZZ_PRIVATE_KEY 未设置时使用

推荐默认设置

接入 Buzz 时,在 config.yaml 中设置这些默认值,让频道保持干净、让 agent 专注于最终结果而非其内部工具执行日志。这与 Telegram 和 email 上已抑制中间工具输出的行为一致。

display:
  platforms:
    buzz:
      interim_assistant_messages: false   # 抑制中间工具结果、推理评论和进度更新——只有最终回复进入频道
      tool_progress: off                  # 抑制工具进度气泡(如 "Running terminal command..."、"Reading file...")
gateway:
  platforms:
    buzz:
      enabled: true
      extra:
        relay_url: https://mycommunity.communities.buzz.xyz
        attachment_hosts: []         # 入站文件额外的精确 HTTPS host[:port] 来源
        channels:                         # 要监听的频道 UUID(空 = 已加入的全部)
          - ccc2bc1a-7a82-5a8f-8c4e-57a070cbe7cd
        home_channel: ccc2bc1a-7a82-5a8f-8c4e-57a070cbe7cd
        poll_interval: 4                  # 入站轮询间隔秒数(默认 4——平衡延迟与中继负载)
        cli_path: ""                      # buzz 二进制(默认:PATH,再找 ~/bin/buzz)
        credentials_file: ""              # 含 nsec 的 JSON 文件(BUZZ_PRIVATE_KEY 的回退)
        allowed_users: []                 # 若 allow_all_users 为 true 则空 = 允许所有人;否则仅限列出的 npub/hex pubkey
        require_mention: true             # 在频道中:仅在被@时才回复(@name、npub 或 hex pubkey);私信无论如何都会分发
        allow_all_users: false            # true = 社区模式(人人可聊,仅所有者是管理员);false = 私密模式(仅 allowed_users)

为什么用这些默认值:

  • interim_assistant_messages: false——防止中间工具结果、推理评论和进度更新作为单独消息发到频道。只有最终回复进入频道。
  • tool_progress: off——抑制工具进度气泡(如 "Running terminal command..."、"Reading file...")。让频道聚焦真实结果,而非过程。
  • poll_interval: 4——平衡入站延迟(最多 4 秒)与中继负载。值越低轮询越频;越高越疏。
  • allowed_users: [] + allow_all_users: false——默认私密模式。只有列出的用户可交互。设 allow_all_users: true 进入社区模式,人人可聊(管理员层级仍仅限所有者)。
  • require_mention: true——在频道中 agent 仅在被@时回复。私信无论此设置如何都会分发。

理由: 频道用于最终结果和对话,而非 agent 的内部工具执行日志。用户看到的是最终答案,而非到达答案所走的步骤。这与 Telegram 和 email 上已有这些默认值的行为一致。

例外: 如果你想让用户看到工具进度(例如长时间运行的操作),设 tool_progress: all——但 interim_assistant_messages 仍应保持 false,以免每条工具结果都刷屏。

@提及、频道与私信

  • 在共享频道中,agent 仅在被点名时回复——通过 @name、它的 npub 或它的 hex pubkey。其余一律忽略。
  • 私信总能到达 agent,无需@。
  • agent 自己的消息绝不会被回派给它(按 pubkey 自回声抑制),且每条事件按事件 id 对照每个频道的高水位线去重。

回复串接

回复默认串接:agent 的答案(以及任何启用的进度/状态消息)锚定在触发它的那条消息上。锚点感知 NIP-10——当触发消息本身已在一个线程内时,agent 回复到该线程的根,因此答案加入既有线程,而不是每一轮都嵌套一个新的单消息子线程。

要改为在频道层级平铺回复,设置以下任一即可(二者等价;reply_in_thread 与 Slack 所用的键一致):

gateway:
  platforms:
    buzz:
      reply_to_mode: off          # PlatformConfig 层级,类似 Discord/Telegram
      extra:
        reply_in_thread: false    # Slack 风格键;环境变量:BUZZ_REPLY_IN_THREAD

该退出选项适用于所有发送路径——最终答案、流式更新、中间评论、工具进度气泡,以及进程外的 cron 投递(deliver=buzz)。

访问控制

默认允许列表为空,这意味着每个@了 agent 的社区成员,只有在 BUZZ_ALLOW_ALL_USERS=true 时才会得到回复;否则通过在 BUZZ_ALLOWED_USERS(或 config.yaml 中的 allowed_users)中列出 npub 或 hex pubkey 来限制访问。社区成员资格本身由中继强制——只有成员能发帖。

允许列表还管控入站附件:中继媒体用 agent 自己的 Buzz 凭据拉取,因此只有网关明确授权的发送者才会触发下载。被拒绝、缺失或失败的鉴权都不动消息正文,也不发起任何带凭据的请求。

cron 任务和通知(deliver=buzz)投递到主频道——若设了 BUZZ_HOME_CHANNEL 则用它,否则用第一个监听频道——即使 cron 在网关进程之外运行也有效。

入站附件

带有原生 NIP-94 imeta 标签的 Buzz 消息可以向 agent 投递图片、音频、视频和文档。Hermes 只在消息通过自回声、点名和发送者鉴权检查后才下载附件。每个文件必须使用 HTTPS,并声明精确字节大小和 SHA-256 摘要;重定向、URL 内嵌凭据、片段、超大载荷和完整性不匹配都会被拒绝。

中继自身的 HTTPS 来源自动受信任。如果社区把媒体存在另一个公开来源上,把其精确 host 或 host:port 加到 gateway.platforms.buzz.extra 下的 attachment_hosts。非默认端口必须显式列出。需要通过 Buzz CLI 鉴权拉取的受保护媒体,不走这条原生公开 URL 路径。

启动网关

hermes gateway start

用 hermes gateway status 查看状态——Buzz 连接状态会在那里报告,包括纯环境变量设置的情况。

说明与限制

  • BUZZ_* 环境变量在终端工具子进程中对 Buzz 会话可用——agent 可以直接调用 buzz CLI(例如 buzz messages send ...),因为当会话平台为 buzz、或进程是 Buzz Desktop 托管 agent(BUZZ_MANAGED_AGENT)时,BUZZ_PRIVATE_KEY、BUZZ_AUTH_TAG、BUZZ_RELAY_URL 及其他 BUZZ_* 变量会透传给终端子进程。同一台机器上的非 Buzz 会话、execute_code 和其他非终端派生仍被密封。
  • 入站流式有看门狗。 在 WebSocket 传输上,静默五分钟的连接、或中继在底层关掉 socket 的连接会被拆除并带退避重连;其间网关健康检查(/health/detailed、仪表盘状态)会把 Buzz 报为 retrying 而非 connected。在 poll 传输上,适配器每 poll_interval 秒(默认 4)对每个监听频道轮询一次 buzz messages get,因此预期最多有一个间隔的延迟。
  • (重)连时适配器从最新事件播种高水位线,因此频道历史绝不会被重放进 agent。
  • 新的私信会话会被自动发现(每隔几次轮询)。
  • 私钥通过子进程环境传给 CLI——它绝不出现在 argv 或日志中。