> ## Documentation Index
> Fetch the complete documentation index at: https://docs.noxus.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugin Architecture

> How the Noxus plugin system works — from the Plugin Server to node execution

Noxus uses a **plugin server** architecture that runs plugin code in isolated processes, separate from the core platform. This keeps the platform stable while letting plugins use any dependencies and run arbitrary logic.

## High-level overview

```mermaid theme={null}
graph LR
    subgraph Platform
        BE[Noxus Backend]
        W[Worker]
    end

    subgraph PluginServer["Plugin Server"]
        PS[Plugin Orchestrator]
        E1[UV Engine]
    end

    subgraph Plugins["Running Plugins"]
        P1["Plugin A (FastAPI)"]
        P2["Plugin B (FastAPI)"]
    end

    BE -- "install / reconcile" --> PS
    W -- "execute node" --> PS
    PS -- "forward request" --> P1
    PS -- "forward request" --> P2
    E1 -- "manages" --> P1
    E1 -- "manages" --> P2
    PS --> E1
```

The **Noxus Backend** manages plugin records (install, uninstall, status). The **Worker** calls plugin nodes during workflow execution. The **Plugin Server** sits between them and the actual plugin processes, handling lifecycle management and request forwarding.

## Plugin Server

The Plugin Server is a standalone FastAPI service that orchestrates all plugin instances. It:

* **Installs** plugins from various sources (Git repos, uploads, marketplace)
* **Starts** each plugin as an isolated process with its own Python environment
* **Forwards** execution requests from the platform to the correct plugin process
* **Reports** status back to the platform via webhooks
* **Reconciles** desired state with actual state on startup and periodically

### Execution engines

The Plugin Server uses an engine abstraction to run plugins. Currently, the **UV Process Engine** is the primary engine:

```mermaid theme={null}
graph TD
    PS[Plugin Server] --> Engine[UV Process Engine]
    Engine --> |"uv venv + install"| Env1[Plugin A venv]
    Engine --> |"uv venv + install"| Env2[Plugin B venv]
    Env1 --> |"noxus plugin serve"| Proc1["Process :auto-port"]
    Env2 --> |"noxus plugin serve"| Proc2["Process :auto-port"]
```

Each plugin gets its own virtual environment created by `uv`. The engine runs `noxus plugin serve` inside that environment, which starts a FastAPI server on an auto-assigned port. The engine reads the port from stdout and forwards all subsequent requests to that address.

### Reconciliation

On startup, the Plugin Server reconciles with the platform to ensure running plugins match the desired state:

```mermaid theme={null}
stateDiagram-v2
    [*] --> NotOnServer: Plugin not running
    [*] --> OnServer: Plugin running

    NotOnServer --> Install: status != UNINSTALLING
    NotOnServer --> MarkUninstalled: status == UNINSTALLING

    OnServer --> NoAction: RUNNING / INSTALLING
    OnServer --> Uninstall: UNINSTALLING
    OnServer --> Restart: ERROR
```

The platform sends the full list of desired plugins with their expected status. The Plugin Server compares this against its running processes and takes the appropriate action — install, restart, uninstall, or do nothing.

## Plugin lifecycle

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Platform as Noxus Backend
    participant PS as Plugin Server
    participant Engine as UV Engine

    User->>Platform: Install plugin (git URL)
    Platform->>Platform: Create plugin record (INSTALLING)
    Platform->>PS: POST /plugins/{id}/install
    PS->>PS: Download source
    PS->>Engine: Install dependencies (uv)
    Engine->>Engine: Create venv, install deps
    PS->>Engine: Start plugin process
    Engine->>Engine: noxus plugin serve --port 0
    Engine-->>PS: Running on port N
    PS->>Platform: Webhook: status=RUNNING + manifest
    Platform->>Platform: Register nodes & integrations
```

### Status flow

Plugins go through these statuses:

| Status           | Meaning                                          |
| ---------------- | ------------------------------------------------ |
| `installing`     | Being downloaded and set up                      |
| `running`        | Healthy and serving requests                     |
| `missing_config` | Needs configuration before it can work           |
| `restarting`     | Being restarted (after update or error recovery) |
| `error`          | Failed — will be retried on next reconciliation  |
| `uninstalling`   | Being removed                                    |
| `uninstalled`    | Fully removed                                    |

## Plugin sources

Plugins can be installed from multiple sources:

| Source          | Use case                                                                                                       |
| --------------- | -------------------------------------------------------------------------------------------------------------- |
| **Git**         | Point to a Git repository (public or private with token). Supports branch, commit, and subdirectory targeting. |
| **Upload**      | Upload a `.tar.gz` package directly through the UI.                                                            |
| **Marketplace** | Install from the official [Noxus Plugins repository](https://github.com/Noxus-AI/noxus-plugins).               |
| **Local**       | Copy from a local directory (development only).                                                                |

## How nodes execute through plugins

When a workflow runs a node that belongs to a plugin, here's what happens:

```mermaid theme={null}
sequenceDiagram
    participant W as Worker
    participant Core as Spotflow Core
    participant PS as Plugin Server
    participant P as Plugin Process

    W->>Core: Execute node "my_node"
    Core->>Core: Lookup node in registry
    Note over Core: Node is a RemoteNode (from plugin)
    Core->>PS: POST /plugins/{id}/nodes/my_node/execute
    PS->>P: Forward to localhost:{port}/nodes/my_node/execute
    P->>P: Run node.call(ctx, **inputs)
    P-->>PS: ExecutionResponse
    PS-->>Core: Response
    Core-->>W: Node result
```

When a plugin is loaded, its manifest registers **dynamic remote node classes** in the platform's node registry. These remote nodes look like normal nodes to the workflow engine but forward their `call()` to the Plugin Server instead of executing locally.

## Plugin process internals

Each plugin process is a FastAPI server generated by the SDK. It exposes:

| Endpoint                           | Purpose                                    |
| ---------------------------------- | ------------------------------------------ |
| `GET /health`                      | Health check                               |
| `POST /validate-config`            | Validate plugin configuration              |
| `POST /nodes/{name}/config`        | Get dynamic node configuration             |
| `POST /nodes/{name}/execute`       | Execute a node                             |
| `POST /integrations/{name}/config` | Get integration configuration              |
| `POST /integrations/{name}/ready`  | Check if integration credentials are valid |

The SDK's `noxus plugin serve` command discovers the plugin class, loads its nodes and integrations, and generates all these routes automatically.

## File handling

Plugins run in isolated processes without direct access to the platform's storage. Files are transferred through the Plugin Server:

```mermaid theme={null}
graph LR
    P[Plugin Process] -- "download file" --> PS[Plugin Server]
    PS -- "GET /plugin-server/files/{id}" --> BE[Platform]
    P -- "upload file" --> PS
    PS -- "POST /plugin-server/files/upload" --> BE
```

Inside plugin code, you use the `File` class and the execution context's file helper — the SDK handles all the bridging transparently.

## Security model

* Each plugin runs in its own **isolated Python environment** with its own dependencies
* Plugin processes bind to **localhost only** — they're not directly accessible from outside
* The Plugin Server authenticates with the platform using an **API key**
* Integration credentials are passed through the **execution context** per-request, not stored in the plugin
* Plugin source downloads support **private Git repositories** with token auth

<CardGroup cols={2}>
  <Card title="Plugin Overview" icon="puzzle-piece" href="/developers/plugins/overview">
    What you can build with plugins
  </Card>

  <Card title="Your First Plugin" icon="rocket" href="/developers/plugins/your-first-plugin">
    Build and deploy a plugin step by step
  </Card>
</CardGroup>
