# Service Call

> Use when the user wants to call Home Assistant services (turn on lights, set temperature, toggle switches) through HA NOVA Relay.

- **Type:** Skill
- **Install:** `agentstack add skill-markusleben-ha-nova-service-call`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [markusleben](https://agentstack.voostack.com/s/markusleben)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [markusleben](https://github.com/markusleben)
- **Source:** https://github.com/markusleben/ha-nova/tree/main/skills/service-call
- **Website:** https://github.com/markusleben/ha-nova

## Install

```sh
agentstack add skill-markusleben-ha-nova-service-call
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# HA NOVA Service Call

## Scope

Direct device/service control:
- call any HA service (`light.turn_on`, `climate.set_temperature`, etc.)
- list available services
- target by entity_id, area_id, or device_id

No config mutations (use `ha-nova:write` for automation/script changes).

## Bootstrap (once per session)

Verify relay CLI: `ha-nova relay health`
If this fails: `ha-nova setup`

## Relay Contract

Use file-based payloads for service writes:
- `ha-nova relay core --method POST --path /api/services/... --body-file `
- `ha-nova relay core --method GET --path /api/states/`
- `--out ` when the response is large

## Flow

1. Resolve target entity (use entity discovery if name is ambiguous).
2. If service is unclear, list available services for the domain:
   - `ha-nova relay core --method GET --path /api/services`
   - Filter by relevant domain.
3. If the user names a room/area but the intended scope could be narrower, ask one clarifying question before using `area_id`.
   - Do not ask a second blocking ambiguity question in the same turn.
   - If entity resolution already consumed the one blocking question, default to the narrower confirmed target or stop and explain the ambiguity.
4. Preview the service call:
   - Before preview: read current state via `ha-nova relay core --method GET --path /api/states/{entity_id}`.
   - If service changes an attribute present in the service call parameters (brightness, temperature, position, hvac_mode, etc.) OR inherently changes entity state (toggle, turn_on, turn_off, press, lock, unlock, open, close), show state delta before the call details:
     ```
     **State delta:**
     brightness: 100% → 40%
     ```
   - Attribute display rules:
     - **Brightness**: HA uses 0-255 internally. ALWAYS show delta in %: `brightness: 100% → 40%` (not raw 0-255). If light is off (brightness null or absent), treat as 0%: `brightness: 0% → 40%`.
     - **Temperature**: Show with unit: `22.5°C → 19°C`. Note: `temperature` = setpoint (what we're changing), `current_temperature` = sensor reading (do NOT use for delta).
     - **Cover position**: `position: 100% (open) → 30%`.
     - **State / mode**: For parameterless state-changing services (toggle, turn_on, turn_off, press, lock, unlock), always show state delta: `on → off`. For mode changes, show: `hvac_mode: heat → cool`.
   - Entity `unavailable` → show delta as `unavailable → {target}` with warning: "Device is offline or unreachable."
   - Entity `unknown` → show delta as `unknown → {target}` with info: "State not yet known (HA may not have polled yet). Service call may still work."
   - State read failed → preview without delta, do not block.
   - Show: service (`domain.service`), target (`entity_id`), data fields.
   - Ask for natural confirmation.
5. Execute:
   - `ha-nova relay core --method POST --path /api/services/{domain}/{service} --body-file `
6. Verify result:
   - Check entity state after call: `ha-nova relay core --method GET --path /api/states/{entity_id}`
   - Report: service called, new state, any errors.

## Service Data Fields

Common patterns:
- `light.turn_on`: `brightness` (0-255), `color_temp` (mireds), `rgb_color` ([r,g,b])
- `climate.set_temperature`: `temperature`, `hvac_mode`
- `switch.toggle`: no extra fields needed
- `cover.set_cover_position`: `position` (0-100)

If unsure about required fields, check `/api/services` response for the service schema.

## Helper Service Patterns

Common service calls for helper entities:

- **input_boolean:** `input_boolean.turn_on`, `input_boolean.turn_off`, `input_boolean.toggle`
- **input_number:** `input_number.set_value` (`value`), `input_number.increment`, `input_number.decrement`
- **input_text:** `input_text.set_value` (`value`)
- **input_select:** `input_select.select_option` (`option`), `input_select.select_first`, `input_select.select_last`, `input_select.select_next`, `input_select.select_previous`
- **input_datetime:** `input_datetime.set_datetime` (`date`, `time`, or `datetime`)
- **input_button:** `input_button.press`
- **counter:** `counter.increment`, `counter.decrement`, `counter.reset`, `counter.set_value` (`value`)
- **timer:** `timer.start` (optional `duration`), `timer.pause`, `timer.cancel`, `timer.finish`, `timer.change` (`duration`)
- **schedule:** `schedule.reload` (reloads all schedule entities from config)

Example:
```json
{"method":"POST","path":"/api/services/input_number/set_value","body":{"entity_id":"input_number.target_temperature","value":22.5}}
```

For helper CRUD (create/update/delete helpers themselves), use `ha-nova:helper` instead.

## Safety

- Preview every service call before execution.
- Never guess entity IDs; resolve or ask.
- No token confirmation needed (service calls are reversible actions).
- For potentially disruptive services (e.g., `homeassistant.restart`), warn and ask for explicit confirmation.

## Error Handling

- `400/VALIDATION_ERROR`: invalid request shape — check path and body format
- `404/NOT_FOUND`: entity or service does not exist — re-resolve
- `502/UPSTREAM_WS_ERROR` or `504/TIMEOUT`: relay lost connection to HA — retry once, then report failure
- State verification failure (state didn't change): report discrepancy, do not retry automatically

## Guardrails

- One entity at a time unless user explicitly requests batch (array `entity_id` supported).
- Verify state change after call.
- If state didn't change as expected, report discrepancy.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [markusleben](https://github.com/markusleben)
- **Source:** [markusleben/ha-nova](https://github.com/markusleben/ha-nova)
- **License:** MIT
- **Homepage:** https://github.com/markusleben/ha-nova

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-markusleben-ha-nova-service-call
- Seller: https://agentstack.voostack.com/s/markusleben
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
