Configuration Hooks
The base consumer config file has a shared consumer object. Some settings are
common to every plugin, and some are specific to one agent type.
Common settings belong directly under consumer:
{
"consumer": {
"server_url": "http://localhost:8080",
"transport": "http",
"service_type": "my_agent",
"agent_config_path": "./my-agent.yml",
"agent_additional_params": []
}
}
Plugin-specific settings should live in a nested block named after the normalized service type:
{
"consumer": {
"service_type": "my_agent",
"my_agent": {
"api_host": "localhost",
"api_port": 19090,
"status_timeout_seconds": 5
}
}
}
That nested block is processed by the plugin, not by a growing list of
agent-specific branches in config.py.
The Hook Name
If the active config contains consumer.<service_type>, the consumer looks for
this function on the selected plugin module:
def process_consumer_config(
context: ConsumerPluginConfigContext,
) -> Mapping[str, Any] | None:
...
The hook receives a ConsumerPluginConfigContext with:
service_type: normalized plugin key, such asmy_agentsection_name: the nested config section nameraw_section: the nested plugin config blockconsumer_raw: the full rawconsumermappingconfig_path: path to the JSON file being loaded
Return a mapping of ConsumerConfig attribute names to values. The loader will
apply those attributes to the ConsumerConfig instance and log each loaded
plugin config value.
Example Hook
from __future__ import annotations
from typing import Any
from opamp_consumer.plugin_config import (
ConsumerPluginConfigContext,
resolve_optional_path_from_config,
)
def process_consumer_config(
context: ConsumerPluginConfigContext,
) -> dict[str, Any]:
raw = context.raw_section
return {
"my_agent_api_host": str(raw.get("api_host") or "localhost"),
"my_agent_api_port": int(raw.get("api_port") or 19090),
"my_agent_home_path": resolve_optional_path_from_config(
raw_value=raw.get("home_path"),
config_path=context.config_path,
),
}
Use resolve_optional_path_from_config(...) for plugin-owned paths. It resolves
relative paths from the config file directory, which is much friendlier than
resolving from whatever process working directory happens to be active.
How The Hook Is Found
The hook discovery order is:
- module named by the matching
consumer.pluginsentry - module discovered from the installed
opamp_consumer.pluginsentry point - conventional built-in module name:
opamp_consumer.<service_type>.client
This lets external packages work cleanly, while still keeping built-in plugins simple.
Keep Common And Plugin Config Separate
Use common ConsumerConfig fields when the concept is shared by all plugins:
server_urltransporttlsserver-authorizationagent_config_pathagent_additional_paramsprocessTrackingprocessDetectionRegexheartbeat_frequencyagent_capabilitiesservice_nameservice_namespace
Use a plugin-specific block when the field is only meaningful to your agent:
- CLI executable path
- daemon home directory
- custom status API host/port
- custom timeout
- credentials for a local agent API
- feature toggles that only your plugin understands
The rule of thumb is: if another plugin would need a paragraph explaining why the setting exists, keep it in your nested plugin block.
Document The Config
Add or update a plugin-specific page under consumer/docs/plugins/.
For a new plugin, create:
consumer/docs/plugins/my-agent.md
Then link it from the “Plugin Configuration Pages” section of
consumer/README.md. Keep the operator-facing config details there, and keep
developer mechanics in this guide.
OpAMP