Ciclo de vida del plugin¶
Cuándo se ejecuta tu código: en el bootstrap de la API (arranque) o en cada petición HTTP (runtime).
Cuándo leer esta página¶
- Necesitas saber qué hooks existen y en qué orden se invocan.
- Quieres distinguir registro de UI (una vez) de lógica de negocio (por request).
- Vas a contribuir módulos a un namespace generativo (
operations,admin, …).
Discovery¶
El framework descubre plugins por:
- Entry points
cortex.pluginsenpyproject.toml(pip / workspace uv). - Sideload con
CORTEX_PLUGIN_DIRS=/ruta/extra(solo desarrollo; override por id). - Harness de tests
create_test_app(..., enabled_plugins="...")— equivalente al state store en memoria; no usar en producción.
En el monorepo cortex-hive, cada plugin es submódulo bajo plugins/. Sin git submodule update --init, el discovery no encuentra paquetes. Ver Repositorios y submódulos.
Los hosts opcionales con entry point cortex.panels se cargan después de materializar namespaces generativos, solo si el panel_id aún no existe.
Orden de bootstrap¶
Fuente del diagrama: docs/diagrams/guias-plugins-ciclo-de-vida-01.mermaid.
flowchart TB
C[Control embebido]
P[Plugins activos]
H[Hooks register_*]
E[ensure_panel]
M[merge_panel_infrastructure]
V[validate_panels]
C --> P --> H --> E --> M --> V - Control embebido —
bootstrap_control_panel(); panel/control/siempre presente. - Plugins activos — instancia cada
create_plugin()del state store. - Hooks — por cada módulo importado, invoca registries (UI, MCP, WS, listeners, observers, settings).
- Paneles generativos —
ensure_panel(panel_id)al primer aporte de un plugin. - Infraestructura — widgets, layouts, módulo
configurationpor panel. - Validación — cada módulo CUS referencia un
panel_idexistente.
Hosts opcionales cortex.panels se cargan entre los pasos 4 y 5 si el namespace dedicado aún no fue materializado.
Hooks de bootstrap¶
| Hook | Registry | Qué publica |
|---|---|---|
register_resources | ResourceRegistry | Manifest + dashboards + forms (recomendado) |
register_dashboards | DashboardRegistrar | JSON en ui/ (legacy) |
register_forms | FormRegistrar | Formularios sueltos |
register_settings | SettingsRegistry | Secciones de configuración |
register_configuration | ConfigurationRegistrar | Segmentos de settings por panel |
register_layouts | LayoutRegistrar | Fragmentos de layout (merge) |
register_reports | ReportRegistry | Reportes exportables |
register_widgets | WidgetRegistrar | Widgets sueltos |
register_render_hooks | RenderHookRegistrar | Slots en el shell |
register_mcp_tools | McpToolRegistry | Tools MCP (POST /mcp) |
register_ws_namespaces | WsNamespaceRegistry | Handlers WebSocket (WS /api/v1/ws) |
register_panel_plugins | PanelPluginRegistrar | Extensión del builder del host |
register_listeners | EventListenerRegistrar | Listeners de events (ADR 021) |
register_observers | ObserverRegistrar | Observers del ciclo de vida de entidades |
Ver Eventos de dominio.
Deprecado
register_panels y depender de paquetes host pip para operations/admin. Usa namespaces generativos y register_resources.
Prioridad de UI¶
Si el paquete exporta register_resources, el loader no ejecuta register_forms ni register_dashboards por separado — el ResourceBuilder ya registra forms y dashboards.
Los hooks deben reexportarse en el __init__.py del paquete del plugin; el loader importa el módulo raíz.
Bootstrap vs runtime¶
| Fase | Qué ocurre | Dónde vive tu código |
|---|---|---|
| Bootstrap | Discovery, hooks, validación CUS | resources.py, provider.py, __init__.py |
| Runtime | Peticiones REST, persistencia | plugin.py → api_router() |
No registres rutas ni manifests en handlers HTTP; hazlo en hooks de bootstrap.
Activación en runtime¶
Tras el arranque, un superadmin puede activar o desactivar plugins en /control/plugins. Si la respuesta incluye requiresRestart: true, reinicia cortex-api para cargar entry points nuevos.
Siguiente paso¶
Integración con el framework — flujo completo discovery → shell React.