Agent Buddy Bridge: M5StickC Plus 物理按钮审批系统

May 1, 2026

Agent Buddy Bridge: M5StickC Plus 物理按钮审批系统

在 AI Agent 领域,安全审批一直是个两难问题:全自动执行有风险,全手动审批太繁琐。Agent Buddy Bridge 项目给出了一种硬件级别的解决方案——用 M5StickC Plus 开发板的物理按钮来做危险命令的"硬件开关"。

项目动机

当你赋予 AI Agent shell 执行权限后,攻击面瞬间扩大。rm -rf /dataDROP TABLE users——这些命令只需要一瞬间的疏忽就可能造成灾难性后果。

现有的审批方案(Telegram 的 /approve、终端交互确认)都有共同的弱点:依赖同一个设备的 UI 交互。如果你离开电脑,Agent 就会一直阻塞等待,或者超时自动拒绝。物理按钮提供了一个独立的、硬隔离的审批通道——你可以在任何地方按下按钮,Agent 立即解除阻塞。

技术架构

整体架构

M5StickC Plus (BLE Peripheral)
    ↕ BLE NUS (Nordic UART Service)
BLECentral (bleak / macOS CoreBluetooth)
    ↓ JSON over BLE
HTTPServer (:8765)
    ↑ POST /buddy/state (Hermes → Bridge, 来自 pre_approval_request hook)
    ↓ POST /internal/approve (Bridge → Hermes, 按钮按下时)
    ↓
Approval Relay (:8766) → resolve_gateway_approval(session_key, choice)
    ↑
    Hermes tools/approval.py

审批流程

危险命令检测 (如 rm -rf /data)
    │
    ▼
tools/approval.py: prompt_dangerous_approval()
    │
    ├─→ 🔔 pre_approval_request hook
    │       → Plugin 收到 {command, session_key, surface="gateway"}
    │       → BuddyPlatformAdapter 推送到 Bridge (:8765)
    │       → BLE → M5StickC 屏幕显示审批提示
    │
    ├─→ 📱 Telegram 通知 (同步触发)
    │       "⚠️ Dangerous command: rm -rf /data
    │        Reply /approve, /always, or /cancel"
    │
    └─→ ⏸️ Agent 线程阻塞 (threading.Event.wait)
            │
    ┌───────┴───────┐
    ▼               ▼
 M5StickC 按钮      Telegram /approve
 (BLE 通知)         (slash command)
    │               │
    ▼               ▼
 Approval Relay     gateway._handle_approve_command()
    │               │
    └───────┬───────┘
            ▼
 resolve_gateway_approval(session_key, "once")
            │
            ▼
    event.set() → Agent 解除阻塞
            │
            ▼
    🔔 post_approval_response hook
        → 清理 M5StickC 屏幕
        → 命令继续执行

双通道审批,先到先得。用户可以在电脑前用 Telegram 审批,也可以在离开电脑时按 M5StickC 按钮。两者同时到达时,先到先得,另一个幂等返回 0。

核心技术要点

1. pre_approval_request hook — 审批请求的推送机制

