# Extension Points in semantica.core for Custom Plugins: A Developer's Guide

> Discover semantica.core extension points PluginRegistry MethodRegistry and ConfigManager to build custom plugins dynamically without altering framework code. Enhance semantica with your own integrations.

- Repository: [Semantica /semantica](https://github.com/semantica-agi/semantica)
- Tags: developer-guide
- Published: 2026-08-21

---

**The `semantica.core` package exposes three primary extension points—`PluginRegistry`, `MethodRegistry`, and `ConfigManager`—that enable dynamic discovery, registration, and configuration of custom plugins without modifying framework internals.**

The `semantica-agi/semantica` framework is designed around a modular architecture that separates core orchestration logic from extensible components. Developers can augment knowledge-graph pipelines, ingestion workflows, and processing steps through well-defined APIs in the `semantica.core` module. These extension points provide version-aware lifecycle management, dependency resolution, and environment-specific configuration handling.

## PluginRegistry: Dynamic Plugin Discovery and Lifecycle Management

The **`PluginRegistry`** class in [`semantica/core/plugin_registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/plugin_registry.py) serves as the primary mechanism for managing custom ingestors, parsers, and exporters. It handles discovery, versioning, dependency resolution, and instance caching.

### Directory-Based Discovery

At initialization, `PluginRegistry` walks the directories specified in the `plugin_paths` parameter to build a catalog of available plugins. This auto-discovery mechanism scans for plugin classes without requiring manual registration.

```python
from semantica.core import PluginRegistry

# Auto-discover plugins under ./plugins

registry = PluginRegistry(plugin_paths=["./plugins"])

```

### Manual Registration and Metadata

For explicit control, use `register_plugin()` to bind a class to a specific name along with version and capability metadata. The system uses the `PluginInfo` dataclass to track dependencies and features.

```python
class MyIngestor:
    def initialize(self):
        print("MyIngestor initialized")
    
    def execute(self, data):
        return {"ingested": True, "data": data}

registry.register_plugin(
    "my_ingestor",
    MyIngestor,
    version="0.1.0",
    description="Demo ingestor for CSV files",
    capabilities=["ingest"],
)

```

### Loading and Initialization

The `load_plugin(name, **config)` method resolves dependencies, instantiates the plugin, invokes its `initialize()` method, and caches the instance for reuse.

```python
plugin = registry.load_plugin("my_ingestor")
result = plugin.execute({"file": "sample.csv"})

```

## MethodRegistry: Custom Orchestration Methods

The **`MethodRegistry`** (exposed as the global `method_registry` in [`semantica/core/registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/registry.py)) allows binding custom Python callables to named tasks. This enables user-defined pipeline steps that the high-level `Semantica` orchestrator can invoke by name.

### Registering Task-Specific Methods

Use `method_registry.register(task, name, func)` to associate a function with a specific task category. Valid tasks include `"knowledge_base"`, `"pipeline"`, or custom categories.

```python
from semantica.core.registry import method_registry

def fast_kb_builder(sources, **kwargs):
    print("Running fast builder on:", sources)
    return {"status": "quick-kb-built"}

method_registry.register("knowledge_base", "fast", fast_kb_builder)

```

### Runtime Method Resolution

Retrieve and execute registered methods using `method_registry.get(task, name)`. This lookup mechanism decouples orchestration logic from implementation details.

```python
builder = method_registry.get("knowledge_base", "fast")
builder(["doc1.pdf", "doc2.pdf"])

```

## ConfigManager: Centralized Configuration with Plugin Hooks

The **`ConfigManager`** in [`semantica/core/config_manager.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/config_manager.py) provides deep-merge configuration loading with validation and environment-variable overrides. Plugins can read custom configuration sections through this centralized system.

### Loading and Accessing Configuration

Use `load_from_file()` to parse YAML configurations, then access plugin-specific sections via the config object. The manager automatically processes `SEMANTICA_` prefixed environment variables.

```python
from semantica.core import ConfigManager

cfg = ConfigManager()
config = cfg.load_from_file("config.yaml")

# Access nested plugin configuration

option_value = config.get("my_plugin.option_a")

```

### Integration with Plugin Initialization

When loading plugins, pass configuration data to the plugin constructor through the `load_plugin()` method's keyword arguments.

```python
registry = PluginRegistry(plugin_paths=["./plugins"])
my_plugin = registry.load_plugin("my_plugin")

# Configuration is available via the plugin instance

print(my_plugin.config)

```

## Key Implementation Files

Understanding the source structure helps when debugging or extending these APIs:

- **[`semantica/core/plugin_registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/plugin_registry.py)** – Implements the full plugin lifecycle including discovery, dependency handling, and caching mechanisms.
- **[`semantica/core/registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/registry.py)** – Contains the `MethodRegistry` class and global `method_registry` instance for orchestration method management.
- **[`semantica/core/config_manager.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/config_manager.py)** – Handles configuration parsing, deep-merging, and environment variable interpolation.
- **[`semantica/core/__init__.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/__init__.py)** – Re-exports the public API including `PluginRegistry` and related classes.

## Summary

- **`PluginRegistry`** provides dynamic discovery, manual registration, version-aware loading, and lifecycle management for custom components.
- **`MethodRegistry`** enables task-based registration of custom orchestration methods accessible by name throughout the framework.
- **`ConfigManager`** offers deep-merge configuration loading with environment variable support, allowing plugins to define custom settings sections.
- All extension points support dependency resolution and instance caching to optimize runtime performance.
- Source implementations reside in [`semantica/core/plugin_registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/plugin_registry.py), [`semantica/core/registry.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/registry.py), and [`semantica/core/config_manager.py`](https://github.com/semantica-agi/semantica/blob/main/semantica/core/config_manager.py).

## Frequently Asked Questions

### How does auto-discovery differ from manual plugin registration?

Auto-discovery scans `plugin_paths` directories at `PluginRegistry` initialization to find plugin classes automatically. Manual registration via `register_plugin()` gives explicit control over names, versions, and capabilities. Both methods result in the same internal metadata stored in `PluginInfo` dataclasses, but manual registration allows you to override discovered plugins or register classes outside the standard directory structure.

### What is the difference between PluginRegistry and MethodRegistry?

`PluginRegistry` manages full plugin classes with lifecycle methods like `initialize()` and `execute()`, handling instantiation and dependency resolution. `MethodRegistry` manages individual Python functions bound to task names for orchestration purposes. Use `PluginRegistry` for complex components requiring state and configuration; use `MethodRegistry` for lightweight processing functions that the orchestrator calls by name.

### Can plugins access their own configuration sections automatically?

Yes. When loading a plugin via `registry.load_plugin("name")`, the `ConfigManager` can pass plugin-specific configuration to the plugin constructor. Plugins receive their configuration section through the instance's `config` attribute, allowing them to read settings defined in YAML files or overridden via `SEMANTICA_` environment variables without directly accessing the global configuration object.

### How does version management work for custom plugins?

The `register_plugin()` method accepts a `version` parameter stored in the `PluginInfo` metadata. The registry uses this information for dependency resolution when plugins declare dependencies on other plugins. While the current implementation primarily tracks versions for compatibility checking, future framework updates may support loading specific version ranges or enforcing semantic versioning constraints during the resolution phase.