# How to Extend LoopX Functionality: A Complete Guide to Building Custom Extensions

> Learn how to extend LoopX functionality with custom extensions. Build new features using LoopX's modular system and a simple provider presentation manifest structure.

- Repository: [huangruiteng/loopx](https://github.com/huangruiteng/loopx)
- Tags: how-to-guide
- Published: 2026-08-15

---

**LoopX uses a modular extension system where you create a package under `loopx/extensions/` containing a provider (business logic), presentation (UI), and manifest ([`extension.toml`](https://github.com/huangruiteng/loopx/blob/main/extension.toml)) to register new capabilities without modifying core code.**

LoopX is designed around a capability-driven architecture that makes extending functionality straightforward. Whether you need to add a new bot integration, custom dashboard, or periodic report, the extension system in `huangruiteng/loopx` provides a standardized pattern for safely adding features.

## Understanding the LoopX Extension Architecture

All extensions live under `loopx/extensions/` and follow a four-component contract. This location is intentional—extensions are provider-neutral capabilities consumable by any LoopX host. The [`DESIGN.md`](https://github.com/huangruiteng/loopx/blob/main/DESIGN.md) file documents this "Capability And Extension Placement" decision in detail.

### Core Extension Components

| Component | Purpose | Location |
|-----------|---------|----------|
| **Provider** | Business logic implementation | `loopx/extensions/<extension>/provider.py` |
| **Presentation** | UI rendering declarations | `loopx/extensions/<extension>/presentation/*.py` |
| **Manifest** | Runtime registration and metadata | `loopx/extensions/<extension>/extension.toml` |
| **Execution Envelope** | Safe execution wrapper | [`loopx/extensions/execution_envelope.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/execution_envelope.py) |

At startup, [`loopx/extensions/runtime.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/runtime.py) scans the extensions directory, parses each [`extension.toml`](https://github.com/huangruiteng/loopx/blob/main/extension.toml) via [`loopx/extensions/manifest.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/manifest.py), and wires components together automatically.

## Creating a New LoopX Extension: Step-by-Step

### Step 1: Scaffold the Extension Structure

Use the built-in scaffold utility to generate the boilerplate directory layout.

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

create_extension(
    name="my_new_feature",
    description="Demo extension that greets the user",
    required_capabilities=["lark"]
)

```

The [`scaffold.py`](https://github.com/huangruiteng/loopx/blob/main/scaffold.py) module handles directory creation and generates placeholder files following LoopX conventions.

### Step 2: Implement the Provider

The provider contains your core business logic. All provider code runs inside [`execution_envelope.py`](https://github.com/huangruiteng/loopx/blob/main/execution_envelope.py), which guarantees isolation, timeout handling, and consistent error reporting.

```python

# loopx/extensions/my_new_feature/provider.py

import json
from loopx.extensions.execution_envelope import safe_execute

def greet_user(name: str) -> dict:
    """Business logic that returns a greeting message."""
    return {"text": f"Hello, {name}! 👋"}

def run(params: dict) -> dict:
    """Safe entry point for the runtime."""
    return safe_execute(lambda: greet_user(params["name"]))

```

The `safe_execute` wrapper in [`execution_envelope.py`](https://github.com/huangruiteng/loopx/blob/main/execution_envelope.py) ensures your code runs with resource limits and proper exception handling.

### Step 3: Declare the Presentation Layer

UI code lives separately in `presentation/` and only consumes public-safe projection data. This separation keeps UI concerns out of business logic.

```python

# loopx/extensions/my_new_feature/presentation/message_card.py

def render(payload: dict) -> dict:
    """Translate provider output to a Lark message card."""
    return {
        "type": "interactive",
        "header": {"title": {"content": "Greeting"}},
        "elements": [{"tag": "div", "text": {"content": payload["text"]}}]
    }

```

### Step 4: Register with the Manifest

The [`extension.toml`](https://github.com/huangruiteng/loopx/blob/main/extension.toml) file is the single source of truth for your extension's identity and dependencies.

```toml

# loopx/extensions/my_new_feature/extension.toml

id = "my_new_feature"
description = "Demo extension that greets the user"
requires = ["lark"]
provider = "provider.run"
presentation = ["presentation/message_card.render"]

```

LoopX reads this manifest via [`loopx/extensions/manifest.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/manifest.py). The `requires` field declares dependencies on existing capabilities, enabling the runtime to resolve extension ordering.

## Running Your Extension

Once files are in place, LoopX automatically discovers the extension on next startup.

**Via CLI:**

```bash
loopx my_new_feature --name Alice

```

**Programmatically via the LoopX SDK:**

Your extension becomes available through the standard LoopX programmatic interface once loaded.

## Key Architectural Guarantees

- **Capability-driven placement**: Extensions under `loopx/extensions/` are reusable across any LoopX host environment
- **Execution safety**: [`execution_envelope.py`](https://github.com/huangruiteng/loopx/blob/main/execution_envelope.py) provides resource isolation and error consistency
- **Presentation separation**: UI code cannot access internal provider state, only projection data
- **Manifest-driven registration**: Single file controls identity, dependencies, and activation hooks

## Reference Implementations

Study these existing extensions for patterns:

- **Lark integration**: [`loopx/extensions/lark/provider.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/lark/provider.py) and [`loopx/extensions/lark/presentation/message_card.py`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/lark/presentation/message_card.py) demonstrate a complete bot integration
- **Periodic reports**: [`loopx/extensions/openviking_periodic_report/extension.toml`](https://github.com/huangruiteng/loopx/blob/main/loopx/extensions/openviking_periodic_report/extension.toml) shows advanced manifest configuration

## Summary

- **LoopX extensions** live in `loopx/extensions/` and follow a four-part structure: provider, presentation, manifest, and execution envelope
- **Use [`scaffold.py`](https://github.com/huangruiteng/loopx/blob/main/scaffold.py)** to generate boilerplate quickly with `create_extension()`
- **Implement business logic** in [`provider.py`](https://github.com/huangruiteng/loopx/blob/main/provider.py) and wrap with `safe_execute()` from [`execution_envelope.py`](https://github.com/huangruiteng/loopx/blob/main/execution_envelope.py)
- **Separate UI concerns** in `presentation/` modules that only consume projection data
- **Register everything** in [`extension.toml`](https://github.com/huangruiteng/loopx/blob/main/extension.toml); [`runtime.py`](https://github.com/huangruiteng/loopx/blob/main/runtime.py) and [`manifest.py`](https://github.com/huangruiteng/loopx/blob/main/manifest.py) handle discovery automatically
- **Invoke extensions** via CLI (`loopx <extension>`) or programmatically after automatic loading

## Frequently Asked Questions

### What happens if my provider code throws an exception?

The `safe_execute()` wrapper in [`execution_envelope.py`](https://github.com/huangruiteng/loopx/blob/main/execution_envelope.py) catches exceptions, enforces timeout limits, and returns standardized error responses. Your extension cannot crash the LoopX runtime.

### Can my extension depend on other extensions?

Yes. Declare dependencies in [`extension.toml`](https://github.com/huangruiteng/loopx/blob/main/extension.toml) using the `requires` field. The manifest parser in [`manifest.py`](https://github.com/huangruiteng/loopx/blob/main/manifest.py) resolves capability dependencies before activating your extension.

### Where should I put configuration for my extension?

Store configuration in [`extension.toml`](https://github.com/huangruiteng/loopx/blob/main/extension.toml) as key-value pairs, or use environment variables read within your provider. The manifest supports arbitrary configuration sections that [`manifest.py`](https://github.com/huangruiteng/loopx/blob/main/manifest.py) exposes to your runtime context.

### How do I update an existing extension without restarting LoopX?

LoopX loads extensions at startup. To hot-reload during development, use the development mode flag or restart the runtime. Production deployments should follow standard deployment practices for your hosting environment.