LoopX Extension and Capability Registration Patterns Explained

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 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 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 (lines 35-68), register_provider() validates these fields before storage.

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 (lines 70-106).

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 (lines 114-138), register_implementation() links the capability to a provider and protocol version.

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.

Scaffolding New Extensions

The scaffold_extension() function in loopx/extensions/scaffold.py (lines 84-143) generates a minimal package structure:

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: Manifest with provider and capability declarations
  • 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 (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 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 drives capability registration. The [capabilities] section enumerates records, and the [provider] block defines the provider:


# 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

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


# 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) Core registry with validation and linking logic
[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) CLI queries (loopx capability list)
[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) Extension lifecycle CLI
[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
  • 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →