# LoopX Extension and Capability Registration Patterns Explained

> Understand LoopX extension and capability registration patterns. Discover how LoopX uses TOML manifests and a CapabilityRegistry for runtime validation and linking of providers and implementations.

- Repository: [huangruiteng/loopx](https://github.com/huangruiteng/loopx)
- Tags: deep-dive
- Published: 2026-08-07

---

**LoopX uses a two-layer registration system where extensions declare capabilities in TOML manifests and the `CapabilityRegistry` validates and links providers, capability records, and implementations at runtime.**

The [huangruiteng/loopx](https://github.com/huangruiteng/loopx) repository implements a modular architecture that separates **capability discovery** from **extension lifecycle management**. This guide covers both patterns with implementation details from the source code.

## What Is a Capability in LoopX?

A **capability** represents a concrete feature that users can interact with—such as a finance connector or data processor. Capabilities are owned by **providers**, which can be `builtin` (core LoopX) or `extension` (third-party). The `CapabilityRegistry` in [`loopx/capabilities/registry.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/capabilities/registry.py) maintains three mutable tables:

- `providers`: Logical sources that declare capabilities
- `records`: Capability definitions with metadata
- `implementations`: Protocol bindings between capabilities and providers

## Capability Registration Pattern

The capability registration pattern follows a three-step validation chain in `CapabilityRegistry`. Each step enforces required fields and origin/visibility rules.

### Step 1: Register the Provider

A provider must contain `id`, `origin`, and four boolean state flags. In [`loopx/capabilities/registry.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/capabilities/registry.py) (lines 35-68), `register_provider()` validates these fields before storage.

```python
from loopx.capabilities.registry import CapabilityRegistry

registry = CapabilityRegistry()

provider = {
    "id": "finance",
    "origin": "extension",  # or "builtin"

    "declared": True,
    "installed": True,
    "enabled": True,
    "ready": True,
}
registry.register_provider(provider)

```

The `origin` field distinguishes core LoopX functionality from third-party extensions. The `ready` flag indicates whether the provider's dependencies are satisfied.

### Step 2: Register the Capability Record

Capability records are validated against `REQUIRED_CAPABILITY_FIELDS` (`id`, `title`, `status`, `user_value`, `next_real_step`). Public capabilities require additional fields: `real_world_anchor` and `entry_command`. See [`loopx/capabilities/registry.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/capabilities/registry.py) (lines 70-106).

```python
capability = {
    "id": "finance_connector",
    "title": "Finance Connector",
    "status": "stable",  # "stable", "beta", or "experimental"

    "user_value": "connect to financial data APIs",
    "next_real_step": "run",  # guides the user workflow

    "origin": "extension",
    "visibility": "public",  # "public" or "internal"

    "provider_id": "finance",
    "real_world_anchor": "https://finance.example.com",
    "entry_command": "loopx finance connect",
}
registry.register_capability(capability)

```

The `next_real_step` field determines what action LoopX prompts the user to take after discovery. The `entry_command` provides a CLI entry point for public capabilities.

### Step 3: Register the Implementation

Implementations bind capabilities to concrete protocols. In [`loopx/capabilities/registry.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/capabilities/registry.py) (lines 114-138), `register_implementation()` links the capability to a provider and protocol version.

```python
impl = {
    "capability_id": "finance_connector",
    "provider_id": "finance",
    "protocol": "finance_extension_v0",  # arbitrary protocol identifier

}
registry.register_implementation(impl)

```

Multiple implementations can exist for the same capability, allowing protocol versioning or alternative backends.

## Extension Registration Pattern

Extensions are standalone Python packages registered through CLI commands and managed by the runtime system in [`loopx/extensions/runtime.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/runtime.py).

### Scaffolding New Extensions

The `scaffold_extension()` function in [`loopx/extensions/scaffold.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/scaffold.py) (lines 84-143) generates a minimal package structure:

```python
from loopx.extensions.scaffold import scaffold_extension

result = scaffold_extension(
    "my_extension",
    destination="packages/my_extension",
    version="0.1.0",
    execute=True,  # False for dry-run preview

)

# Returns: {"status": "success", "next_commands": [...]}

```

The scaffold creates:
- [`extension.toml`](https://github.com/huangruiteng/loopx/blob/main/extension.toml): Manifest with provider and capability declarations
- [`pyproject.toml`](https://github.com/huangruiteng/loopx/blob/main/pyproject.toml): Poetry-based Python package configuration
- `src/`: Source stub with CLI entry point
- `examples/`: Request/response schema samples

### CLI Registration Commands

The `register_extension_commands()` function in [`loopx/cli_commands/extension.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/cli_commands/extension.py) (lines 88-152) adds sub-commands under `loopx extension`:

| Command | Purpose |
|---------|---------|
| `init` | Preview or create extension scaffold |
| `install` | Validate manifest, run doctor checks, persist state |
| `upgrade` | Update to new manifest version |
| `enable` / `disable` | Toggle provider `enabled` flag |
| `rollback` | Revert to prior manifest revision |
| `run` | Invoke standalone extension with JSON payload |

All commands support `--execute` for real effects; without it, they print planned actions for validation.

### Runtime Handling

The extension runtime in [`loopx/extensions/runtime.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/runtime.py) provides three core operations:

- **`install_extension()`**: Validates manifest, updates `default_extension_state_file`, and calls `CapabilityRegistry.register_provider()`, `register_capability()`, and `register_implementation()` for each declared capability
- **`enable_extension()` / `disable_extension()`**: Flips provider state flags
- **`run_standalone_extension()`**: Loads `src/<module>/cli.py` and forwards JSON request payload

These helpers are invoked from `handle_extension_command()` (lines 75-184).

## How Extension and Capability Patterns Interact

When an extension is installed, its [`extension.toml`](https://github.com/huangruiteng/loopx/blob/main/extension.toml) drives capability registration. The `[capabilities]` section enumerates records, and the `[provider]` block defines the provider:

```python

# Parsed from extension.toml by install_extension()

registry = CapabilityRegistry()

registry.register_provider(provider_record)  # from [provider]

for cap in manifest["capabilities"]:
    registry.register_capability(cap)
    for impl in cap.get("implementations", []):
        registry.register_implementation(impl)

```

Built-in capabilities follow the identical path, except with `origin: "builtin"` and manifests located in core LoopX packages. This uniform treatment allows LoopX to handle built-in and third-party features identically.

## Complete Registration Example

```python
from loopx.capabilities.registry import CapabilityRegistry

registry = CapabilityRegistry()

# 1. Register provider

registry.register_provider({
    "id": "analytics",
    "origin": "extension",
    "declared": True,
    "installed": True,
    "enabled": True,
    "ready": True,
})

# 2. Register capability

registry.register_capability({
    "id": "real_time_dashboard",
    "title": "Real-Time Dashboard",
    "status": "stable",
    "user_value": "visualize live data streams",
    "next_real_step": "enable",
    "origin": "extension",
    "visibility": "public",
    "provider_id": "analytics",
    "real_world_anchor": "https://analytics.example.com",
    "entry_command": "loopx analytics dashboard",
})

# 3. Register implementation

registry.register_implementation({
    "capability_id": "real_time_dashboard",
    "provider_id": "analytics",
    "protocol": "analytics_grpc_v2",
})

# 4. Retrieve enriched record

dashboard = registry.get("real_time_dashboard")
print(dashboard["provider"]["enabled"])  # True

print(dashboard["implementations"])      # List of protocol bindings

```

## CLI Workflow for Extension Management

```bash

# Scaffold extension (dry-run preview)

loopx extension init my_analytics --destination packages/my_analytics

# Create files on disk

loopx extension init my_analytics --destination packages/my_analytics --execute

# Install and register capabilities

loopx extension install --manifest packages/my_analytics/extension.toml --execute

# Enable if not auto-enabled

loopx extension enable my_analytics --execute

# Run with sample request

loopx extension run my_analytics --input-json packages/my_analytics/examples/request.json --execute

```

## Key Source Files

| File | Role |
|------|------|
| [[`loopx/capabilities/registry.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/capabilities/registry.py)](https://github.com/huangruiteng/loopx/blob/main/loopx/capabilities/registry.py) | Core registry with validation and linking logic |
| [[`loopx/capabilities/catalog.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/capabilities/catalog.py)](https://github.com/huangruiteng/loopx/blob/main/loopx/capabilities/catalog.py) | Manifest parsing for capability definitions |
| [[`loopx/cli_commands/capability.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/cli_commands/capability.py)](https://github.com/huangruiteng/loopx/blob/main/loopx/cli_commands/capability.py) | CLI queries (`loopx capability list`) |
| [[`loopx/extensions/scaffold.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/scaffold.py)](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/scaffold.py) | Extension package generator |
| [[`loopx/cli_commands/extension.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/cli_commands/extension.py)](https://github.com/huangruiteng/loopx/blob/main/loopx/cli_commands/extension.py) | Extension lifecycle CLI |
| [[`loopx/extensions/runtime.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/runtime.py)](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/runtime.py) | State persistence and execution |

## Summary

- **Capability registration** uses `CapabilityRegistry` with three validated tables: providers, records, and implementations
- **Extension registration** combines scaffolding, CLI commands, and runtime state management in [`loopx/extensions/runtime.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/runtime.py)
- Extensions declare capabilities in TOML manifests; the install flow automatically registers them with the registry
- Both `builtin` and `extension` origins follow identical data models, enabling uniform handling
- All registration calls occur at runtime when manifests are loaded, not at import time

## Frequently Asked Questions

### What is the difference between a provider and a capability in LoopX?

A **provider** is a logical source (builtin or extension) that can declare multiple **capabilities**. The provider tracks installation and enablement state, while a capability describes a concrete feature with user-facing metadata like `user_value` and `entry_command`. Multiple capabilities can share one provider.

### How does LoopX validate capability manifests?

The `CapabilityRegistry` enforces validation in three stages. `register_provider()` checks required origin and state flags (lines 35-68). `register_capability()` validates against `REQUIRED_CAPABILITY_FIELDS` and enforces public capability rules (lines 70-106). `register_implementation()` verifies capability-provider linkage (lines 114-138).

### Can I register capabilities without using the extension system?

Yes. Direct programmatic registration works by instantiating `CapabilityRegistry` and calling `register_provider()`, `register_capability()`, and `register_implementation()`. This is how built-in capabilities are registered—without an extension manifest, using `origin: "builtin"`.

### What happens when I disable an extension?

The `disable_extension()` runtime helper flips the provider's `enabled` flag to `False`. Capability lookups via `registry.get()` still return the record, but the enriched provider state shows `enabled: False`. The implementation bindings remain registered; only the provider state changes.