@snarflakes

Openclaw Interaction Bridge

Bridge OpenClaw agent state directly to snarling display via HTTP API, with notification support

当前版本
v1.6.0
code-plugin社区source-linked

OpenClaw Interaction Bridge

A plugin that bridges OpenClaw agent activity to any external program! Snarling for example — a Raspberry Pi + DisplayHAT Mini companion that shows what the agent is doing and lets you approve or reject actions with physical A/B buttons and lets agents send notifications with a feedback loop for attunement!

What It Does

  • State display: Automatically sends agent state changes (processing, communicating, sleeping) to Snarling's display
  • Physical approvals: Registers a request_user_approval tool that routes yes/no decisions to Snarling's A/B buttons
  • Notifications: Registers a send_notification tool that sends alerts to the display with priority-based timeouts and full two-way feedback
  • Notification feedback: Receives callback data from Snarling (revealed, dismissed, timed out) with timing metrics, enabling notification attunement
  • Approval tracking: Counts approval lifecycle events (requested, approved, rejected, timed out, errored)

Installation

# Clone to your OpenClaw extensions directory
git clone https://github.com/snarflakes/openclaw-interaction-bridge.git \
  ~/.openclaw/extensions/openclaw-interaction-bridge

# Install dependencies
cd ~/.openclaw/extensions/openclaw-interaction-bridge
npm install

# Restart OpenClaw
openclaw gateway restart

Prerequisites

  • Snarling running on a Raspberry Pi with DisplayHAT Mini (state + approval server on port 5000)
  • OpenClaw gateway >= 2026.3.24-beta.2

Configuration

No config needed for the default Snarling setup. The plugin works out of the box.

Custom Targets

To use a custom interaction surface (Tauri app, mobile web view, etc.), edit the constants at the top of index.ts:

const SNARLING_URL = "http://localhost:5000/state";    // → your state endpoint
const CALLBACK_BASE_URL = "http://localhost:18789";    // → your callback base URL

The approval secret is set via OPENCLAW_APPROVAL_SECRET env var. If not set, a random UUID is generated on each startup. The secret must be included in the JSON body of callback requests (not query params — the gateway strips those).

No config file yet — when there are multiple adapters, a config-driven system will make sense. For now, editing the source is honest and simple.

How It Works

State Updates

The plugin hooks into OpenClaw events and POSTs state to Snarling:

OpenClaw EventSnarling StateMeaning
before_tool_callprocessingAgent is using tools
before_agent_replycommunicatingAgent is generating a response
agent_endsleepingAgent finished its turn
10s idle timeoutsleepingNo recent activity

Duplicates are suppressed — only state changes are sent.

Approval Flow

When the agent calls request_user_approval:

  1. Plugin creates a TaskFlow and sets it to waiting state
  2. POSTs approval request directly to Snarling on port 5000 (/approval/alert) — no middleman
  3. Snarling displays the request on screen with A/B button prompt
  4. User presses A (approve) or B (reject)
  5. Snarling forwards the decision to the plugin's /approval-callback HTTP route
  6. Plugin resumes the TaskFlow and enqueues a system event to wake the agent
  7. Snarling also sends a WebSocket RPC wake to bypass the gateway's requests-in-flight check

Only one approval at a time — subsequent requests are blocked until the current one is resolved (with a 30-minute stale timeout as a safety net).

Notification Flow

When the agent calls send_notification:

  1. Plugin creates a TaskFlow and sets it to waiting state
  2. POSTs notification to Snarling on port 5000 (/approval/alert) with type: "notification"
  3. Snarling displays the notification on screen with priority-based face and banner behavior
  4. User interacts: A press reveals text, B press dismisses, or low-priority auto-dismisses after timeout
  5. Snarling forwards feedback (revealed/dismissed/timed out + timing) to the plugin's /notification-callback HTTP route
  6. Plugin resumes the TaskFlow and enqueues a system event to wake the agent
  7. Snarling also sends a WebSocket RPC wake to bypass the gateway's requests-in-flight check

If TaskFlow is unavailable, the notification degrades to fire-and-forget (no feedback).

