first commit
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
# OpenClaw Integration — Implementation Plan
|
||||
|
||||
## 1. Overview
|
||||
|
||||
This document describes the architecture and phased implementation plan for the
|
||||
**OpenClaw Integration** — a native Home Assistant custom integration that acts as
|
||||
a satellite companion to the existing **OpenClaw Assistant** addon.
|
||||
|
||||
### Goals
|
||||
|
||||
| # | Goal | Priority |
|
||||
|---|------|----------|
|
||||
| 1 | Chat card (text, streaming, files, voice) embedded in HA dashboard | P0 |
|
||||
| 2 | Sensor / binary-sensor entities for status, model, sessions | P0 |
|
||||
| 3 | Bidirectional addon ↔ integration communication (zero manual setup) | P0 |
|
||||
| 4 | Native HA conversation agent (Assist / Voice PE) | P1 |
|
||||
| 5 | Service calls & events for automations | P1 |
|
||||
| 6 | Media player entity for TTS output | P2 |
|
||||
|
||||
---
|
||||
|
||||
## 2. Existing Addon — Key Facts
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Slug | `openclaw_assistant_dev` |
|
||||
| Gateway port | `18789` (configurable via `gateway_port`) |
|
||||
| Auth | Token-based (`gateway.auth.token` in `openclaw.json`) |
|
||||
| Config file | `/config/.openclaw/openclaw.json` (addon container) |
|
||||
| OpenAI-compatible endpoint | `POST /v1/chat/completions` (opt-in via `enable_openai_api`) |
|
||||
| Gateway bind | `127.0.0.1` (loopback) or `0.0.0.0` (lan) |
|
||||
| Node process | `openclaw gateway run` |
|
||||
| Ingress port | `48099` (nginx) |
|
||||
|
||||
---
|
||||
|
||||
## 3. Architecture
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ Home Assistant Core │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────┐ │
|
||||
│ │ Sensors / │ │ Conversation │ │ Services / │ │
|
||||
│ │ Binary │ │ Agent │ │ Events │ │
|
||||
│ │ Sensors │ │ (Assist/VPE) │ │ │ │
|
||||
│ └──────┬───────┘ └──────┬───────┘ └───────┬────────┘ │
|
||||
│ │ │ │ │
|
||||
│ └────────┬────────┴───────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────▼────────┐ │
|
||||
│ │ OpenClawAPI │ (api.py — HTTP client) │
|
||||
│ │ Client │ │
|
||||
│ └───────┬────────┘ │
|
||||
│ │ HTTP / SSE │
|
||||
├──────────────────┼────────────────────────────────────────┤
|
||||
│ │ │
|
||||
│ ┌───────────────▼──────────────────────────────┐ │
|
||||
│ │ OpenClaw Gateway (addon) │ │
|
||||
│ │ │ │
|
||||
│ │ /v1/chat/completions (SSE streaming) │ │
|
||||
│ │ /api/status (JSON) │ │
|
||||
│ │ /api/sessions (JSON) │ │
|
||||
│ │ /api/models (JSON) │ │
|
||||
│ └──────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ OpenClaw Assistant Addon Container │
|
||||
└───────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ Lovelace Dashboard │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────┐ │
|
||||
│ │ openclaw-chat-card │ │
|
||||
│ │ ┌──────────────────────────────────┐ │ │
|
||||
│ │ │ Message history (markdown) │ │ │
|
||||
│ │ │ Typing indicator │ │ │
|
||||
│ │ │ File / image attachments │ │ │
|
||||
│ │ │ Voice input button │ │ │
|
||||
│ │ │ Voice mode toggle │ │ │
|
||||
│ │ └──────────────────────────────────┘ │ │
|
||||
│ └────────────────────────────────────────┘ │
|
||||
│ ▲ │
|
||||
│ │ HA WebSocket API │
|
||||
│ │ (openclaw.send_message service) │
|
||||
│ │ + event subscriptions │
|
||||
└───────┼─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
Home Assistant Core (services / events)
|
||||
```
|
||||
|
||||
### 3.1 Auto-Discovery (Zero-Config)
|
||||
|
||||
The integration discovers the addon with **no manual setup** using two mechanisms:
|
||||
|
||||
1. **Supervisor API** — at config-flow time the integration calls
|
||||
`GET /addons/openclaw_assistant_dev/info` via the HA Supervisor client.
|
||||
This gives us: addon state, network ports, options.
|
||||
|
||||
2. **Shared filesystem** — the addon mounts `/addon_configs/<slug>` which maps
|
||||
to `/config` inside the container. The integration can read
|
||||
`openclaw.json` to get the gateway auth token, mode, and port.
|
||||
|
||||
**Net effect:** the user clicks "Add Integration → OpenClaw" and everything
|
||||
connects automatically — no token or URL entry required.
|
||||
|
||||
### 3.2 Communication Protocol
|
||||
|
||||
| Direction | Transport | Endpoint / Mechanism |
|
||||
|-----------|-----------|----------------------|
|
||||
| Integration → Chat | HTTP POST + SSE stream | `/v1/chat/completions` (OpenAI compat) |
|
||||
| Integration → Status | HTTP GET (polled every 30 s) | `/api/status` |
|
||||
| Integration → Sessions | HTTP GET (polled every 60 s) | `/api/sessions` |
|
||||
| Integration → Models | HTTP GET (on startup + hourly) | `/v1/models` |
|
||||
| Addon → HA (events) | HA REST API (long-lived token) | `POST /api/events/openclaw_*` |
|
||||
| Frontend → Integration | HA WebSocket API | service calls + event subscriptions |
|
||||
|
||||
### 3.3 Latency Budget (Voice Mode)
|
||||
|
||||
| Step | Target | Notes |
|
||||
|------|--------|-------|
|
||||
| STT (browser/HA) | ≤ 500 ms | WebSpeech API or Whisper via HA |
|
||||
| Network to OpenClaw | ≤ 100 ms | localhost or LAN |
|
||||
| OpenClaw inference | ≤ 1500 ms | First token via SSE stream |
|
||||
| TTS | ≤ 500 ms | HA `tts.speak` or browser SpeechSynthesis |
|
||||
| **Total** | **≤ 2600 ms** | Under 3 s target |
|
||||
|
||||
---
|
||||
|
||||
## 4. File Structure
|
||||
|
||||
```
|
||||
openclaw_integration/
|
||||
├── IMPLEMENTATION_PLAN.md ← this file
|
||||
├── hacs.json ← HACS metadata
|
||||
├── README.md
|
||||
│
|
||||
├── custom_components/
|
||||
│ └── openclaw/
|
||||
│ ├── __init__.py ← integration setup, coordinator
|
||||
│ ├── manifest.json ← HA integration manifest
|
||||
│ ├── config_flow.py ← auto-discovery config flow
|
||||
│ ├── const.py ← constants, defaults
|
||||
│ ├── api.py ← OpenClaw gateway HTTP client
|
||||
│ ├── coordinator.py ← DataUpdateCoordinator for polling
|
||||
│ ├── sensor.py ← sensor entities
|
||||
│ ├── binary_sensor.py ← binary sensor entities
|
||||
│ ├── conversation.py ← native conversation agent
|
||||
│ ├── services.py ← service call handlers
|
||||
│ ├── services.yaml ← service definitions
|
||||
│ ├── strings.json ← English UI strings
|
||||
│ └── translations/
|
||||
│ └── en.json ← English translations
|
||||
│
|
||||
└── www/
|
||||
└── openclaw-chat-card.js ← Lovelace custom card (Lit)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Phased Implementation
|
||||
|
||||
### Phase 1 — Foundation (MVP)
|
||||
|
||||
**Goal:** Integration installs, auto-discovers addon, exposes sensors.
|
||||
|
||||
| Task | File(s) | Description |
|
||||
|------|---------|-------------|
|
||||
| 1.1 | `manifest.json` | Integration metadata, dependencies |
|
||||
| 1.2 | `const.py` | Domain, default ports, config keys |
|
||||
| 1.3 | `api.py` | `OpenClawApiClient` — HTTP client to gateway |
|
||||
| 1.4 | `config_flow.py` | Auto-discovery via Supervisor + shared config |
|
||||
| 1.5 | `coordinator.py` | `DataUpdateCoordinator` polling status/sessions/model |
|
||||
| 1.6 | `__init__.py` | Integration setup, platforms, coordinator init |
|
||||
| 1.7 | `sensor.py` | `openclaw_status`, `openclaw_last_activity`, `openclaw_session_count`, `openclaw_model` |
|
||||
| 1.8 | `binary_sensor.py` | `openclaw_connected` |
|
||||
| 1.9 | `strings.json`, `translations/en.json` | UI text |
|
||||
| 1.10 | `hacs.json` | HACS configuration |
|
||||
|
||||
**Acceptance criteria:**
|
||||
- `Add Integration → OpenClaw` works with zero config
|
||||
- All 5 entities appear and update
|
||||
- Integration reconnects gracefully when addon restarts
|
||||
|
||||
### Phase 2 — Services, Events & Conversation Agent
|
||||
|
||||
**Goal:** Automations can send/receive messages; Assist pipeline works.
|
||||
|
||||
| Task | File(s) | Description |
|
||||
|------|---------|-------------|
|
||||
| 2.1 | `services.yaml`, `services.py` | `openclaw.send_message`, `openclaw.clear_history` |
|
||||
| 2.2 | `__init__.py` (update) | Fire `openclaw_message_received` HA event on response |
|
||||
| 2.3 | `conversation.py` | Register as `conversation` agent |
|
||||
| 2.4 | `api.py` (update) | SSE streaming support (`async for` over response chunks) |
|
||||
| 2.5 | Testing | Verify Assist Text/Voice pipeline end-to-end |
|
||||
|
||||
**Acceptance criteria:**
|
||||
- `openclaw.send_message` callable from automations
|
||||
- `openclaw_message_received` event fires and can trigger automations
|
||||
- OpenClaw appears in Assist agent picker
|
||||
- Voice PE works: wake word → STT → OpenClaw → TTS → speaker
|
||||
|
||||
### Phase 3 — Chat Card (Frontend)
|
||||
|
||||
**Goal:** Full chat UI as a Lovelace custom card.
|
||||
|
||||
| Task | File(s) | Description |
|
||||
|------|---------|-------------|
|
||||
| 3.1 | `openclaw-chat-card.js` | Base card shell (Lit element, card config) |
|
||||
| 3.2 | (continued) | Message history with timestamps, markdown rendering |
|
||||
| 3.3 | (continued) | Streaming response display (typing indicator) |
|
||||
| 3.4 | (continued) | File/image attachment support (upload via service) |
|
||||
| 3.5 | (continued) | Voice input (WebSpeech/MediaRecorder → send audio) |
|
||||
| 3.6 | (continued) | Voice mode toggle (continuous listen → auto-respond with TTS) |
|
||||
| 3.7 | `__init__.py` (update) | Register card as Lovelace resource |
|
||||
| 3.8 | Card editor | Visual card configuration editor |
|
||||
|
||||
**Acceptance criteria:**
|
||||
- Card renders chat history with markdown
|
||||
- Real-time streaming of AI responses
|
||||
- File upload works in both directions
|
||||
- Voice input captures and sends audio
|
||||
- Voice mode maintains continuous conversation
|
||||
|
||||
### Phase 4 — Media Player & Polish
|
||||
|
||||
**Goal:** Native TTS output, wake word integration, production hardening.
|
||||
|
||||
| Task | File(s) | Description |
|
||||
|------|---------|-------------|
|
||||
| 4.1 | `media_player.py` | Media player entity for TTS output routing |
|
||||
| 4.2 | | Wake word detection integration |
|
||||
| 4.3 | | WebSocket connection management (token refresh, reconnect) |
|
||||
| 4.4 | | Error handling, rate limiting, connection pooling |
|
||||
| 4.5 | | Performance profiling (voice latency budget) |
|
||||
| 4.6 | | Documentation and HACS submission |
|
||||
|
||||
---
|
||||
|
||||
## 6. Entity Reference
|
||||
|
||||
### Sensors
|
||||
|
||||
| Entity ID | Class | State | Attributes |
|
||||
|-----------|-------|-------|------------|
|
||||
| `sensor.openclaw_status` | — | `online` / `offline` / `processing` | `gateway_version`, `uptime` |
|
||||
| `sensor.openclaw_last_activity` | `timestamp` | ISO 8601 datetime | `last_message_preview` |
|
||||
| `sensor.openclaw_session_count` | — | integer (active count) | `sessions` (list of IDs) |
|
||||
| `sensor.openclaw_model` | — | model name string | `provider`, `context_window` |
|
||||
|
||||
### Binary Sensors
|
||||
|
||||
| Entity ID | Class | State |
|
||||
|-----------|-------|-------|
|
||||
| `binary_sensor.openclaw_connected` | `connectivity` | `on` / `off` |
|
||||
|
||||
### Services
|
||||
|
||||
| Service | Fields | Description |
|
||||
|---------|--------|-------------|
|
||||
| `openclaw.send_message` | `message` (str), `session_id` (str, optional), `attachments` (list, optional) | Send a message to OpenClaw |
|
||||
| `openclaw.clear_history` | `session_id` (str, optional) | Clear conversation history |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Data | Description |
|
||||
|-------|------|-------------|
|
||||
| `openclaw_message_received` | `message`, `session_id`, `model`, `timestamp` | Fired when OpenClaw sends a response |
|
||||
|
||||
---
|
||||
|
||||
## 7. Key Technical Decisions
|
||||
|
||||
### 7.1 Why HTTP+SSE instead of WebSocket?
|
||||
|
||||
- The addon already exposes an **OpenAI-compatible** HTTP endpoint with SSE streaming
|
||||
- No additional gateway code needed on the addon side
|
||||
- SSE is simpler to manage (no bi-directional state, automatic reconnect)
|
||||
- WebSocket can be added later for real-time push features
|
||||
|
||||
### 7.2 Why Supervisor API for discovery?
|
||||
|
||||
- Available in all HAOS / Supervised installs (target audience)
|
||||
- Provides addon state, network config, and options without filesystem access
|
||||
- Filesystem fallback (`/addon_configs/`) handles edge cases
|
||||
|
||||
### 7.3 Why register as a conversation agent?
|
||||
|
||||
- Native Assist integration = works with Voice PE, S3 satellite, etc.
|
||||
- No need for third-party HACS integrations (Extended OpenAI Conversation)
|
||||
- Event-driven: HA handles STT/TTS pipeline, we just process text
|
||||
|
||||
### 7.4 Frontend card communication
|
||||
|
||||
- Card uses HA WebSocket API (already authenticated)
|
||||
- Calls `openclaw.send_message` service
|
||||
- Subscribes to `openclaw_message_received` events
|
||||
- No separate WebSocket to gateway needed (avoids CORS, auth issues)
|
||||
|
||||
---
|
||||
|
||||
## 8. Challenges & Mitigations
|
||||
|
||||
| Challenge | Mitigation |
|
||||
|-----------|------------|
|
||||
| Gateway not reachable (loopback bind) | Integration runs in same host; `127.0.0.1` works. Document `lan` mode for remote setups. |
|
||||
| Token rotation / mismatch | Re-read `openclaw.json` on connection failure; config flow stores token in HA config entry |
|
||||
| Voice latency > 3s | Use SSE streaming (first token fast), browser-side SpeechSynthesis for TTS, Whisper locally for STT |
|
||||
| Addon not installed | Config flow gracefully fails with a message directing user to install the addon first |
|
||||
| HACS distribution | Standard HACS custom integration + Lovelace card resources |
|
||||
| Large file uploads | Chunk uploads through service call; gateway handles multipart |
|
||||
|
||||
---
|
||||
|
||||
## 9. Dependencies
|
||||
|
||||
### Python (integration)
|
||||
|
||||
| Package | Purpose | In HA? |
|
||||
|---------|---------|--------|
|
||||
| `aiohttp` | HTTP client for gateway API | ✅ built-in |
|
||||
| `homeassistant` | HA core APIs | ✅ built-in |
|
||||
|
||||
### JavaScript (frontend card)
|
||||
|
||||
| Library | Purpose | Bundled? |
|
||||
|---------|---------|----------|
|
||||
| `lit` | Web component framework | ✅ available via HA |
|
||||
| `marked` | Markdown rendering | Bundle in card JS |
|
||||
|
||||
No additional pip dependencies required — the integration uses only HA built-ins.
|
||||
|
||||
---
|
||||
|
||||
## 10. Testing Strategy
|
||||
|
||||
| Level | Tool | Coverage |
|
||||
|-------|------|----------|
|
||||
| Unit | `pytest` + `pytest-homeassistant-custom-component` | API client, coordinator, config flow |
|
||||
| Integration | HA dev container with addon mock | End-to-end entity updates, service calls |
|
||||
| Frontend | Manual + Playwright | Card rendering, streaming, voice |
|
||||
|
||||
---
|
||||
|
||||
## 11. Timeline Estimate
|
||||
|
||||
| Phase | Duration | Milestone |
|
||||
|-------|----------|-----------|
|
||||
| Phase 1 | 1–2 weeks | Sensors visible, auto-discovery works |
|
||||
| Phase 2 | 1–2 weeks | Conversation agent in Assist, services/events |
|
||||
| Phase 3 | 2–3 weeks | Chat card MVP (text + streaming + files) |
|
||||
| Phase 4 | 2–3 weeks | Voice mode, media player, polish |
|
||||
|
||||
**Total estimated: 6–10 weeks to full feature set.**
|
||||
Reference in New Issue
Block a user