> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/home-assistant/core/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Loader

> Loading and managing Home Assistant integrations

The `homeassistant.loader` module provides the integration loading system that discovers, validates, and loads integrations.

## Integration Class

The `Integration` class represents a loaded integration and provides access to its components and metadata.

### Attributes

<ResponseField name="domain" type="str">
  Domain name of the integration
</ResponseField>

<ResponseField name="name" type="str">
  Human-readable name from the manifest
</ResponseField>

<ResponseField name="pkg_path" type="str">
  Python package path (e.g., "homeassistant.components.light")
</ResponseField>

<ResponseField name="file_path" type="pathlib.Path">
  Filesystem path to the integration
</ResponseField>

<ResponseField name="manifest" type="Manifest">
  The integration's manifest.json contents
</ResponseField>

<ResponseField name="dependencies" type="list[str]">
  List of domains this integration depends on
</ResponseField>

<ResponseField name="requirements" type="list[str]">
  List of Python package requirements
</ResponseField>

<ResponseField name="version" type="AwesomeVersion | None">
  Version of the integration (for custom integrations)
</ResponseField>

<ResponseField name="is_built_in" type="bool">
  Whether this is a built-in integration
</ResponseField>

<ResponseField name="config_flow" type="bool">
  Whether the integration has a config flow
</ResponseField>

<ResponseField name="documentation" type="str | None">
  URL to the integration's documentation
</ResponseField>

<ResponseField name="integration_type" type="str">
  Type of integration (entity, device, hub, service, helper, system, virtual)
</ResponseField>

<ResponseField name="iot_class" type="str | None">
  IoT class of the integration (cloud\_polling, cloud\_push, local\_polling, local\_push, etc.)
</ResponseField>

<ResponseField name="quality_scale" type="str | None">
  Quality scale rating (internal, silver, gold, platinum)
</ResponseField>

### Methods

#### async\_get\_component()

Load and return the integration's main component.

<ResponseField name="return" type="ComponentProtocol">
  The loaded component module
</ResponseField>

```python theme={null}
integration = await async_get_integration(hass, "light")
component = await integration.async_get_component()

# Now you can call component methods
if hasattr(component, "async_setup_entry"):
    await component.async_setup_entry(hass, entry)
```

#### async\_get\_platform(platform\_name)

Load and return a specific platform.

<ParamField path="platform_name" type="str" required>
  Name of the platform to load
</ParamField>

<ResponseField name="return" type="ModuleType">
  The loaded platform module
</ResponseField>

```python theme={null}
# Load the MQTT platform for the light integration
integration = await async_get_integration(hass, "light")
mqtt_platform = await integration.async_get_platform("mqtt")
```

#### async\_get\_platforms(platform\_names)

Load multiple platforms at once.

<ParamField path="platform_names" type="Iterable[str]" required>
  Names of platforms to load
</ParamField>

<ResponseField name="return" type="dict[str, ModuleType]">
  Dictionary mapping platform names to loaded modules
</ResponseField>

```python theme={null}
integration = await async_get_integration(hass, "my_integration")
platforms = await integration.async_get_platforms(["sensor", "switch"])

sensor_platform = platforms["sensor"]
switch_platform = platforms["switch"]
```

#### get\_component()

Synchronously get the component (thread-safe).

<Warning>
  This method is thread-safe but should generally be avoided in favor of `async_get_component()` in async code.
</Warning>

```python theme={null}
component = integration.get_component()
```

#### get\_platform(platform\_name)

Synchronously get a platform (thread-safe).

```python theme={null}
platform = integration.get_platform("mqtt")
```

## Loading Functions

### async\_get\_integration(hass, domain)

Get an integration by domain.

<ParamField path="hass" type="HomeAssistant" required>
  Home Assistant instance
</ParamField>

<ParamField path="domain" type="str" required>
  Domain of the integration to load
</ParamField>

<ResponseField name="return" type="Integration">
  The loaded integration
</ResponseField>

```python theme={null}
from homeassistant.loader import async_get_integration

integration = await async_get_integration(hass, "light")
print(f"Loaded {integration.name}")
```

<Note>
  Raises `IntegrationNotFound` if the integration doesn't exist.
</Note>

### async\_get\_integrations(hass, domains)

Get multiple integrations at once.

<ParamField path="hass" type="HomeAssistant" required>
  Home Assistant instance
</ParamField>

<ParamField path="domains" type="Iterable[str]" required>
  List of domains to load
</ParamField>

<ResponseField name="return" type="dict[str, Integration | Exception]">
  Dictionary mapping domains to Integration objects or exceptions
</ResponseField>

```python theme={null}
results = await async_get_integrations(hass, ["light", "switch", "sensor"])

for domain, result in results.items():
    if isinstance(result, Integration):
        print(f"Loaded {domain}")
    else:
        print(f"Failed to load {domain}: {result}")
```

### async\_get\_custom\_components(hass)

Get all custom integrations.

<ResponseField name="return" type="dict[str, Integration]">
  Dictionary of custom integrations by domain
</ResponseField>

```python theme={null}
custom = await async_get_custom_components(hass)
for domain, integration in custom.items():
    print(f"Custom: {domain} - {integration.name}")
```

### async\_get\_config\_flows(hass, type\_filter=None)

Get all integrations that support config flows.

<ParamField path="hass" type="HomeAssistant" required>
  Home Assistant instance
</ParamField>

<ParamField path="type_filter" type="str">
  Filter by integration type (device, helper, hub, service)
</ParamField>

<ResponseField name="return" type="set[str]">
  Set of domain names that support config flows
</ResponseField>