Parameters:

  • message (required) — the notification text
  • priority (optional) — "low", "normal" (default), or "high"
  • duration (optional) — seconds before auto-clear (default: 0, which means Snarling decides based on priority)

The notification payload sent to Snarling:

{
  "type": "notification",
  "message": "Stove's been on 20 min",
  "priority": "high",
  "duration": 0,
  "notification_id": "notify-1234567890-abc",
  "callback_url": "http://localhost:18789/notification-callback",
  "session_key": "agent:main:main",
  "secret": "uuid"
}

The feedback payload received from Snarling:

{
  "notification_id": "notify-1234567890-abc",
  "revealed": true,
  "time_to_reveal_sec": 42.5,
  "dismissed": false,
  "timed_out": false,
  "secret": "uuid",
  "sessionKey": "agent:main:main"
}

time_to_reveal_sec measures total time from when the notification was sent to when the user interacted with it — including any time spent queued behind other notifications.

Priority-Based Timeout Behavior

PriorityDefault TimeoutBehavior
highNone (0)Stays until user interacts — never auto-dismisses
normalNone (0)Stays until user interacts — never auto-dismisses
low300s (5 min)Auto-dismisses after timeout, sends timed_out feedback

The plugin sends duration: 0 by default, letting Snarling decide based on priority. No urgent or moderate notification should ever just disappear.

Notification Attunement

The feedback loop enables notification attunement — the agent learning when and how to reach out effectively. Each notification generates a data point: was it revealed (and how quickly), dismissed without reading, or timed out? Over time, the agent adjusts notification behavior based on what works.

See NOTIFICATION_POLICY.md for the attunement framework details.

Approval Tracker

The plugin tracks approval and notification lifecycle counts in memory:

CounterWhen it increments
requestedEvery time request_user_approval is called
approvedCallback resolved as approved
rejectedCallback resolved as rejected
timedOutStale lock cleared after 30min timeout
erroredSnarling notification POST failed

Notification stats:

CounterWhen it increments
sentEvery time send_notification is called
revealedUser pressed A to reveal notification text
dismissedUser pressed B to dismiss without reading
timedOutLow-priority notification auto-dismissed
erroredSnarling notification POST failed

Query the stats:

curl -s -X POST http://localhost:18789/approval-callback \
  -H "Authorization: Bearer <gateway-token>" \
  -H "Content-Type: application/json" \
  -d '{"action":"stats"}'

Returns: {"stats":{"requested":2,"approved":1,"rejected":1,"timedOut":0,"errored":0}}

Stats are in-memory only — they reset on gateway restart.

Architecture

OpenClaw Agent
      ↓ (plugin hooks: before_tool_call, before_agent_reply, agent_end)
Interaction Bridge Plugin
      ↓ (POST localhost:5000/state)               ← state updates
      ↓ (POST localhost:5000/approval/alert)      ← approval requests
      ↓ (POST localhost:5000/approval/alert)       ← notification requests (type: "notification")
      ↑ (POST localhost:18789/approval-callback)   ← approval responses
      ↑ (POST localhost:18789/notification-callback) ← notification feedback (revealed/dismissed/timed out)
Snarling Display (Python service on port 5000)
      ↓ (WebSocket RPC wake)                        ← bypasses gateway requests-in-flight

No approval_server middleman — the plugin talks directly to Snarling. Snarling resolves approvals and notifications via its A/B buttons and POSTs the result back to the gateway.

Install from ClawHub

openclaw plugins install clawhub:@snarflakes/openclaw-interaction-bridge

Development

git checkout development
# make changes
git add .
git commit -m "feat: description"
git push origin development

Credits

Built by Snar for the OpenClaw ecosystem.

源码与版本

源码仓库

snarflakes/openclaw-interaction-bridge

打开仓库

源码提交

a13147d

查看提交

安装命令

openclaw plugins install clawhub:openclaw-interaction-bridge

元数据

  • 包名: openclaw-interaction-bridge
  • 创建时间: 2026/04/26
  • 更新时间: 2026/04/26
  • 执行代码:
  • 源码标签: development

兼容性

  • 构建于 OpenClaw: 2026.4.5
  • 插件 API 范围: >=2026.3.24-beta.2
  • 标签: latest
  • 文件数: 9