Home Assistant capability parity — north-star roadmap¶
Status: proposed / north-star (2026-06-19). A forward-looking plan, not a committed
schedule. Research against a cloned home-assistant/core, mapped onto our existing subsystems.
Why this doc exists¶
The goal: eventually be able to offer the full breadth and depth of Home Assistant's functionality and integrations — with our own implementation, not HA's packages.
This is distinct from home-assistant-adoption.md, which is
the incremental polish of subsystems we already have (state timestamps, areas/labels, typed
selectors, richer flows) — much of that is shipped. This doc is the north star: what it takes
to grow from "an LLM agent that reads a synced datastore" into "a system that can do everything
HA does," and in what order.
The core tension (read this first)¶
HA and Personal Agent solve overlapping problems from opposite ends:
| Home Assistant | Personal Agent (today) | |
|---|---|---|
| Shape | Local-first real-time control system | Cloud/self-hosted durable LLM agent |
| Tenancy | Single-tenant | Multi-tenant (RLS, org scoping) |
| State | In-memory state machine, sub-second | Postgres snapshot via periodic pull + webhook push |
| Consumer | Dashboards, automations, voice | An LLM agent reading entities + tools |
| Latency | "turn the light on" in <1s | sync→DB→agent: seconds+ |
Our architecture is deliberately HA-shaped — the integration contract, the
entity/device/area model, the Workflow trigger engine, EntityWriter push, the Redis-Streams
bus and the Rust device-agent are the same building blocks HA has. We do not need to rebuild.
But our entity model today is "sync into the DB so the agent can read it." That cannot switch a
light in under a second. That is the one genuinely structural gap. Everything else is additive
on the existing integration contract.
The strategic decision¶
Add a real-time control plane alongside the existing agent/DB plane — do not replace it. The durable, governed, multi-tenant agent path stays exactly as is (Frozen Contracts intact). The new control plane is a low-latency lane for live device state and direct actuation that also feeds the same entity store (so the agent, history, automations and RAG all still see one truth).
The five pillars¶
Pillar 1 — Real-time control plane (the only structural gap)¶
Today: pull-sync + webhook push → DB → agent reads. async_call_action actuates synchronously
over HTTP+DB. For smart-home we additionally need a live lane:
- Live-state cache (Redis) beside the DB source of truth — sub-second state fan-out without
persisting every tick. The DB +
entity_state_historystay the durable record; the cache is the hot read path for dashboards/automations. - Low-latency push ingestion for
iot_class: local_push/local_polling. OurMessageListenerProvider+CommsListenerManager(survive-anything backoff supervisor) is exactly this pattern — generalize it from comms messages to arbitrary entity state: anEntityListenerProviderthat streams state changes and writes them throughEntityWriter+ the live cache. - Low-latency action dispatch.
async_call_actionexists but routes through HTTP+DB (and, for automations, Temporal). Add a direct in-process dispatch path for interactive control so "light on" never waits on a workflow. Durable/agent-initiated actions keep the existing path.
Reuses: EntityWriter, the Redis-Streams bus + AG-UI converter, availability column,
state_changed_at/state_updated_at, the listener-manager supervisor pattern.
New: live-state cache keys + read path, EntityListenerProvider capability, a direct
actuation dispatcher, iot_class-driven scheduling (push vs poll vs cloud).
Pillar 2 — Standard entity-class catalog (what makes breadth usable)¶
HA's real magic is not 1000 integrations — it's that a light from Hue, IKEA and Shelly share
one state/attribute/action schema (brightness, color, hvac_mode, cover position…). That is why
UI, voice and automations work generically across vendors.
Today we have free-form entity_type + device_class/state_class/unit + per-type actions.
Add a canonical catalog of standard entity classes — light, switch, binary_sensor,
sensor, climate, cover, lock, media_player, camera, fan, vacuum, … — each with a
fixed state/attribute/action schema. An integration that maps its entity onto light gets generic
controls, voice and automations for free. This is the single biggest conceptual win and the
lever that makes breadth pay off.
Reuses: EntityTypeDescriptor (device_class/state_class/unit/actions already there),
EntityActionDescriptor, the catalog-sync in integrations/sync.py.
New: a registry of canonical classes + their schemas; validation that an integration's
declared type conforms; generic UI cards + voice intents + automation building-blocks keyed on the
class rather than the domain.
Pillar 3 — Discovery + local connectivity (the device-agent as LAN bridge)¶
HA finds devices on the LAN (zeroconf/mDNS/Bluetooth/SSDP). We are cloud/self-hosted, so the Rust device-agent is our bridge into the LAN. Plan: the device-agent runs discovery, reports found devices to the backend, and that feeds discovery-source config flows (HA analog). The manifest regains the discovery vectors we intentionally omitted (zeroconf/bluetooth/…), scoped to "announced by a device-agent on the user's network."
Reuses: clients/device-agent/ + the device WS gateway, the config-flow manager (add a
discovery-initiated entry path), the manifest schema.
New: discovery vectors in the manifest, a device-agent discovery reporter, a discovery →
config-flow intake (dedupe by a stable unique id).
Pillar 4 — Robustness / self-healing (table stakes at scale)¶
The four items from the prior analysis are nice-to-have at 10 integrations and mandatory at 200+. At parity scale they are a precondition, not polish:
- Reauth flow (
ConfigEntryAuthFailedanalog →async_step_reauth) — credentials expire constantly (IMAP, OAuth, bridge sessions). Re-ask only the credentials, keep the rest, raise a user action + notification. Doubly valuable for us: the agent can read the open reauth and proactively offer to fix it. - Setup-retry with backoff (
ConfigEntryNotReadyanalog) — a transient external blip at boot must not kill an entry permanently. Mirrors our "readiness gates only on hard deps" philosophy (Frozen Contract #9) at the integration level. - Availability propagation on sync failure — the
availabilitycolumn already exists; wire N consecutive failures → entitiesunavailable+ poll-interval backoff (the useful half of HA'sDataUpdateCoordinator). "unavailable" is more honest than "stale-but-available." - Repairs / issue registry — a structured, actionable, dismissible issue an integration raises ("API key invalid", "device unreachable") with an optional guided fix flow. For us these are not just UI badges but context the agent reads and acts on. Reauth (#1) is really the most important special case of a repair issue — design #1 and #4 together.
Reuses: HealthResult, the config-flow manager, the availability/health columns, the
notification system.
New: an Issue/Repair model + registry, a reauth flow variant, a setup-retry state machine
on IntegrationConfig (loaded/setup_error/setup_retry) + reload endpoint.
Pillar 5 — Breadth engine (parity is, ultimately, a volume problem)¶
Reaching the long tail is a throughput problem. Make every new integration a pipeline, not handwork:
just new-integrationscaffold — generate the folder, manifest, config-flow, toolset and translation stubs.hassfest-style manifest lint in CI — today we validate only at load time (extra="forbid"); add a CI gate that validates every manifest + standard-class conformance.- A documented contribution path — the integration author's guide, trust-tier rules, the capability/standard-class contracts.
Reuses: the loader's validation, the just task runner, integrations/README.md.
New: the scaffold recipe, the CI lint, the author guide.
The pragmatic accelerator: a Home Assistant bridge¶
Before reimplementing 1000 integrations, a single Home-Assistant-bridge integration (against HA's WebSocket API) inherits HA's entire ecosystem immediately — HA entities become our entities, HA services become our actions. That is "not the same packages" — it is one package that inherits all the others.
Use it as a bridge, not a destination: it delivers breadth on day one while Pillars 1–2 are built and the highest-value integrations are reimplemented natively. The mature pattern is a dual strategy — native depth where it counts, bridge for the long-tail breadth. The bridge maps cleanly onto Pillar 2's standard classes (HA already speaks light/climate/cover/…), so the work is reusable rather than throwaway.
Sequencing¶
Phased so each phase is independently valuable and nothing becomes a parallel island:
- Phase 0 — Bridge + classes (breadth, fast). Standard entity-class catalog (Pillar 2, the reusable core) + the HA-bridge integration (immediate breadth). Validates the class catalog against a real, broad source.
- Phase 1 — Real-time lane (depth). The control plane (Pillar 1): live cache,
EntityListenerProvider, direct actuation. Now native integrations can be fast, not just present. - Phase 2 — Robustness (scale). Reauth + repairs + setup-retry + availability propagation (Pillar 4). Required before the integration count grows.
- Phase 3 — Local reach (LAN). Device-agent discovery + discovery config flows (Pillar 3).
- Phase 4 — Breadth engine (sustain). Scaffold + CI lint + author guide (Pillar 5), then reimplement the long tail natively, retiring bridge dependence where depth matters.
Open decisions¶
- How far into real-time do we go? Full sub-second local control, or "near-real-time orchestration" (the agent commands a control layer, HA-bridge or native, that owns the hard real-time loop)? This bounds Pillar 1's scope.
- Where does the live-state cache sit relative to RLS/multi-tenancy? Per-org Redis keyspaces; how does the governance/classification gate (Frozen Contract #14) apply to live state?
- Bridge entity identity — namespacing HA entity ids into our
(entry, type, external_id)without collisions, and whether bridged entities are tier-gated like native ones. - Standard-class governance — do canonical classes carry a default
required_tier, or is tier always per-integration?
Non-goals (deliberately not HA)¶
- Entity-as-a-live-Python-object + an in-process global state machine — contradicts our DB/Temporal/multi-tenant model on purpose.
supported_featuresbitmask — our explicit per-typeactionsmodel is clearer; keep it.- Re-using HA's Python packages or YAML config format.
- The HA add-on/supervisor model — our compute-provider/sandbox story covers running external workloads.
Compiled 2026-06-19 against a cloned
home-assistant/core. Each pillar maps onto an existing model/service in this repo; see the per-pillar Reuses/New notes for the file targets. Companion tohome-assistant-adoption.md(incremental) — this doc is the breadth/depth north star.