Home Assistant Left the Core: What Happens to Your Setup

You ask Hermes to dim the living-room lights and get unknown platform: homeassistant back. You changed nothing and deleted nothing — you just ran hermes update last night.
That is what “core slimming” looks like from the user side: a platform adapter that used to ship inside Hermes moved into the plugin catalog. The good news is that the move came with an automatic migration, and for most people nothing in their config needs to change. Here is what left, how the migration runs, and what to do if it does not land.
What actually left the core
Home Assistant used to be part of the kernel: plugins/platforms/homeassistant/ (the gateway platform adapter) plus tools/homeassistant_tool.py (the agent tool), along with the homeassistant / hermes-homeassistant toolsets, the Platform.HOMEASSISTANT enum, the HASS_TOKEN env-enable row, the pip homeassistant extra, and a pile of hardcoded entries scattered through dump output, the setup summary, the dashboard platform card and the ACP tool lists.
#132469 removed all of it. The feature now lives in the homeassistant catalog plugin (repo NousResearch/hermes-homeassistant, pinned at 2.0.1 in the review). In your upgraded tree, plugins/platforms/ no longer has a homeassistant directory.
Your config stays as it is
This is the best part: the plugin was built to be same names, same config keys, same environment variables.
HASS_TOKENandHASS_URLare unchanged;platforms.homeassistantin your gateway config is unchanged;- the
ha_*tool names are unchanged.
In other words, there is no new key to go and learn. The only thing you need to confirm is that the plugin is actually installed.
How the automatic migration works
The release adds a generic “left core” migration in hermes_cli/left_core_migration.py, and its design is worth reading because it solves the hardest part of any plugin split: moving existing users without a support thread.
The table is LEFT_CORE, and each row says which catalog plugin to install plus a read-only predicate for “did this home use the feature”. Right now there is exactly one row:
LEFT_CORE: tuple[LeftCoreFeature, ...] = (
LeftCoreFeature(
plugin="homeassistant", label="Home Assistant", in_use=homeassistant_in_use,
unchanged="HASS_TOKEN/HASS_URL, platforms.homeassistant and the ha_* tool names are unchanged",
secret_env=("HASS_TOKEN",), private_env=("HASS_URL",),
toolsets=("homeassistant",), off_platforms=("acp", "webhook"), platform="homeassistant",
enable_env=("HASS_TOKEN",), channel_env_prefixes=("HASS_",),
),
)
The “did this home use it” test is read-only: HASS_TOKEN in the home’s .env (that one variable enabled both the adapter and the tools), the platform enabled in its gateway config (legacy gateway.json or the gateway.platforms / platforms / gateway.homeassistant blocks, where the last explicit enabled wins), or homeassistant selected in the home’s toolsets. A HASS_TOKEN coming from the process environment (systemd, Docker) counts too.
Installs happen at three moments:
hermes update— installs for every profile home that shares the venv and used the feature;- agent start — retries once per process for the active home (desktop users update through the app and never run
hermes update, so this is how they get it), honouringsecurity.allow_lazy_installs; - gateway start — also retries once, and queues the outcome for that home’s first agent turn.
Installs go through the normal catalog path at the reviewed pin, so the kill list, dependency constraints and enable step all apply. One thoughtful detail: dependency consent is unattended for these rows, because the feature shipped in core and its users already accepted those dependencies back then.
Two more anti-annoyance rules:
- after a failed attempt (not in the catalog, unreachable, install error), startup retries skip the row for
STARTUP_RETRY_SECONDS— so an offline machine pays one network round trip, not one on everyhermes chat, whilehermes updatealways retries; - a home is auto-installed at most once, recorded as
_left_core_installedin itsconfig.yaml. If you remove the plugin later, that is your choice and it sticks.
Confirming it after the upgrade
hermes update
hermes plugins list | grep homeassistant
If the plugin shows up (enabled), you are done. If it did not install — say security.allow_lazy_installs: false, or the machine has been offline — installing it by hand works just as well:
hermes plugins install homeassistant
hermes plugins enable homeassistant
Note that plugins install resolves the reviewed pin from the plugin catalog rather than an arbitrary repo, so you are not pulling unreviewed code. For how plugin capabilities are isolated once installed, see plugin host isolation mode and the plugin catalog guide.
The table will grow
LEFT_CORE is generic; Home Assistant is only the first row. Combined with the catalog’s review and supply-chain checks (see plugin catalog CI and supply chain), it is fair to expect more built-in capabilities to take this path: removed from core, then installed automatically for the users who had them.
For users this is a healthier shape — a smaller kernel, faster updates, and platform adapters that can release on their own schedule instead of waiting for the next Hermes minor. The cost is that “built in” no longer means “always present”, so a quick glance at your platform plugins after an upgrade is a habit worth keeping.
The short version
- Home Assistant’s gateway platform and
homeassistanttool left the core and are now an official catalog plugin; hermes updateinstalls it for profiles that used it, with a retry at agent and gateway start that honourssecurity.allow_lazy_installs;- config keys, env vars and tool names are unchanged — if
hermes plugins listshows it, the migration worked; - if it did not install,
hermes plugins install homeassistantis the manual path, and more entries are expected inLEFT_CORE.