> ## 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.

# HomeAssistant Core

> The central coordinator managing the event loop, components, and system lifecycle

The `HomeAssistant` class is the heart of the system, coordinating all operations and managing the asyncio event loop. Every integration, automation, and service interacts with this central hub.

## Core Class Structure

The `HomeAssistant` object is the main entry point for all Home Assistant operations:

```python homeassistant/core.py theme={null}
class HomeAssistant:
    """Root object of the Home Assistant home automation."""
    
    def __init__(self, config_dir: str) -> None:
        """Initialize new Home Assistant object."""
        self.data = HassDict()
        self.loop = asyncio.get_running_loop()
        self.bus = EventBus(self)
        self.services = ServiceRegistry(self)
        self.states = StateMachine(self.bus, self.loop)
        self.config = Config(self, config_dir)
        self.state: CoreState = CoreState.not_running
```

### Key Components

<CardGroup cols={2}>
  <Card title="data" icon="database">
    Shared storage dictionary for cross-component communication
  </Card>

  <Card title="loop" icon="rotate">
    The asyncio event loop managing all async operations
  </Card>

  <Card title="bus" icon="rss">
    Event bus for publishing and subscribing to events
  </Card>

  <Card title="services" icon="list">
    Registry of all available services across domains
  </Card>

  <Card title="states" icon="circle-nodes">
    State machine tracking all entity states
  </Card>

  <Card title="config" icon="gear">
    System configuration including paths and settings
  </Card>
</CardGroup>

## Lifecycle Management

### Startup Process

Home Assistant follows a well-defined startup sequence:

```python homeassistant/core.py theme={null}
async def async_start(self) -> None:
    """Finalize startup from inside the event loop."""
    _LOGGER.info("Starting Home Assistant %s", __version__)
    
    self.set_state(CoreState.starting)
    self.bus.async_fire_internal(EVENT_CORE_CONFIG_UPDATE)
    self.bus.async_fire_internal(EVENT_HOMEASSISTANT_START)
    
    # Wait for startup tasks with timeout
    if not self._tasks:
        pending = None
    else:
        _done, pending = await asyncio.wait(
            self._tasks, timeout=TIMEOUT_EVENT_START
        )
    
    # Allow automations to set up triggers
    await asyncio.sleep(0)
    
    self.set_state(CoreState.running)
    self.bus.async_fire_internal(EVENT_CORE_CONFIG_UPDATE)
    self.bus.async_fire_internal(EVENT_HOMEASSISTANT_STARTED)
```

<Steps>
  <Step title="Event Loop Started">
    The asyncio event loop begins running in the main thread.
  </Step>

  <Step title="Core Integrations Load">
    Essential integrations like `homeassistant` and `persistent_notification` are loaded.
  </Step>

  <Step title="START Event Fired">
    The `EVENT_HOMEASSISTANT_START` event signals integrations to begin setup.
  </Step>

  <Step title="Tasks Complete">
    All startup tasks must complete within 15 seconds (TIMEOUT\_EVENT\_START).
  </Step>

  <Step title="STARTED Event Fired">
    The `EVENT_HOMEASSISTANT_STARTED` event indicates the system is fully operational.
  </Step>
</Steps>

### Shutdown Process

Shutdown occurs in multiple stages to ensure clean termination:

```python homeassistant/core.py theme={null}
async def async_stop(self, exit_code: int = 0, *, force: bool = False) -> None:
    """Stop Home Assistant and shuts down all threads."""
    
    # Stage 1 - Run shutdown jobs
    try:
        async with self.timeout.async_timeout(STOPPING_STAGE_SHUTDOWN_TIMEOUT):
            tasks = []
            for job in self._shutdown_jobs:
                task_or_none = self.async_run_hass_job(job.job, *job.args)
                if task_or_none:
                    tasks.append(task_or_none)
            if tasks:
                await asyncio.gather(*tasks, return_exceptions=True)
    except TimeoutError:
        _LOGGER.warning("Timed out waiting for shutdown jobs")
    
    # Stage 2 - Stop integrations
    self.set_state(CoreState.stopping)
    self.bus.async_fire_internal(EVENT_HOMEASSISTANT_STOP)
    
    # Stage 3 - Final write
    self.set_state(CoreState.final_write)
    self.bus.async_fire_internal(EVENT_HOMEASSISTANT_FINAL_WRITE)
    
    # Stage 4 - Close
    self.set_state(CoreState.not_running)
    self.bus.async_fire_internal(EVENT_HOMEASSISTANT_CLOSE)
    
    self.set_state(CoreState.stopped)
```

<Note>
  The shutdown process has timeouts at each stage to prevent a single misbehaving integration from blocking shutdown indefinitely.
</Note>

## Task Management

Home Assistant provides sophisticated task management capabilities:

### Creating Tasks

```python homeassistant/core.py theme={null}
@callback
def async_create_task[_R](
    self,
    target: Coroutine[Any, Any, _R],
    name: str | None = None,
    eager_start: bool = True,
) -> asyncio.Task[_R]:
    """Create a task from within the event loop."""
    if eager_start:
        task = create_eager_task(target, name=name, loop=self.loop)
        if task.done():
            return task
    else:
        task = self.loop.create_task(target, name=name)
    
    self._tasks.add(task)
    task.add_done_callback(self._tasks.remove)
    return task
```

