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

# Building an orchestrator

> Select one configured workflow node with a visible local policy and trace.

# Building an orchestrator

## What this lets you do

Choose one configured connector or workflow for each turn with your own visible local policy.

## What you need

* A running DreamLayer clone
* At least one configured connector or workflow
* Python for the local orchestrator module

## Steps

### 1. Add a minimal policy

```python theme={null}
from dreamlayer.models import CreateJobRequest, Workflow
from dreamlayer.orchestration import OrchestratorContext

ORCHESTRATOR_API_VERSION = 1

def build_workflow(
    request: CreateJobRequest,
    context: OrchestratorContext,
) -> Workflow:
    connector = next(
        (
            item
            for item in context.connectors
            if item.id not in {"sample", "dreamlayer-hosted"}
        ),
        None,
    )
    if connector is None or not connector.models:
        raise ValueError("configure one local or BYOK connector first")
    return context.use(
        connector.id,
        connector.models[0].id,
        rule_id="configured_connector_first",
    )
```

### 2. Keep behavior inside the contract

An orchestrator receives a request and a read-only view of the user's configured connectors, models, and workflows. It returns one validated `Workflow` containing one node for the turn.

* Declare supported orchestrator API version `1`.
* Select only from the visible configured catalog.
* Return one node.
* Emit an inspectable mechanical trace.
* Fail on invalid, unavailable, or ambiguous selection.

### 3. Preserve the V1 boundary

Public local orchestration does not contain DreamLayer's private hosted routing policy. It does not rank providers using private data, hide fallbacks, or execute a public multi-node DAG.

### 4. Save and configure the plugin

For a clone-based installation, save the example as
`src/dreamlayer_runtime/my_orchestrator.py`. This location is inside the runtime's importable
Python package. Then store its exact module and function reference:

```bash theme={null}
./dreamlayer configure --name DREAMLAYER_ORCHESTRATOR_PLUGIN
```

Enter `dreamlayer_runtime.my_orchestrator:build_workflow` when prompted. Plugin references must
use `package.module:function` format. If you keep your orchestrator outside the runtime package,
install its package into the runtime environment before configuring the reference.

### 5. Restart and activate it

Press `Ctrl+C` in the terminal running DreamLayer, then start it again:

```bash theme={null}
./dreamlayer
```

In a second terminal, select the configured plugin and check the runtime:

```bash theme={null}
./dreamlayer policy source plugin
./dreamlayer doctor
```

## Confirm it worked

`./dreamlayer policy source plugin` reports the plugin source. A turn in My Orchestrator selects the first configured local or BYOK connector, returns one workflow node, and records the `configured_connector_first` trace.

## Common errors

* Empty catalog: configure a connector or workflow before selection.
* Unknown ID: select only an item supplied in the current context.
* More than one node: return one workflow node for the V1 turn.
* Plugin cannot be loaded: for the clone-based example, confirm the file is at
  `src/dreamlayer_runtime/my_orchestrator.py` and the reference is
  `dreamlayer_runtime.my_orchestrator:build_workflow`. For another module, confirm its package is
  installed in the runtime environment and its reference uses `package.module:function`.

## Troubleshooting

Inspect the local trace and current configured catalog. Fail visibly when selection is invalid or ambiguous.

## Next steps

* [Connect local ComfyUI](/local-comfyui)
* [Use AI Policy Builder](/policy-builder)
* [Review the open-source boundary](/open-source-boundary)
