By default, HA services are "fire-and-forget" and return empty arrays [].
Register service with supports_response:
from homeassistant.helpers.service import SupportsResponse
hass.services.async_register(
domain,
"get_full_config",
handle_get_full_config,
schema=GET_CONFIG_SCHEMA,
supports_response=SupportsResponse.ONLY, # ← KEY PARAMETER
)
Call with ?return_response flag:
curl -X POST "$HA_URL/api/services/your_domain/get_full_config?return_response"
async def handle_get_full_config(hass: HomeAssistant, call: ServiceCall):
"""Handle the service call and return data."""
# ... your logic ...
return {"entities": entity_data, "automations": automation_data}
| Use Case | Use | Don't Use |
|---|---|---|
| ---------- | ----- | ----------- |
| Return complex data | HTTP View | Service (without response support) |
| Fire-and-forget actions | Service | HTTP View |
| Trigger automations | Service | HTTP View |
| Query state/config | HTTP View | Internal storage APIs |
For data retrieval APIs:
from homeassistant.components.http import HomeAssistantView
class OpenClawConfigView(HomeAssistantView):
"""HTTP view for retrieving config."""
url = "/api/openclaw/config"
name = "api:openclaw:config"
requires_auth = True
async def get(self, request):
hass = request.app["hass"]
config = await get_config_data(hass)
return json_response(config)
# Register in async_setup:
hass.http.register_view(OpenClawConfigView())
Never use underscore-prefixed APIs — they're private and change between versions.
❌ Wrong:
storage_collection = hass.data["_storage_collection"]
✅ Right:
# Use public APIs only
from homeassistant.helpers.storage import Store
store = Store(hass, STORAGE_VERSION, STORAGE_KEY)
from homeassistant.helpers.storage import Store
STORAGE_KEY = "your_domain.storage"
STORAGE_VERSION = 1
store = Store(hass, STORAGE_VERSION, STORAGE_KEY)
# Save
data = {"entities": modified_entities}
await store.async_save(data)
# Load
data = await store.async_load()
Use external database or file storage, not HA storage helpers.
| Change | Version | Migration |
|---|---|---|
| -------- | --------- | ----------- |
| Conversation agents | 2025.x+ | Use async_process directly |
| Service response data | 2023.7+ | Add supports_response param |
| Config entry migration | 2022.x+ | Use async_migrate_entry |
Always check: https://www.home-assistant.io/blog/ for your target version range.
custom_components/your_domain/
├── __init__.py # async_setup_entry
├── config_flow.py # UI configuration
├── manifest.json # Dependencies, version
├── services.yaml # Service definitions
└── storage_services.py # Your storage logic
{
"domain": "your_domain",
"name": "Your Integration",
"codeowners": ["@yourusername"],
"config_flow": true,
"dependencies": [],
"requirements": [],
"version": "1.0.0"
}
?return_response)developers.home-assistant.io/docs/creating_integration_indexdevelopers.home-assistant.io/docs/dev_101_servicesdevelopers.home-assistant.io/docs/api/webserverhome-assistant.io/blog/ (filter by version)hacs.xyz/docs/publish/startFrom HA-OpenClaw Bridge attempt:
> "80% of our issues were discoverable with 30-60 minutes of upfront docs reading. We jumped straight to coding based on assumptions rather than reading how HA actually works."
Use skills/pre-coding-research/ methodology before starting.
共 1 个版本