<Info>
  **Eager Start**: When `eager_start=True`, the task begins executing immediately rather than waiting for the next event loop iteration. This significantly improves performance for short-running tasks.
</Info>

### Background Tasks

Background tasks are designed for long-running operations:

```python homeassistant/core.py theme={null}
@callback
def async_create_background_task[_R](
    self, 
    target: Coroutine[Any, Any, _R], 
    name: str,
    eager_start: bool = True
) -> asyncio.Task[_R]:
    """Create a background task.
    
    A background task is different from a normal task:
    - Will not block startup
    - Will be automatically cancelled on shutdown  
    - Calls to async_block_till_done will not wait for completion
    """
    if eager_start:
        task = create_eager_task(target, name=name, loop=self.loop)
        if task.done():
            return task
    else:
        task = self.loop.create_task(target, name=name)
    
    self._background_tasks.add(task)
    task.add_done_callback(self._background_tasks.remove)
    return task
```

<Warning>
  Use background tasks for operations that should not prevent Home Assistant from starting or stopping, such as continuous monitoring loops or periodic sync operations.
</Warning>

## Job Execution

The `HassJob` system provides type-aware job execution:

```python homeassistant/core.py theme={null}
class HassJob[**_P, _R_co]:
    """Represent a job to be run later.
    
    We check the callable type in advance so we can avoid
    checking it every time we run the job.
    """
    
    def __init__(
        self,
        target: Callable[_P, _R_co],
        name: str | None = None,
        *,
        cancel_on_shutdown: bool | None = None,
        job_type: HassJobType | None = None,
    ) -> None:
        self.target = target
        self.name = name
        self._cancel_on_shutdown = cancel_on_shutdown
        if job_type:
            self._cache["job_type"] = job_type
```

### Job Types

<CodeGroup>
  ```python Coroutine Function theme={null}
  # Async functions run directly in event loop
  async def my_async_handler(event):
      await some_async_operation()
      
  job = HassJob(my_async_handler)
  # job.job_type == HassJobType.Coroutinefunction
  ```

  ```python Callback theme={null}
  # @callback decorated functions run immediately
  from homeassistant.core import callback

  @callback
  def my_callback_handler(event):
      # Synchronous, non-blocking operation
      process_event(event)
      
  job = HassJob(my_callback_handler)
  # job.job_type == HassJobType.Callback
  ```

  ```python Executor theme={null}
  # Regular functions run in thread pool
  def my_blocking_handler(event):
      # Blocking I/O operation
      result = requests.get("https://api.example.com")
      
  job = HassJob(my_blocking_handler)
  # job.job_type == HassJobType.Executor
  ```
</CodeGroup>

## Thread Safety

Home Assistant enforces strict thread safety:

```python homeassistant/core.py theme={null}
def verify_event_loop_thread(self, what: str) -> None:
    """Report and raise if not running in event loop thread."""
    if self.loop_thread_id != threading.get_ident():
        from .helpers import frame
        frame.report_non_thread_safe_operation(what)
```

### Calling from External Threads

When calling Home Assistant methods from external threads:

```python theme={null}
from homeassistant.util.async_ import run_callback_threadsafe

# From external thread
future = run_callback_threadsafe(
    hass.loop,
    hass.states.async_set,
    "sensor.example",
    "new_value"
)
result = future.result()  # Block until complete
```

<Tip>
  Always use `run_callback_threadsafe` when calling Home Assistant methods from background threads to avoid race conditions and data corruption.
</Tip>

## Accessing the Instance

In contexts where passing `hass` is impractical, you can retrieve it:

```python homeassistant/core.py theme={null}
@callback
def async_get_hass() -> HomeAssistant:
    """Return the HomeAssistant instance.
    
    Raises HomeAssistantError when called from the wrong thread.
    """
    if not (hass := async_get_hass_or_none()):
        raise HomeAssistantError(
            "async_get_hass called from the wrong thread"
        )
    return hass
```

<Warning>
  Use `async_get_hass()` sparingly. It's better to pass `hass` explicitly to maintain clear dependencies and improve testability.
</Warning>

## Configuration Management

The config object provides access to system configuration:

```python theme={null}
hass.config.config_dir      # Configuration directory path
hass.config.latitude        # Home location latitude  
hass.config.longitude       # Home location longitude
hass.config.elevation       # Home elevation
hass.config.time_zone       # System timezone
hass.config.units           # Unit system (metric/imperial)
hass.config.safe_mode       # Whether running in safe mode
hass.config.recovery_mode   # Whether running in recovery mode
```

## Data Storage

The `hass.data` dictionary provides shared storage:

```python theme={null}
# Store integration-specific data
hass.data["my_integration"] = MyIntegrationData()

# Use HassKey for type safety
from homeassistant.util.hass_dict import HassKey

MY_DATA_KEY: HassKey[MyIntegrationData] = HassKey("my_integration")
hass.data[MY_DATA_KEY] = MyIntegrationData()
```

<Note>
  Use the integration domain as the key to avoid conflicts. For complex data structures, consider using `HassKey` for type safety.
</Note>
