Plugin Startup¶
on_started() is called once immediately after the status transitions to STARTED,
before the main loop Task is scheduled. This is where you perform one-time setup:
loading
configuration files, opening connections, and initialising state in self.environment.
import asyncio
import json
from consortium.framework.plugins import BasePlugin
from consortium.framework.signal_exceptions.plugins_signal_exceptions import (
PluginStartError,
)
class Plugin(BasePlugin):
label = "consortium.plugins.agent_report"
name = "Agent Report Plugin"
description = (
"Logs a periodic summary of all currently registered agents "
"at a configurable interval."
)
version = "0.1.0"
compatible_framework_version = ">=0.1.0"
authors = {"Your Name"}
autostart = True
async def on_started(self) -> None:
config_path = self.root_directory / "config.json"
if not config_path.exists():
raise PluginStartError(
message=(
f"Configuration file not found at '{config_path}'. "
"Create a config.json with an 'interval_seconds' key."
),
)
with config_path.open("r") as f:
config = json.load(f)
self.environment.interval = config.get("interval_seconds", 60)
self.environment.total_reports_emitted = 0
self.logger.info(
"Agent Report Plugin started. Reporting every {} seconds.",
self.environment.interval,
)
Signalling errors: PluginStartError¶
The framework uses exceptions to communicate from hook methods back to the lifecycle
engine. Raising PluginStartError from on_started() aborts the start sequence
cleanly:
the plugin's status reverts to INITIALIZED and the error is surfaced to whoever called
start(). This is the correct way to signal that a plugin cannot start.
# Correct: tells the lifecycle engine to abort startup cleanly
raise PluginStartError(message="Configuration file missing.")
# Incorrect: an unhandled exception transitions the plugin to FATAL
raise FileNotFoundError("config.json not found")
Only raise PluginStartError from on_started(). Its counterparts for the other phases
are PluginRuntimeError (from on_running(), see
Plugin Error Handling) and PluginStopError (from
on_stopped(), see Plugin Shutdown).
self.environment¶
self.environment is a types.SimpleNamespace that is created fresh each time the
plugin is instantiated. Use it to carry mutable state across hook method calls:
# Setting state in on_started
self.environment.interval = 30
self.environment.total_reports = 0
# Reading it later in on_running or on_stopped
if self.environment.total_reports > 0:
...
Do not store state as direct instance attributes (self.interval = 30). Using
self.environment keeps runtime state clearly separate from class-level configuration
and from the framework-managed attributes on self.
self.root_directory¶
self.root_directory is a pathlib.Path pointing to the directory that contains
your plugin's source files. Use it to load sibling files without hard-coding absolute
paths:
config_path = self.root_directory / "config.json"
data_path = self.root_directory / "session_data.json"
self.logger¶
self.logger is a loguru logger automatically bound
with the plugin's name and ID. Use {} placeholders rather than f-strings so loguru can
defer evaluation until the message is actually written:
# Preferred: deferred evaluation
self.logger.info("Found {} agents.", len(agents))
# Avoid: eagerly evaluated even if the log level is filtered out
self.logger.info(f"Found {len(agents)} agents.")
Available levels: debug, info, success, warning, error, critical.
Continue to Plugin Running Loop to build the main loop.