Files
homeai/homeai-agent/skills/home-assistant/openclaw_bridge.py
Aodhan Collins 6db8ae4492 feat: complete voice pipeline — fix wake word crash, bridge timeout, HA conversation agent
- Fix Wyoming satellite crash on wake word: convert macOS .aiff chimes to .wav
  (Python wave module only reads RIFF format, not AIFF)
- Fix OpenClaw HTTP bridge: increase subprocess timeout 30s → 120s, add SO_REUSEADDR
- Fix HA conversation component: use HTTP agent (not CLI) since HA runs in Docker
  on a different machine; update default host to Mac Mini IP, timeout to 120s
- Rewrite character manager as Vite+React app with schema validation
- Add Wyoming satellite wake word command, ElevenLabs TTS server, wakeword monitor
- Add Phase 5 development plan
- Update TODO.md: mark voice pipeline and agent tasks complete

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:15:55 +00:00

93 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""OpenClaw Bridge for Home Assistant
This script acts as a bridge between Home Assistant and OpenClaw.
It can be called from HA via shell_command or command_line integration.
Usage:
python openclaw_bridge.py "Your message here"
Output:
{"response": "OpenClaw's response text"}
"""
import argparse
import json
import subprocess
import sys
from pathlib import Path
def load_character_prompt() -> str:
"""Load the active character system prompt."""
character_path = Path.home() / ".openclaw" / "characters" / "aria.json"
if not character_path.exists():
return ""
try:
with open(character_path) as f:
data = json.load(f)
return data.get("system_prompt", "")
except Exception:
return ""
def call_openclaw(message: str, agent: str = "main", timeout: int = 30) -> str:
"""Call OpenClaw CLI and return the response."""
# Inject system prompt
system_prompt = load_character_prompt()
if system_prompt:
message = f"System Context: {system_prompt}\n\nUser Request: {message}"
try:
result = subprocess.run(
["openclaw", "agent", "--message", message, "--agent", agent],
capture_output=True,
text=True,
timeout=timeout,
)
if result.returncode != 0:
return f"Error: OpenClaw failed with code {result.returncode}"
# Return stdout (the response)
return result.stdout.strip()
except subprocess.TimeoutExpired:
return "Error: OpenClaw command timed out"
except FileNotFoundError:
return "Error: openclaw command not found. Is OpenClaw installed?"
except Exception as e:
return f"Error: {str(e)}"
def main():
parser = argparse.ArgumentParser(
description="Bridge between Home Assistant and OpenClaw"
)
parser.add_argument("message", help="Message to send to OpenClaw")
parser.add_argument(
"--agent", default="main", help="Agent to use (default: main)"
)
parser.add_argument(
"--timeout", type=int, default=30, help="Timeout in seconds (default: 30)"
)
parser.add_argument(
"--raw", action="store_true", help="Output raw text instead of JSON"
)
args = parser.parse_args()
# Call OpenClaw
response = call_openclaw(args.message, args.agent, args.timeout)
if args.raw:
print(response)
else:
# Output as JSON for HA
output = {"response": response}
print(json.dumps(output))
if __name__ == "__main__":
main()