Home Assistant
Home Assistant Integration
Section titled “Home Assistant Integration”Hermes Agent integrates with Home Assistant in two ways:
- Gateway platform — subscribes to real-time state changes via WebSocket and responds to events
- Smart home tools — four LLM-callable tools for querying and controlling devices via the REST API
1. Create a Long-Lived Access Token
Section titled “1. Create a Long-Lived Access Token”- Open your Home Assistant instance
- Go to your Profile (click your name in the sidebar)
- Scroll to Long-Lived Access Tokens
- Click Create Token, give it a name like “Hermes Agent”
- Copy the token
2. Configure Environment Variables
Section titled “2. Configure Environment Variables”# Add to ~/.hermes/.env
# Required: your Long-Lived Access TokenHASS_TOKEN=your-long-lived-access-token
# Optional: HA URL (default: http://homeassistant.local:8123)HASS_URL=http://192.168.1.100:8123The homeassistant toolset is automatically enabled when HASS_TOKEN is set. Both the gateway platform and the device control tools activate from this single token.
3. Start the Gateway
Section titled “3. Start the Gateway”hermes gatewayHome Assistant will appear as a connected platform alongside any other messaging platforms (Telegram, Discord, etc.).
Available Tools
Section titled “Available Tools”Hermes Agent registers four tools for smart home control:
ha_list_entities
Section titled “ha_list_entities”List Home Assistant entities, optionally filtered by domain or area.
Parameters:
domain(optional) — Filter by entity domain:light,switch,climate,sensor,binary_sensor,cover,fan,media_player, etc.area(optional) — Filter by area/room name (matches against friendly names):living room,kitchen,bedroom, etc.
Example:
List all lights in the living roomReturns entity IDs, states, and friendly names.
ha_get_state
Section titled “ha_get_state”Get detailed state of a single entity, including all attributes (brightness, color, temperature setpoint, sensor readings, etc.).
Parameters:
entity_id(required) — The entity to query, e.g.,light.living_room,climate.thermostat,sensor.temperature
Example:
What's the current state of climate.thermostat?Returns: state, all attributes, last changed/updated timestamps.
ha_list_services
Section titled “ha_list_services”List available services (actions) for device control. Shows what actions can be performed on each device type and what parameters they accept.
Parameters:
domain(optional) — Filter by domain, e.g.,light,climate,switch
Example:
What services are available for climate devices?ha_call_service
Section titled “ha_call_service”Call a Home Assistant service to control a device.
Parameters:
domain(required) — Service domain:light,switch,climate,cover,media_player,fan,scene,scriptservice(required) — Service name:turn_on,turn_off,toggle,set_temperature,set_hvac_mode,open_cover,close_cover,set_volume_levelentity_id(optional) — Target entity, e.g.,light.living_roomdata(optional) — Additional parameters as a JSON object
Examples:
Turn on the living room lights→ ha_call_service(domain="light", service="turn_on", entity_id="light.living_room")Set the thermostat to 22 degrees in heat mode→ ha_call_service(domain="climate", service="set_temperature", entity_id="climate.thermostat", data={"temperature": 22, "hvac_mode": "heat"})Set living room lights to blue at 50% brightness→ ha_call_service(domain="light", service="turn_on", entity_id="light.living_room", data={"brightness": 128, "color_name": "blue"})Gateway Platform: Real-Time Events
Section titled “Gateway Platform: Real-Time Events”The Home Assistant gateway adapter connects via WebSocket and subscribes to state_changed events. When a device state changes and matches your filters, it’s forwarded to the agent as a message.
Event Filtering
Section titled “Event Filtering”:::warning Required Configuration
By default, no events are forwarded. You must configure at least one of watch_domains, watch_entities, or watch_all to receive events. Without filters, a warning is logged at startup and all state changes are silently dropped.
:::
Configure which events the agent sees in ~/.hermes/config.yaml under the Home Assistant platform’s extra section:
platforms: homeassistant: enabled: true extra: watch_domains: - climate - binary_sensor - alarm_control_panel - light watch_entities: - sensor.front_door_battery ignore_entities: - sensor.uptime - sensor.cpu_usage - sensor.memory_usage cooldown_seconds: 30| Setting | Default | Description |
|---|---|---|
watch_domains | (none) | Only watch these entity domains (e.g., climate, light, binary_sensor) |
watch_entities | (none) | Only watch these specific entity IDs |
watch_all | false | Set to true to receive all state changes (not recommended for most setups) |
ignore_entities | (none) | Always ignore these entities (applied before domain/entity filters) |
cooldown_seconds | 30 | Minimum seconds between events for the same entity |
Event Formatting
Section titled “Event Formatting”State changes are formatted as human-readable messages based on domain:
| Domain | Format |
|---|---|
climate | ”HVAC mode changed from ‘off’ to ‘heat’ (current: 21, target: 23)“ |
sensor | ”changed from 21°C to 22°C” |
binary_sensor | ”triggered” / “cleared” |
light, switch, fan | ”turned on” / “turned off” |
alarm_control_panel | ”alarm state changed from ‘armed_away’ to ‘triggered’“ |
| (other) | “changed from ‘old’ to ‘new‘“ |
Agent Responses
Section titled “Agent Responses”Outbound messages from the agent are delivered as Home Assistant persistent notifications (via persistent_notification.create). These appear in the HA notification panel with the title “Hermes Agent”.
Connection Management
Section titled “Connection Management”- WebSocket with 30-second heartbeat for real-time events
- Automatic reconnection with backoff: 5s → 10s → 30s → 60s
- REST API for outbound notifications (separate session to avoid WebSocket conflicts)
- Authorization — HA events are always authorized (no user allowlist needed, since the
HASS_TOKENauthenticates the connection)
Security
Section titled “Security”The Home Assistant tools enforce security restrictions:
:::warning Blocked Domains The following service domains are blocked to prevent arbitrary code execution on the HA host:
shell_command— arbitrary shell commandscommand_line— sensors/switches that execute commandspython_script— scripted Python executionpyscript— broader scripting integrationhassio— addon control, host shutdown/rebootrest_command— HTTP requests from HA server (SSRF vector)
Attempting to call services in these domains returns an error. :::
Entity IDs are validated against the pattern ^[a-z_][a-z0-9_]*\.[a-z0-9_]+$ to prevent injection attacks.
Example Automations
Section titled “Example Automations”Morning Routine
Section titled “Morning Routine”User: Start my morning routine
Agent:1. ha_call_service(domain="light", service="turn_on", entity_id="light.bedroom", data={"brightness": 128})2. ha_call_service(domain="climate", service="set_temperature", entity_id="climate.thermostat", data={"temperature": 22})3. ha_call_service(domain="media_player", service="turn_on", entity_id="media_player.kitchen_speaker")Security Check
Section titled “Security Check”User: Is the house secure?
Agent:1. ha_list_entities(domain="binary_sensor") → checks door/window sensors2. ha_get_state(entity_id="alarm_control_panel.home") → checks alarm status3. ha_list_entities(domain="lock") → checks lock states4. Reports: "All doors closed, alarm is armed_away, all locks engaged."Reactive Automation (via Gateway Events)
Section titled “Reactive Automation (via Gateway Events)”When connected as a gateway platform, the agent can react to events:
[Home Assistant] Front Door: triggered (was cleared)
Agent automatically:1. ha_get_state(entity_id="binary_sensor.front_door")2. ha_call_service(domain="light", service="turn_on", entity_id="light.hallway")3. Sends notification: "Front door opened. Hallway lights turned on."