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

在 AI Agent 领域,安全审批一直是个两难问题:全自动执行有风险,全手动审批太繁琐。Agent Buddy Bridge 项目给出了一种硬件级别的解决方案——用 M5StickC Plus 开发板的物理按钮来做危险命令的"硬件开关"。
项目动机
当你赋予 AI Agent shell 执行权限后,攻击面瞬间扩大。rm -rf /data、DROP 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 (系统) | 8765 | BLE Central + HTTP Server |
| Approval Relay | Hermes venv Python | 8766 | 调用 resolve_gateway_approval() |
为什么需要两个 Python 环境?
bleak需要系统 Python 的 pyobjc (CoreBluetooth) 支持resolve_gateway_approval()需要 Hermes venv 才能导入 tools.approval
两个进程通过 HTTP 通信(localhost),互相独立,任何一个崩溃不影响另一个。
依赖的 Hermes 接口 (v0.12.0)
| # | 能力 | 状态 | PR |
|---|---|---|---|
| 1 | pre_approval_request hook | ✅ 已合并 | #16776 |
| 2 | post_approval_response hook | ✅ 已合并 | #16776 |
| 3 | platform_registry 插件注册 | ✅ 内置 | — |
| 4 | resolve_gateway_approval() | ✅ 一直可用 | — |
| 5 | Session 清理时唤醒阻塞审批 | ✅ 已合并 | #18171 |
| 6 | pre_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 优化)
项目链接
- GitHub:harryfan1985/agent-buddy-bridge
- Hermes Agent:NousResearch/hermes-agent
- M5StickC Plus 开发板:M5Stack 官方
本文基于 Hermes Agent v0.12.0 和 agent-buddy-bridge v1.0.0。检查日期:2026-05-01。