这是 Hermes v0.12.0 引入的关键能力(PR #16776)。当 Agent 执行到危险命令时,approval.py 会触发 pre_approval_request hook,回调携带:

  • command — 待审批的命令文本
  • session_key — 当前会话标识(用于后续审批回传)
  • pattern_key — 命令模式匹配键
  • surface — 触发来源("gateway" / "cli")

这个 hook 解决了之前方案中最大的断点:M5StickC 如何知道 Hermes 何时在等待审批?现在 hook 会主动推送,不需要轮询。

2. post_approval_response hook — 审批结果的清理机制

审批完成后(不管是通过按钮还是 Telegram),hook 回调携带 choice 字段("once" / "always" / "deny" / "timeout"),Plugin 可以据此清理 M5StickC 屏幕、记录审计日志等。

3. platform_registry — 插件化平台适配器

Hermes 内置的 platform_registry 允许插件注册自定义平台适配器(参考 IRC/Teams 插件的实现)。BuddyPlatformAdapter 通过这个机制被注册为 Hermes 的一个"平台",而不需要修改 Hermes 核心代码。

4. Approval Relay — HTTP 到 Python 函数的桥接

按钮按下事件通过 BLE → HTTP Server (:8765) → Approval Relay (:8766) 到达 Hermes。resolve_gateway_approval() 是 Python 函数而非 HTTP 端点,所以需要一个 Relay 进程来做桥接。Relay 使用 Hermes venv 的 Python(因为它需要 from tools.approval import resolve_gateway_approval)。

双进程设计

进程Python端口职责
BuddyBridge/usr/bin/python3 (系统)8765BLE Central + HTTP Server
Approval RelayHermes venv Python8766调用 resolve_gateway_approval()

为什么需要两个 Python 环境?

  • bleak 需要系统 Python 的 pyobjc (CoreBluetooth) 支持
  • resolve_gateway_approval() 需要 Hermes venv 才能导入 tools.approval

两个进程通过 HTTP 通信(localhost),互相独立,任何一个崩溃不影响另一个。

依赖的 Hermes 接口 (v0.12.0)

#能力状态PR
1pre_approval_request hook✅ 已合并#16776
2post_approval_response hook✅ 已合并#16776
3platform_registry 插件注册✅ 内置
4resolve_gateway_approval()✅ 一直可用
5Session 清理时唤醒阻塞审批✅ 已合并#18171
6pre_tool_call approve 指令❌ 未合并#11816

PR #11816 是唯一的未合并项,它允许插件白名单命令自动放行(不触发审批)。这不影响物理按钮审批的核心链路——hook + Relay 路径独立处理按钮审批。

安装和使用

前置依赖

  • macOS(CoreBluetooth 用于 BLE)
  • 系统 Python 3.9+ 带 pyobjc
  • Hermes Agent v0.12.0+ 安装在 ~/.hermes/
  • M5StickC Plus,烧录了 Claude Desktop Buddy 固件(BLE 广播名为 Claude-XXXX)
  • Python 包:bleak, aiohttp

安装步骤

# 1. 克隆项目
cd ~/code
git clone https://github.com/harryfan1985/agent-buddy-bridge.git
cd agent-buddy-bridge

# 2. 安装依赖
/usr/bin/pip3 install bleak aiohttp

# 3. 创建插件软链接
ln -s ~/code/agent-buddy-bridge/hermes_plugin ~/.hermes/plugins/buddy-bridge

配置 Hermes

~/.hermes/config.yaml 中添加:

gateway:
  platforms:
    buddy:
      enabled: true
      extra:
        bridge_url: "http://localhost:8765"

plugins:
  enabled:
    - buddy-bridge

启动服务

终端 1 — BuddyBridge(BLE + HTTP):

cd ~/code/agent-buddy-bridge
/usr/bin/python3 -m hermes_buddy_bridge.main     --http-port 8765 --relay-url http://localhost:8766

终端 2 — Approval Relay:

cd ~/code/agent-buddy-bridge
~/.hermes/hermes-agent/venv/bin/python     -m hermes_buddy_bridge.approval_relay     --hermes-home ~/.hermes --port 8766

启动后重启 Hermes Gateway:hermes gateway restart

验证

# 健康检查
curl -s http://localhost:8765/health
curl -s http://localhost:8766/health

# BLE 设备连接状态
curl -s http://localhost:8765/buddy/status
# → {"connected": true, "device_name": "Claude-0C1E"}

# 审批路径测试(幂等,无 pending 时返回 resolved=0)
curl -s -X POST http://localhost:8765/internal/approve   -H "Content-Type: application/json"   -d '{"session_key":"test","choice":"once"}'
# → {"status": "ok", "via": "approval-relay", "resolved": 0}

项目状态和 TODO

核心审批链路已打通。目前余下工作分为三个优先级:

  • P1 — BuddyPlatformAdapter 适配 pre_approval_request hook(目前基于旧架构实现)
  • P2 — 端到端集成测试(触发真实危险命令 → M5StickC 显示 → 按钮审批 → Agent 解除阻塞)
  • P3 — 等待 PR #11816 合并(白名单命令自动放行,UX 优化)

项目链接


本文基于 Hermes Agent v0.12.0 和 agent-buddy-bridge v1.0.0。检查日期:2026-05-01。