Registry System#
Centralized component registry with configuration-driven application loading, convention-based module discovery, and explicit component registration.
Core Registry Classes#
RegistryManager#
- class framework.registry.RegistryManager(application_names=None)[source]#
Bases:
object
Centralized registry for all ALS Expert Agent components.
This class provides the single point of access for capabilities, nodes, context classes, and data sources throughout the framework. It replaces the fragmented registry system with a unified approach that eliminates circular imports through lazy loading and provides dependency-ordered initialization.
The registry system follows a strict initialization order to handle dependencies: 1. Context classes (required by capabilities) 2. Data sources (required by capabilities) 3. Core nodes (infrastructure components) 4. Capabilities (domain-specific functionality) 5. Framework prompt providers (application-specific prompts) 6. Workflow templates (predefined execution patterns)
All components are loaded lazily using module path and class name metadata, preventing circular import issues while maintaining full introspection capabilities.
Note
The registry is typically accessed through the global functions get_registry() and initialize_registry() rather than instantiated directly.
Warning
Registry initialization must complete successfully before any components can be accessed. Failed initialization will raise RegistryError.
Initialize registry manager with convention-based application loading.
Creates a new registry manager instance that will load the specified application registries using naming conventions. The manager builds a merged configuration by combining the framework registry with all specified application registries.
The initialization process follows these steps: 1. Load framework registry from framework.registry.registry 2. Load application registries from applications.{app_name}.registry 3. Merge configurations with application overrides taking precedence 4. Prepare component registries for lazy loading
Applications are loaded using the convention-based pattern where each application name corresponds to a registry module at: applications.{app_name}.registry
Each application registry module must contain exactly one class implementing the RegistryConfigProvider interface.
- Parameters:
application_names (list[str], optional) – List of application names to load using conventions. If None or empty, only the framework registry will be loaded. Application names should match directory names under src/applications/
- Raises:
RegistryError – If any application registry cannot be loaded
ConfigurationError – If registry configuration is invalid
Note
The registry manager is not initialized after construction. Call initialize() to perform component loading and make components available for access.
Examples
Create registry with specific applications:
>>> manager = RegistryManager(["als_expert", "wind_turbine"]) >>> manager.initialize() # Load components >>> capability = manager.get_capability("pv_address_finding")
Create framework-only registry:
>>> manager = RegistryManager([]) # No applications >>> manager.initialize() >>> memory_cap = manager.get_capability("memory") # Framework capability
Typical usage through global functions:
>>> # Preferred approach - use global functions >>> from framework.registry import initialize_registry, get_registry >>> initialize_registry() # Uses config to determine applications >>> registry = get_registry()
See also
initialize_registry()
: Preferred way to create and initialize registryget_registry()
: Access the global singleton registry instanceinitialize()
: Initialize components after constructionRegistryConfigProvider
: Interface that applications must implementComponent Access Methods
Capabilities:
- get_capability(name)[source]#
Retrieve registered capability instance by name.
- Parameters:
name (str) – Unique capability name from registration
- Returns:
Capability instance if registered, None otherwise
- Return type:
framework.base.BaseCapability, optional
- get_all_capabilities()[source]#
Retrieve all registered capability instances.
- Returns:
List of all registered capability instances
- Return type:
Context Classes:
- get_context_class(context_type)[source]#
Retrieve context class by type identifier.
- Parameters:
context_type (str) – Context type identifier (e.g., ‘PV_ADDRESSES’)
- Returns:
Context class if registered, None otherwise
- Return type:
Type[framework.base.CapabilityContext], optional
- get_all_context_classes()[source]#
Get dictionary of all registered context classes by context type.
This method provides access to all registered context classes indexed by their context type identifiers. It enables introspection of the complete context system and supports dynamic context handling patterns.
- Returns:
Dictionary mapping context types to their corresponding context classes
- Return type:
Dict[str, Type[CapabilityContext]]
Examples
Access all context classes:
>>> registry = get_registry() >>> context_classes = registry.get_all_context_classes() >>> pv_class = context_classes.get("PV_ADDRESSES") >>> if pv_class: ... instance = pv_class(pvs=["test:pv"])
Infrastructure Nodes:
- get_node(name)[source]#
Retrieve registered node instance by name.
- Parameters:
name (str) – Unique node name from registration
- Returns:
Node instance if registered, None otherwise
- Return type:
framework.base.BaseCapabilityNode, optional
- get_all_nodes()[source]#
Retrieve all registered nodes as (name, callable) pairs.
- Returns:
Dictionary mapping node names to their callable instances
- Return type:
Dict[str, Any]
Data Sources:
- get_data_source(name)[source]#
Retrieve data source provider instance by name.
- Parameters:
name (str) – Unique data source name from registration
- Returns:
Data source provider instance if registered, None otherwise
- Return type:
Any, optional
- get_all_data_sources()[source]#
Retrieve all registered data source provider instances.
- Returns:
List of all registered data source provider instances
- Return type:
list[Any]
Services:
- get_service(name)[source]#
Retrieve registered service graph by name.
- Parameters:
name (str) – Unique service name from registration
- Returns:
Compiled LangGraph service instance if registered, None otherwise
- Return type:
Any, optional
- get_all_services()[source]#
Retrieve all registered service graph instances.
- Returns:
List of all registered service graph instances
- Return type:
list[Any]
Registry Management
- initialize()[source]#
Initialize all component registries in dependency order.
Performs complete initialization of the registry system by loading all registered components in the proper dependency order. This method handles the transition from configuration metadata to actual component instances, importing modules and instantiating classes as needed.
The initialization process follows strict dependency order to ensure components are available when needed by dependent components:
Context Classes: Data structures used by capabilities
Data Sources: External data providers used by capabilities
Core Nodes: Infrastructure components (router, orchestrator, etc.)
Services: Internal LangGraph service graphs
Capabilities: Domain-specific functionality
Framework Prompt Providers: Application-specific prompt customizations
During initialization, the registry: - Dynamically imports all component modules using lazy loading - Instantiates classes and functions as specified in registrations - Validates that all components can be loaded successfully - Creates proper cross-references between related components - Sets up prompt provider overrides and customizations
- Component Loading Details:
Context Classes: Imported and registered by type identifier
Data Sources: Instantiated and optionally health-checked
Nodes: Decorator-created functions registered for LangGraph
Capabilities: Instantiated with decorator-created node functions
Services: Service graphs compiled and made available
Analyzers: Policy and domain analyzers prepared for use
- Raises:
RegistryError – If any component fails to load, import, or initialize. This includes missing modules, invalid class names, or instantiation failures
ConfigurationError – If configuration is invalid, has circular dependencies, or contains inconsistent component definitions
ImportError – If any component module cannot be imported
AttributeError – If any component class or function is not found in its module
Note
This method is idempotent - multiple calls have no effect if the registry is already initialized. The initialization state is tracked internally.
Warning
All component imports occur during this call. Import failures, missing dependencies, or circular imports will prevent framework operation. Ensure all component modules and dependencies are available.
Examples
Basic initialization:
>>> registry = RegistryManager(["als_expert"]) >>> registry.initialize() # Load all components >>> print(registry.get_stats()) # Check what was loaded
Handle initialization errors:
>>> try: ... registry.initialize() ... except RegistryError as e: ... print(f"Registry initialization failed: {e}") ... # Check configuration or fix missing components
Check initialization status:
>>> if not registry._initialized: ... registry.initialize() >>> capability = registry.get_capability("my_capability")
See also
validate_configuration()
: Validate configuration before initializationget_stats()
: Check initialization results and component countsclear()
: Reset registry to uninitialized stateinitialize_registry()
: Global function that calls this method
- validate_configuration()[source]#
Validate registry configuration for consistency and completeness.
Performs comprehensive validation of the registry configuration including duplicate name checking, dependency validation, and structural consistency. This method should be called before initialization to catch configuration errors early.
- Returns:
List of validation error messages, empty if valid
- Return type:
list[str]
Examples
Validate before initialization:
>>> registry = get_registry() >>> errors = registry.validate_configuration() >>> if errors: ... print(f"Configuration errors: {errors}") ... else: ... registry.initialize()
- export_registry_to_json(output_dir=None)[source]#
Export registry metadata for external tools and plan editors.
Creates comprehensive JSON export of all registered components including capabilities, context types, and workflow templates. This data is used by execution plan editors and other external tools to understand system capabilities.
- Parameters:
output_dir (str, optional) – Directory path for saving JSON files, if None returns data only
- Returns:
Complete registry metadata with capabilities, context types, and templates
- Return type:
dict[str, Any]
- Raises:
Exception – If file writing fails when output_dir is specified
Examples
Export to directory:
>>> registry = get_registry() >>> data = registry.export_registry_to_json("/tmp/registry") >>> print(f"Exported {data['metadata']['total_capabilities']} capabilities")
Get data without saving:
>>> data = registry.export_registry_to_json() >>> capabilities = data['capabilities']
Registry Statistics and Debugging
- get_stats()[source]#
Retrieve comprehensive registry statistics for debugging.
- Returns:
Dictionary containing counts and lists of registered components
- Return type:
dict[str, Any]
Examples
Check registry status:
>>> registry = get_registry() >>> stats = registry.get_stats() >>> print(f"Loaded {stats['capabilities']} capabilities") >>> print(f"Available: {stats['capability_names']}")
- __init__(application_names=None)[source]#
Initialize registry manager with convention-based application loading.
Creates a new registry manager instance that will load the specified application registries using naming conventions. The manager builds a merged configuration by combining the framework registry with all specified application registries.
The initialization process follows these steps: 1. Load framework registry from framework.registry.registry 2. Load application registries from applications.{app_name}.registry 3. Merge configurations with application overrides taking precedence 4. Prepare component registries for lazy loading
Applications are loaded using the convention-based pattern where each application name corresponds to a registry module at: applications.{app_name}.registry
Each application registry module must contain exactly one class implementing the RegistryConfigProvider interface.
- Parameters:
application_names (list[str], optional) – List of application names to load using conventions. If None or empty, only the framework registry will be loaded. Application names should match directory names under src/applications/
- Raises:
RegistryError – If any application registry cannot be loaded
ConfigurationError – If registry configuration is invalid
Note
The registry manager is not initialized after construction. Call initialize() to perform component loading and make components available for access.
Examples
Create registry with specific applications:
>>> manager = RegistryManager(["als_expert", "wind_turbine"]) >>> manager.initialize() # Load components >>> capability = manager.get_capability("pv_address_finding")
Create framework-only registry:
>>> manager = RegistryManager([]) # No applications >>> manager.initialize() >>> memory_cap = manager.get_capability("memory") # Framework capability
Typical usage through global functions:
>>> # Preferred approach - use global functions >>> from framework.registry import initialize_registry, get_registry >>> initialize_registry() # Uses config to determine applications >>> registry = get_registry()
See also
initialize_registry()
: Preferred way to create and initialize registryget_registry()
: Access the global singleton registry instanceinitialize()
: Initialize components after constructionRegistryConfigProvider
: Interface that applications must implement
- initialize()[source]#
Initialize all component registries in dependency order.
Performs complete initialization of the registry system by loading all registered components in the proper dependency order. This method handles the transition from configuration metadata to actual component instances, importing modules and instantiating classes as needed.
The initialization process follows strict dependency order to ensure components are available when needed by dependent components:
Context Classes: Data structures used by capabilities
Data Sources: External data providers used by capabilities
Core Nodes: Infrastructure components (router, orchestrator, etc.)
Services: Internal LangGraph service graphs
Capabilities: Domain-specific functionality
Framework Prompt Providers: Application-specific prompt customizations
During initialization, the registry: - Dynamically imports all component modules using lazy loading - Instantiates classes and functions as specified in registrations - Validates that all components can be loaded successfully - Creates proper cross-references between related components - Sets up prompt provider overrides and customizations
- Component Loading Details:
Context Classes: Imported and registered by type identifier
Data Sources: Instantiated and optionally health-checked
Nodes: Decorator-created functions registered for LangGraph
Capabilities: Instantiated with decorator-created node functions
Services: Service graphs compiled and made available
Analyzers: Policy and domain analyzers prepared for use
- Raises:
RegistryError – If any component fails to load, import, or initialize. This includes missing modules, invalid class names, or instantiation failures
ConfigurationError – If configuration is invalid, has circular dependencies, or contains inconsistent component definitions
ImportError – If any component module cannot be imported
AttributeError – If any component class or function is not found in its module
Note
This method is idempotent - multiple calls have no effect if the registry is already initialized. The initialization state is tracked internally.
Warning
All component imports occur during this call. Import failures, missing dependencies, or circular imports will prevent framework operation. Ensure all component modules and dependencies are available.
Examples
Basic initialization:
>>> registry = RegistryManager(["als_expert"]) >>> registry.initialize() # Load all components >>> print(registry.get_stats()) # Check what was loaded
Handle initialization errors:
>>> try: ... registry.initialize() ... except RegistryError as e: ... print(f"Registry initialization failed: {e}") ... # Check configuration or fix missing components
Check initialization status:
>>> if not registry._initialized: ... registry.initialize() >>> capability = registry.get_capability("my_capability")
See also
validate_configuration()
: Validate configuration before initializationget_stats()
: Check initialization results and component countsclear()
: Reset registry to uninitialized stateinitialize_registry()
: Global function that calls this method
- export_registry_to_json(output_dir=None)[source]#
Export registry metadata for external tools and plan editors.
Creates comprehensive JSON export of all registered components including capabilities, context types, and workflow templates. This data is used by execution plan editors and other external tools to understand system capabilities.
- Parameters:
output_dir (str, optional) – Directory path for saving JSON files, if None returns data only
- Returns:
Complete registry metadata with capabilities, context types, and templates
- Return type:
dict[str, Any]
- Raises:
Exception – If file writing fails when output_dir is specified
Examples
Export to directory:
>>> registry = get_registry() >>> data = registry.export_registry_to_json("/tmp/registry") >>> print(f"Exported {data['metadata']['total_capabilities']} capabilities")
Get data without saving:
>>> data = registry.export_registry_to_json() >>> capabilities = data['capabilities']
- get_capability(name)[source]#
Retrieve registered capability instance by name.
- Parameters:
name (str) – Unique capability name from registration
- Returns:
Capability instance if registered, None otherwise
- Return type:
framework.base.BaseCapability, optional
- get_always_active_capability_names()[source]#
Get names of capabilities marked as always active.
- Returns:
List of capability names that are always active
- Return type:
List[str]
- get_all_capabilities()[source]#
Retrieve all registered capability instances.
- Returns:
List of all registered capability instances
- Return type:
- get_capabilities_overview()[source]#
Generate a text overview of all registered capabilities.
- Returns:
Human-readable overview of capabilities and their descriptions
- Return type:
str
- get_node(name)[source]#
Retrieve registered node instance by name.
- Parameters:
name (str) – Unique node name from registration
- Returns:
Node instance if registered, None otherwise
- Return type:
framework.base.BaseCapabilityNode, optional
- get_all_nodes()[source]#
Retrieve all registered nodes as (name, callable) pairs.
- Returns:
Dictionary mapping node names to their callable instances
- Return type:
Dict[str, Any]
- get_context_class(context_type)[source]#
Retrieve context class by type identifier.
- Parameters:
context_type (str) – Context type identifier (e.g., ‘PV_ADDRESSES’)
- Returns:
Context class if registered, None otherwise
- Return type:
Type[framework.base.CapabilityContext], optional
- get_context_class_by_name(class_name)[source]#
Retrieve context class by class name identifier.
- Parameters:
class_name (str) – Python class name (e.g., ‘PVAddresses’)
- Returns:
Context class if found, None otherwise
- Return type:
Type[framework.base.CapabilityContext], optional
- is_valid_context_type(context_type)[source]#
Check if a context type is registered in the registry.
- Parameters:
context_type (str) – Context type identifier (e.g., ‘PV_ADDRESSES’)
- Returns:
True if context type is registered, False otherwise
- Return type:
bool
- get_all_context_types()[source]#
Get list of all registered context types.
- Returns:
List of all registered context type identifiers
- Return type:
list[str]
- get_all_context_classes()[source]#
Get dictionary of all registered context classes by context type.
This method provides access to all registered context classes indexed by their context type identifiers. It enables introspection of the complete context system and supports dynamic context handling patterns.
- Returns:
Dictionary mapping context types to their corresponding context classes
- Return type:
Dict[str, Type[CapabilityContext]]
Examples
Access all context classes:
>>> registry = get_registry() >>> context_classes = registry.get_all_context_classes() >>> pv_class = context_classes.get("PV_ADDRESSES") >>> if pv_class: ... instance = pv_class(pvs=["test:pv"])
- get_data_source(name)[source]#
Retrieve data source provider instance by name.
- Parameters:
name (str) – Unique data source name from registration
- Returns:
Data source provider instance if registered, None otherwise
- Return type:
Any, optional
- get_all_data_sources()[source]#
Retrieve all registered data source provider instances.
- Returns:
List of all registered data source provider instances
- Return type:
list[Any]
- get_service(name)[source]#
Retrieve registered service graph by name.
- Parameters:
name (str) – Unique service name from registration
- Returns:
Compiled LangGraph service instance if registered, None otherwise
- Return type:
Any, optional
- get_all_services()[source]#
Retrieve all registered service graph instances.
- Returns:
List of all registered service graph instances
- Return type:
list[Any]
- get_execution_policy_analyzers()[source]#
Retrieve all registered execution policy analyzer instances.
Creates instances of execution policy analyzers with empty configurable. The actual configurable will be provided when the analyzers are used.
- Returns:
List of execution policy analyzer instances
- Return type:
list[Any]
- get_domain_analyzers()[source]#
Retrieve all registered domain analyzer instances.
Creates instances of domain analyzers with empty configurable. The actual configurable will be provided when the analyzers are used.
- Returns:
List of domain analyzer instances
- Return type:
list[Any]
- get_available_data_sources(state)[source]#
Retrieve available data sources for current execution context.
Filters all registered data sources based on their availability for the current agent state and returns them in registration order (framework providers first, then applications).
- Parameters:
state (framework.state.AgentState) – Current agent state for availability checking
- Returns:
Available data source providers in registration order
- Return type:
list[Any]
Note
Providers without is_available() method are assumed to be available.
- property context_types#
Dynamic object providing context type constants as attributes.
Creates a dynamic object where each registered context type is accessible as an attribute with its string value.
- Returns:
Object with context types as attributes
- Return type:
object
Examples
Access context types:
>>> registry = get_registry() >>> pv_type = registry.context_types.PV_ADDRESSES >>> print(pv_type) # "PV_ADDRESSES"
- property capability_names#
Dynamic object providing capability names as constants with debug fallback.
Creates a dynamic object where each registered capability name is accessible as an uppercase constant attribute. If a capability name is not registered, returns the expected string and logs a warning (useful for development).
- Returns:
Object with capability names as constant attributes
- Return type:
object
Examples
Access capability names as constants:
>>> registry = get_registry() >>> pv_finding = registry.capability_names.PV_ADDRESS_FINDING >>> print(pv_finding) # "pv_address_finding"
Graceful fallback for missing capabilities:
>>> viz_name = registry.capability_names.DATA_VISUALIZATION # Not registered >>> print(viz_name) # "data_visualization" (with warning logged)
- validate_configuration()[source]#
Validate registry configuration for consistency and completeness.
Performs comprehensive validation of the registry configuration including duplicate name checking, dependency validation, and structural consistency. This method should be called before initialization to catch configuration errors early.
- Returns:
List of validation error messages, empty if valid
- Return type:
list[str]
Examples
Validate before initialization:
>>> registry = get_registry() >>> errors = registry.validate_configuration() >>> if errors: ... print(f"Configuration errors: {errors}") ... else: ... registry.initialize()
- get_stats()[source]#
Retrieve comprehensive registry statistics for debugging.
- Returns:
Dictionary containing counts and lists of registered components
- Return type:
dict[str, Any]
Examples
Check registry status:
>>> registry = get_registry() >>> stats = registry.get_stats() >>> print(f"Loaded {stats['capabilities']} capabilities") >>> print(f"Available: {stats['capability_names']}")
- clear()[source]#
Clear all registry data and reset initialization state.
Removes all registered components and marks the registry as uninitialized. This method is primarily used for testing to ensure clean state between tests.
Warning
This method clears all registered components. Only use for testing or complete registry reset scenarios.
Global Registry Functions#
- framework.registry.get_registry()[source]#
Retrieve the global registry manager singleton instance.
Returns the global registry manager instance, creating it automatically if it doesn’t exist. This function provides the primary access point for the registry system throughout the framework, ensuring consistent access to the same registry instance across all framework components.
The registry instance is created from the global configuration. Applications are loaded from the ‘applications’ configuration key and their registries are loaded using the pattern: applications.{app_name}.registry
- Singleton Behavior:
First call creates the registry instance from configuration
Subsequent calls return the same instance
Registry persists for the lifetime of the application
Thread-safe access to the global instance
- Registry Creation Process:
Read ‘applications’ list from global configuration
Create RegistryManager with configured application names
Build merged configuration (framework + applications)
Return uninitialized registry instance
- Returns:
The global registry manager singleton instance. The instance may not be initialized - call initialize_registry() or registry.initialize() to load components before accessing them
- Return type:
- Raises:
ConfigurationError – If global configuration is invalid or applications configuration is malformed
RuntimeError – If registry creation fails due to configuration issues
Note
The returned registry instance may not be initialized. Components are not available until initialize_registry() or registry.initialize() is called.
Warning
This function creates the registry from global configuration on first access. Ensure configuration is properly set before calling this function.
Examples
Basic registry access:
>>> from framework.registry import get_registry, initialize_registry >>> >>> # Initialize first, then access >>> initialize_registry() >>> registry = get_registry() >>> capability = registry.get_capability("pv_address_finding")
Check if registry is initialized:
>>> registry = get_registry() >>> if not registry._initialized: ... registry.initialize() >>> stats = registry.get_stats()
Access registry from different modules:
>>> # Same instance returned everywhere >>> from framework.registry import get_registry >>> registry1 = get_registry() >>> registry2 = get_registry() >>> assert registry1 is registry2 # Same instance
See also
initialize_registry()
: Initialize the registry system with componentsreset_registry()
: Reset the global registry instanceRegistryManager
: The registry manager class returned by this function Registry and Discovery : Registry access patterns
- framework.registry.initialize_registry(auto_export=True)[source]#
Initialize the global registry system with all components.
Performs complete initialization of the global registry system, including loading of application registries, component loading in dependency order, and optional export of registry metadata for external tools. This function should be called once during application startup before accessing any framework components.
The initialization process: 1. Gets or creates the global registry singleton instance 2. Loads all components in proper dependency order 3. Validates that all components loaded successfully 4. Optionally exports registry metadata to JSON files 5. Sets up the registry for component access throughout the application
- Component Loading Order:
Context classes (data structures)
Data sources (external data providers)
Core nodes (infrastructure components)
Services (internal LangGraph service graphs)
Capabilities (domain-specific functionality)
Framework prompt providers (application customizations)
- Auto-Export Functionality:
When auto_export is True, the function automatically exports complete registry metadata to JSON files for use by external tools, execution plan editors, and documentation systems. Export includes capability definitions, context types, and component relationships.
- Parameters:
auto_export (bool) – Whether to automatically export registry metadata to JSON files after successful initialization. Export files are saved to the configured registry_exports_dir location
- Raises:
RegistryError – If registry initialization fails due to component loading errors, missing modules, or invalid component definitions
ConfigurationError – If global configuration is invalid, application configurations are malformed, or dependencies are inconsistent
ImportError – If any component module cannot be imported
AttributeError – If any component class or function is not found
Note
This function is idempotent - multiple calls have no effect if the registry is already initialized. The initialization state persists for the application lifetime.
Warning
This function must be called before accessing any framework components. Attempting to access components before initialization will result in empty or incomplete results.
Examples
Basic application startup:
>>> from framework.registry import initialize_registry, get_registry >>> >>> # Initialize during application startup >>> initialize_registry() >>> >>> # Now components are available >>> registry = get_registry() >>> capability = registry.get_capability("pv_address_finding")
Initialize without metadata export:
>>> # Skip JSON export for faster initialization >>> initialize_registry(auto_export=False)
Handle initialization errors:
>>> try: ... initialize_registry() ... print("Registry initialized successfully") ... except RegistryError as e: ... print(f"Registry initialization failed: {e}") ... # Handle missing components or configuration issues
Check initialization results:
>>> initialize_registry() >>> registry = get_registry() >>> stats = registry.get_stats() >>> print(f"Loaded {stats['capabilities']} capabilities")
See also
get_registry()
: Access the initialized registry instancereset_registry()
: Reset registry for testing or reconfigurationRegistryManager.initialize()
: Core initialization method called by this functionRegistryManager.export_registry_to_json()
: Export functionality used when auto_export=True
Registration Configuration#
Configuration Interface#
- class framework.registry.RegistryConfigProvider[source]#
Bases:
ABC
Abstract interface for application registry configuration.
All applications must implement this interface to provide their registry configuration in a standardized, type-safe manner. This interface eliminates naming ambiguity and ensures consistent registry patterns across all applications in the framework ecosystem.
The framework loads classes implementing this interface from each configured application’s registry module using the convention-based path: applications.{app_name}.registry
This design provides several key benefits:
Type Safety: All registry configurations are strongly typed
Convention-Based Loading: Standardized module path patterns
Validation: Automatic validation of registry structure
Extensibility: Easy to add new component types without breaking changes
Documentation: Self-documenting registry configurations
- Implementation Requirements:
Exactly one class per application registry module must implement this interface
The get_registry_config() method must return a complete RegistryConfig
All component registrations must use valid module paths and class names
Context type dependencies (provides/requires) must be consistent
The registry system will call get_registry_config() once during initialization and merge the returned configuration with the framework’s base registry. Applications can override framework components by using the same names.
- Raises:
RegistryError – If multiple implementations found in one module
RegistryError – If no implementation found in application registry module
NotImplementedError – If get_registry_config() is not implemented
Examples
Basic application registry:
>>> class MyAppRegistryProvider(RegistryConfigProvider): ... def get_registry_config(self) -> RegistryConfig: ... return RegistryConfig( ... capabilities=[ ... CapabilityRegistration( ... name="my_capability", ... module_path="applications.myapp.capabilities.my_capability", ... class_name="MyCapability", ... description="Application-specific functionality", ... provides=["MY_RESULTS"], ... requires=["INPUT_DATA"] ... ) ... ], ... context_classes=[ ... ContextClassRegistration( ... context_type="MY_RESULTS", ... module_path="applications.myapp.context_classes", ... class_name="MyResults" ... ) ... ] ... )
Advanced registry with services and data sources:
>>> class AdvancedAppRegistryProvider(RegistryConfigProvider): ... def get_registry_config(self) -> RegistryConfig: ... return RegistryConfig( ... capabilities=[...], ... context_classes=[...], ... data_sources=[ ... DataSourceRegistration( ... name="app_database", ... module_path="applications.myapp.data_sources.database", ... class_name="AppDatabaseProvider", ... description="Application-specific database access", ... health_check_required=True ... ) ... ], ... services=[ ... ServiceRegistration( ... name="data_processor", ... module_path="applications.myapp.services.processor", ... class_name="DataProcessorService", ... description="Multi-step data processing workflow", ... provides=["PROCESSED_DATA"], ... requires=["RAW_DATA"], ... internal_nodes=["validator", "transformer", "aggregator"] ... ) ... ] ... )
Note
The framework will merge application registries with the base framework registry, allowing applications to override framework components by using the same names.
Warning
Each application registry module must contain exactly one class implementing this interface. Multiple implementations or missing implementations will cause RegistryError during framework initialization.
See also
RegistryConfig
: Configuration structure returned by implementationsRegistryManager
: Manager that discovers and uses these providers Building Your First Capability : Complete application development guideAbstract Methods
- abstractmethod get_registry_config()[source]#
Get complete application registry configuration.
This method is called once during registry initialization to retrieve the complete component configuration for the application. The returned RegistryConfig will be merged with the framework’s base registry, allowing applications to extend or override framework functionality.
The configuration should include all components that the application provides: capabilities, context classes, data sources, services, and any other registered components. Components are loaded lazily using the module_path and class_name metadata provided in the registrations.
- Implementation Guidelines:
Return a complete RegistryConfig with all application components
Use descriptive names and clear documentation for all components
Ensure provides/requires relationships are consistent across components
Validate that all module paths and class names are correct
Consider component initialization order when defining dependencies
- Returns:
Complete registry configuration for this application including all capabilities, context classes, data sources, services, and other components that should be available in the framework
- Return type:
- Raises:
NotImplementedError – If not implemented by subclass (required by ABC)
ImportError – If any component module paths are invalid
AttributeError – If any component class names are not found
Note
This method is called exactly once during registry initialization. The framework caches the returned configuration, so dynamic changes after initialization are not supported.
Warning
All module paths must be importable and all class names must exist in their respective modules. Invalid paths will cause registry initialization to fail.
Examples
Minimal application configuration:
>>> def get_registry_config(self) -> RegistryConfig: ... return RegistryConfig( ... capabilities=[ ... CapabilityRegistration( ... name="hello_world", ... module_path="applications.myapp.capabilities.hello", ... class_name="HelloWorldCapability", ... description="Simple greeting capability", ... provides=["GREETING"], ... requires=[] ... ) ... ], ... context_classes=[ ... ContextClassRegistration( ... context_type="GREETING", ... module_path="applications.myapp.context_classes", ... class_name="GreetingContext" ... ) ... ] ... )
Complex application with all component types:
>>> def get_registry_config(self) -> RegistryConfig: ... return RegistryConfig( ... capabilities=[...], # Domain-specific capabilities ... context_classes=[...], # Data structures ... data_sources=[...], # External data providers ... services=[...], # Internal service graphs ... framework_prompt_providers=[...] # Custom prompts ... )
See also
RegistryConfig
: Structure of the returned configurationCapabilityRegistration
: Capability registration metadataContextClassRegistration
: Context class registration metadata Registry and Discovery : Component registration guide
- abstractmethod get_registry_config()[source]#
Get complete application registry configuration.
This method is called once during registry initialization to retrieve the complete component configuration for the application. The returned RegistryConfig will be merged with the framework’s base registry, allowing applications to extend or override framework functionality.
The configuration should include all components that the application provides: capabilities, context classes, data sources, services, and any other registered components. Components are loaded lazily using the module_path and class_name metadata provided in the registrations.
- Implementation Guidelines:
Return a complete RegistryConfig with all application components
Use descriptive names and clear documentation for all components
Ensure provides/requires relationships are consistent across components
Validate that all module paths and class names are correct
Consider component initialization order when defining dependencies
- Returns:
Complete registry configuration for this application including all capabilities, context classes, data sources, services, and other components that should be available in the framework
- Return type:
- Raises:
NotImplementedError – If not implemented by subclass (required by ABC)
ImportError – If any component module paths are invalid
AttributeError – If any component class names are not found
Note
This method is called exactly once during registry initialization. The framework caches the returned configuration, so dynamic changes after initialization are not supported.
Warning
All module paths must be importable and all class names must exist in their respective modules. Invalid paths will cause registry initialization to fail.
Examples
Minimal application configuration:
>>> def get_registry_config(self) -> RegistryConfig: ... return RegistryConfig( ... capabilities=[ ... CapabilityRegistration( ... name="hello_world", ... module_path="applications.myapp.capabilities.hello", ... class_name="HelloWorldCapability", ... description="Simple greeting capability", ... provides=["GREETING"], ... requires=[] ... ) ... ], ... context_classes=[ ... ContextClassRegistration( ... context_type="GREETING", ... module_path="applications.myapp.context_classes", ... class_name="GreetingContext" ... ) ... ] ... )
Complex application with all component types:
>>> def get_registry_config(self) -> RegistryConfig: ... return RegistryConfig( ... capabilities=[...], # Domain-specific capabilities ... context_classes=[...], # Data structures ... data_sources=[...], # External data providers ... services=[...], # Internal service graphs ... framework_prompt_providers=[...] # Custom prompts ... )
See also
RegistryConfig
: Structure of the returned configurationCapabilityRegistration
: Capability registration metadataContextClassRegistration
: Context class registration metadata Registry and Discovery : Component registration guide
RegistryConfig#
- class framework.registry.RegistryConfig(capabilities, context_classes, core_nodes=<factory>, data_sources=<factory>, services=<factory>, domain_analyzers=<factory>, execution_policy_analyzers=<factory>, framework_prompt_providers=<factory>, framework_exclusions=<factory>, initialization_order=<factory>)[source]#
Bases:
object
Complete registry configuration with all component metadata.
Contains the complete configuration for the framework registry including all component registrations and initialization ordering. Enhanced for LangGraph migration with support for decorators and advanced features.
Most fields are optional with sensible defaults to improve UX for applications. Applications typically only need to define capabilities, context_classes, and optionally data_sources and framework_prompt_providers.
- Parameters:
capabilities (list[CapabilityRegistration]) – Registration entries for domain capabilities
context_classes (list[ContextClassRegistration]) – Registration entries for context data classes
core_nodes (list[NodeRegistration]) – Registration entries for infrastructure nodes (optional)
data_sources (list[DataSourceRegistration]) – Registration entries for external data sources (optional)
services (list[ServiceRegistration]) – Registration entries for internal service graphs (optional)
domain_analyzers (list[DomainAnalyzerRegistration]) – Registration entries for domain analyzers (optional)
execution_policy_analyzers (list[ExecutionPolicyAnalyzerRegistration]) – Registration entries for execution policy analyzers (optional)
framework_prompt_providers (list[FrameworkPromptProviderRegistration]) – Registration entries for prompt providers (optional)
framework_exclusions (dict[str, list[str]]) – Framework component names to exclude by type (optional)
initialization_order (list[str]) – Component type initialization sequence (optional)
Component Lists
- capabilities: List[CapabilityRegistration]#
Registration entries for domain capabilities (required).
- context_classes: List[ContextClassRegistration]#
Registration entries for context data classes (required).
- core_nodes: List[NodeRegistration]#
Registration entries for infrastructure nodes (optional).
- data_sources: List[DataSourceRegistration]#
Registration entries for external data sources (optional).
- services: List[ServiceRegistration]#
Registration entries for internal service graphs (optional).
- capabilities: List[CapabilityRegistration]#
- context_classes: List[ContextClassRegistration]#
- core_nodes: List[NodeRegistration]#
- data_sources: List[DataSourceRegistration]#
- services: List[ServiceRegistration]#
- domain_analyzers: List[DomainAnalyzerRegistration]#
- execution_policy_analyzers: List[ExecutionPolicyAnalyzerRegistration]#
- framework_prompt_providers: List[FrameworkPromptProviderRegistration]#
- framework_exclusions: Dict[str, List[str]]#
- initialization_order: List[str]#
- __init__(capabilities, context_classes, core_nodes=<factory>, data_sources=<factory>, services=<factory>, domain_analyzers=<factory>, execution_policy_analyzers=<factory>, framework_prompt_providers=<factory>, framework_exclusions=<factory>, initialization_order=<factory>)#
Registration Classes#
Component Registration#
- class framework.registry.CapabilityRegistration(name, module_path, class_name, description, provides, requires, always_active=False, functional_node=None, example_usage='')[source]#
Bases:
object
Registration metadata for capabilities.
Defines the metadata required for lazy loading of capability classes that implement specific functionality for agent systems. Enhanced for LangGraph migration with support for convention-based decorators and advanced features.
- Parameters:
name (str) – Unique capability name for registration
module_path (str) – Python module path for lazy import
class_name (str) – Class name within the module
description (str) – Human-readable description of capability
provides (list[str]) – List of context types this capability produces
requires (list[str]) – List of context types this capability needs
always_active (bool) – Whether capability is always active (no classification needed), defaults to False
functional_node (str) – Name of the functional node for execution (from capability.node attribute)
example_usage (str) – Example of how this capability is used
Key Fields
- name: str#
Unique capability name for registration.
- module_path: str#
Python module path for lazy import.
- class_name: str#
Class name within the module.
- provides: List[str]#
Context types this capability produces.
- requires: List[str]#
Context types this capability needs as input.
- name: str#
- module_path: str#
- class_name: str#
- description: str#
- provides: List[str]#
- requires: List[str]#
- always_active: bool = False#
- functional_node: str = None#
- example_usage: str = ''#
- __init__(name, module_path, class_name, description, provides, requires, always_active=False, functional_node=None, example_usage='')#
- class framework.registry.ContextClassRegistration(context_type, module_path, class_name)[source]#
Bases:
object
Registration metadata for context data classes.
Defines the metadata required for lazy loading of context classes that represent structured data passed between capabilities.
- Parameters:
context_type (str) – String identifier for the context type (e.g., ‘PV_ADDRESSES’)
module_path (str) – Python module path for lazy import
class_name (str) – Class name within the module
Key Fields
- context_type: str#
String identifier for the context type (e.g., ‘PV_ADDRESSES’).
- module_path: str#
Python module path for lazy import.
- class_name: str#
Class name within the module.
- context_type: str#
- module_path: str#
- class_name: str#
- __init__(context_type, module_path, class_name)#
- class framework.registry.NodeRegistration(name, module_path, function_name, description)[source]#
Bases:
object
Registration metadata for infrastructure node functions.
Defines the metadata required for lazy loading of functional nodes.
- Parameters:
name (str) – Unique identifier for the node in the registry
module_path (str) – Python module path for lazy import
function_name (str) – Function name within the module (decorated with @infrastructure_node)
description (str) – Human-readable description of node functionality
Key Fields
- name: str#
Unique identifier for the node in the registry.
- module_path: str#
Python module path for lazy import.
- function_name: str#
Function name within the module (decorated with @infrastructure_node).
- name: str#
- module_path: str#
- function_name: str#
- description: str#
- __init__(name, module_path, function_name, description)#
- class framework.registry.DataSourceRegistration(name, module_path, class_name, description, health_check_required=True)[source]#
Bases:
object
Registration metadata for external data source providers.
Defines the metadata required for lazy loading of data source provider classes that provide access to external systems and databases.
- Parameters:
name (str) – Unique identifier for the data source in the registry
module_path (str) – Python module path for lazy import
class_name (str) – Class name within the module
description (str) – Human-readable description of data source
health_check_required (bool) – Whether provider requires health checking
Key Fields
- name: str#
Unique identifier for the data source in the registry.
- health_check_required: bool#
Whether provider requires health checking.
- name: str#
- module_path: str#
- class_name: str#
- description: str#
- health_check_required: bool = True#
- __init__(name, module_path, class_name, description, health_check_required=True)#
- class framework.registry.ServiceRegistration(name, module_path, class_name, description, provides=<factory>, requires=<factory>, internal_nodes=<factory>)[source]#
Bases:
object
Registration metadata for internal service graphs.
Services are separate LangGraph graphs that can be called by capabilities without interfering with the main graph routing. Each service manages its own internal node flow and returns control to the calling capability.
- Parameters:
name (str) – Unique identifier for the service in the registry
module_path (str) – Python module path for lazy import
class_name (str) – Service class name within the module
description (str) – Human-readable description of service functionality
provides (list[str]) – List of context types this service produces
requires (list[str]) – List of context types this service needs
internal_nodes (list[str]) – List of node names internal to this service
Key Fields
- internal_nodes: List[str]#
List of node names internal to this service.
- name: str#
- module_path: str#
- class_name: str#
- description: str#
- provides: List[str]#
- requires: List[str]#
- internal_nodes: List[str]#
- __init__(name, module_path, class_name, description, provides=<factory>, requires=<factory>, internal_nodes=<factory>)#
Specialized Registration#
- class framework.registry.FrameworkPromptProviderRegistration(application_name, module_path, description, prompt_builders=<factory>)[source]#
Bases:
object
Registration metadata for application-specific prompt providers.
Defines the metadata required for dependency injection of application-specific prompt builders. Uses the professional pattern of “start with defaults, override specific components” - applications only declare what they want to customize, everything else uses framework defaults.
- Parameters:
application_name (str) – Application identifier (e.g., ‘als_expert’)
module_path (str) – Python module path for lazy import
description (str) – Human-readable description of prompt provider
prompt_builders (dict[str, str]) – Mapping of prompt types to override with custom builder classes
Examples
Basic application override:
FrameworkPromptProviderRegistration( application_name="als_expert", module_path="applications.als_expert.framework_prompts", description="ALS-specific prompt customizations", prompt_builders={ "orchestrator": "ALSOrchestratorPromptBuilder", "memory_extraction": "ALSMemoryExtractionPromptBuilder" # time_range_parsing not listed = uses framework default } )
Key Fields
- application_name: str#
Application identifier (e.g., ‘als_expert’).
- prompt_builders: Dict[str, str]#
Mapping of prompt types to override with custom builder classes.
- application_name: str#
- module_path: str#
- description: str#
- prompt_builders: Dict[str, str]#
- __init__(application_name, module_path, description, prompt_builders=<factory>)#
- class framework.registry.ExecutionPolicyAnalyzerRegistration(name, module_path, class_name, description, priority=50)[source]#
Bases:
object
Registration metadata for configurable execution policy analyzers.
Defines the metadata required for lazy loading of execution policy analyzer classes that make execution mode and approval decisions based on code analysis.
- Parameters:
name (str) – Unique identifier for the policy analyzer in the registry
module_path (str) – Python module path for lazy import
class_name (str) – Class name within the module
description (str) – Human-readable description of policy analyzer
priority (int) – Analysis priority (lower numbers = higher priority)
- name: str#
- module_path: str#
- class_name: str#
- description: str#
- priority: int = 50#
- __init__(name, module_path, class_name, description, priority=50)#
- class framework.registry.DomainAnalyzerRegistration(name, module_path, class_name, description, priority=50)[source]
Bases:
object
Registration metadata for configurable domain analyzers.
Defines the metadata required for lazy loading of domain analyzer classes that analyze generated code for domain-specific patterns and operations.
- Parameters:
name (str) – Unique identifier for the domain analyzer in the registry
module_path (str) – Python module path for lazy import
class_name (str) – Class name within the module
description (str) – Human-readable description of domain analyzer
priority (int) – Analysis priority (lower numbers = higher priority)
- name: str
- module_path: str
- class_name: str
- description: str
- priority: int = 50
- __init__(name, module_path, class_name, description, priority=50)
Registry Architecture#
The registry system uses a two-tier architecture with configuration-driven application loading:
Framework Registry: Core infrastructure loaded from framework.registry.registry
Application Registries: Domain-specific components from applications.{app}.registry
(applications must be listed in global configuration)
Initialization Order:
Components are initialized in strict dependency order:
Context classes (required by capabilities)
Data sources (required by capabilities)
Core nodes (infrastructure components)
Services (internal LangGraph service graphs)
Capabilities (domain-specific functionality)
Framework prompt providers (application-specific prompts)
Lazy Loading:
All components use lazy loading to prevent circular import issues. Components are imported and instantiated only during the initialization phase, not at module load time.
Registry Export System#
The registry provides comprehensive export functionality for external tool integration and debugging:
Automatic Export:
Registry metadata is automatically exported during initialize_registry()
when auto_export=True
(default).
Manual Export:
Use RegistryManager.export_registry_to_json()
for on-demand export of registry state.
Export Configuration:
Default export directory is configured via file_paths.registry_exports_dir
in config.yml
(defaults to _agent_data/registry_exports/
).
Export Structure: Exports create standardized JSON files containing capability definitions, context types, and metadata suitable for consumption by external tools, execution plan editors, and debugging utilities.
Integration Pattern: The export system enables air-gapped integration where external tools need component metadata but cannot execute live Python code.
See also
- Base Components
Base component classes and decorators for registered components
- State and Context Management
State and context management for component data
- Configuration System
Configuration system used by registry initialization
- Registry and Discovery
Complete guide to registry system and component discovery