Skip to content

Plugin System

Overview

The Athomic Plugin System provides a powerful and clean way to extend the core functionality of the application without modifying its source code. Plugins can introduce new API routes, register custom services into the lifecycle, or execute logic at specific points in the application's startup sequence.

The system is built on Python's native importlib.metadata and entry points, making it a standard and robust way to create a pluggable architecture.

How It Works

  1. Entry Point: A plugin is a separate, installable Python package that defines an entry point in its pyproject.toml under the [project.entry-points."nala.plugins"] group.
  2. Discovery: At startup, the PluginManager discovers all installed packages that declare this entry point.
  3. Hooks: Plugins define functions decorated with @hookimpl. The PluginManager registers these functions as implementations for specific, predefined hooks.
  4. Execution: When the core application reaches a certain point, it calls plugin_manager.call_hook("hook_name"), which executes all registered implementations for that hook.

Available Hooks

  • on_athomic_startup(athomic: Athomic): Called early in the startup sequence. Ideal for registering custom services with the LifecycleRegistry.
  • get_api_routers() -> List[APIRouter]: Called by the web server layer. Each plugin can return a list of FastAPI APIRouter objects, which will be automatically mounted into the main application.

Creating a Plugin

See the plugins/nala-plugin-greetings directory for a complete example of a simple plugin.

API Reference

nala.athomic.plugins.hooks.hookimpl(func)

Decorator to explicitly mark a function as a hook implementation.

This metadata allows the PluginManager to discover and register the implementation with the corresponding hook specification.

nala.athomic.plugins.manager.PluginManager

Bases: PluginManagerProtocol

Mediates the interaction between the Athomic core and external plugins.

It implements the Mediator, Observer, and Registry patterns to handle plugin discovery, registration, and resilient hook execution.

__init__()

Initializes the PluginManager and its internal hook registry.

call_hook(hook_name, **kwargs) async

Executes all registered implementations for a given hook with resilience, observability (tracing/metrics), and failure notification.

discover_and_load() async

Discovers plugins using Python's entry points (group="nala.plugins"), loads their modules, and registers all functions marked with @hookimpl.

get_api_routers() async

Public contract method for the API layer. It calls the 'get_api_routers' hook, aggregates the results (a list of lists), and flattens them into a single list of router objects.