```python theme={null}
# Get all integrations with config flows
all_flows = await async_get_config_flows(hass)

# Get only device integrations with config flows
device_flows = await async_get_config_flows(hass, "device")
```

## Manifest Structure

The `manifest.json` file defines integration metadata:

```json theme={null}
{
  "domain": "my_integration",
  "name": "My Integration",
  "codeowners": ["@username"],
  "config_flow": true,
  "dependencies": ["http"],
  "documentation": "https://www.home-assistant.io/integrations/my_integration",
  "iot_class": "cloud_polling",
  "requirements": ["my-library==1.0.0"],
  "version": "1.0.0",
  "integration_type": "hub"
}
```

### Manifest Fields

<ParamField path="domain" type="str" required>
  Unique domain identifier (must match directory name)
</ParamField>

<ParamField path="name" type="str" required>
  Human-readable name
</ParamField>

<ParamField path="codeowners" type="list[str]">
  GitHub usernames of code owners
</ParamField>

<ParamField path="config_flow" type="bool" default="false">
  Whether the integration supports config flows
</ParamField>

<ParamField path="dependencies" type="list[str]">
  List of integration domains this depends on
</ParamField>

<ParamField path="after_dependencies" type="list[str]">
  Integrations to load before this one (soft dependencies)
</ParamField>

<ParamField path="requirements" type="list[str]">
  Python package requirements (with versions)
</ParamField>

<ParamField path="documentation" type="str">
  URL to documentation
</ParamField>

<ParamField path="integration_type" type="str">
  One of: entity, device, hardware, helper, hub, service, system, virtual
</ParamField>

<ParamField path="iot_class" type="str">
  IoT class: cloud\_polling, cloud\_push, local\_polling, local\_push, assumed, calculated
</ParamField>

<ParamField path="quality_scale" type="str">
  Quality scale: internal, silver, gold, platinum
</ParamField>

<ParamField path="version" type="str">
  Version string (required for custom integrations)
</ParamField>

<ParamField path="single_config_entry" type="bool" default="false">
  Whether only one config entry is allowed
</ParamField>

<ParamField path="import_executor" type="bool" default="true">
  Whether to import the integration in the executor
</ParamField>

## Component Protocol

Integrations can implement these methods to support various features:

### async\_setup(hass, config)

Set up the integration from YAML configuration.

<ParamField path="hass" type="HomeAssistant" required>
  Home Assistant instance
</ParamField>

<ParamField path="config" type="ConfigType" required>
  Configuration dictionary
</ParamField>

<ResponseField name="return" type="bool">
  True if setup succeeded
</ResponseField>

```python theme={null}
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the integration."""
    # Setup code here
    return True
```

### async\_setup\_entry(hass, entry)

Set up from a config entry.

```python theme={null}
async def async_setup_entry(
    hass: HomeAssistant,
    entry: ConfigEntry
) -> bool:
    """Set up from a config entry."""
    # Setup code here
    return True
```

### async\_unload\_entry(hass, entry)

Unload a config entry.

```python theme={null}
async def async_unload_entry(
    hass: HomeAssistant,
    entry: ConfigEntry
) -> bool:
    """Unload a config entry."""
    # Cleanup code here
    return True
```

### async\_remove\_entry(hass, entry)

Called when a config entry is removed.

```python theme={null}
async def async_remove_entry(
    hass: HomeAssistant,
    entry: ConfigEntry
) -> None:
    """Handle removal of an entry."""
    # Cleanup code here
    pass
```

### async\_migrate\_entry(hass, entry)

Migrate a config entry to a new version.

```python theme={null}
async def async_migrate_entry(
    hass: HomeAssistant,
    entry: ConfigEntry
) -> bool:
    """Migrate old entry."""
    # Migration code here
    return True
```

## Discovery Integration Types

### Bluetooth

Integrations can be discovered via Bluetooth:

```json theme={null}
{
  "bluetooth": [
    {
      "local_name": "My Device*",
      "service_uuid": "0000180f-0000-1000-8000-00805f9b34fb"
    }
  ]
}
```

### Zeroconf

Discovery via Zeroconf/mDNS:

```json theme={null}
{
  "zeroconf": [
    "_my-service._tcp.local.",
    {
      "type": "_another-service._tcp.local.",
      "name": "mydevice*"
    }
  ]
}
```

### SSDP

Discovery via SSDP:

```json theme={null}
{
  "ssdp": [
    {
      "manufacturer": "My Manufacturer",
      "modelName": "My Model"
    }
  ]
}
```

### USB

Discovery via USB:

```json theme={null}
{
  "usb": [
    {
      "vid": "10C4",
      "pid": "EA60"
    }
  ]
}
```

## Error Handling

### IntegrationNotFound

Raised when an integration cannot be found:

```python theme={null}
from homeassistant.loader import IntegrationNotFound

try:
    integration = await async_get_integration(hass, "nonexistent")
except IntegrationNotFound:
    _LOGGER.error("Integration not found")
```

## Best Practices

### Cache Integration References

Cache integration references to avoid repeated lookups:

```python theme={null}
class MyCoordinator:
    def __init__(self, hass, entry):
        self._integration = None
    
    async def _get_integration(self):
        if self._integration is None:
            self._integration = await async_get_integration(
                self.hass, "my_integration"
            )
        return self._integration
```

### Use Executor for Blocking Code

Set `import_executor: true` in manifest for integrations with blocking imports:

```json theme={null}
{
  "domain": "my_integration",
  "import_executor": true
}
```

### Specify Dependencies

Always declare integration dependencies:

```json theme={null}
{
  "dependencies": ["http", "mqtt"],
  "after_dependencies": ["recorder"]
}
```
