# Configs

> A config is the unit of publishing: a named, versioned bundle of the components you select (models, agents, templates, skills, loops, cells, MCP servers, connectors and more) plus resource limits, storage paths, token caps and settings, which the engine resolves as one artifact. You build it in the Console's guided config builder and publish immutable versions. As of September 25, 2026, OpenEng AI isn't live yet.

A **config** is the unit of publishing: a named, versioned bundle of the components you select (models,
agents, templates, skills, loops, cells, MCP servers, connectors and more) plus resource limits,
storage paths, token caps and settings, which the engine resolves as one artifact. **Configs** sits at
the top of the Console's nav, right under Overview: it's where you create configs, build them in the
guided config builder, publish versions and look back through them.

> [!WARNING] Status on September 25, 2026: OpenEng AI isn't live yet
> The Console and Web Console interfaces load, but the OpenEng AI API routes and the Broker aren't
> deployed. Nothing can be saved or published, and no AI engine can register or connect. Pro,
> Enterprise and pay-as-you-go launch in Q4 2026 and can't be purchased yet. This page describes
> OpenEng AI as it works once those services are live ([status](ai.md)).

*Figure: Configs — the guided config builder: the status strip under the header, the step rail grouped into phases, and the current step's page.*

> [!NOTE] Execution flow is per-config
> Each config also carries its own
> [execution flow](execution-flow.md) — the graph of stages the engine runs
> for every turn. You design it in the builder's **Execution flow** step. A config
> whose flow you never touch uses the default flow, so it is entirely opt-in.

## What it is, and when to use it

Everything the engine runs comes from a published config version, and **nothing is served until you
create and publish one**: the engine answers every request with *"No configuration published, please
create and publish a configuration to start accessing the engine."* A new account has no config; the
Console doesn't create one for you.

One config is enough to start. Create *additional* configs when different machines or sessions need
different setups: a work profile and a home-lab profile, a locked-down config you share with a
teammate, a sandbox-fleet config. In the Web Console at app.openeng.app, you pick which config and
version each session uses. Requests that name no config use the engine's default: the config set with
`--default` or `OPENENG_DEFAULT_CONFIG`, otherwise the config you own named `default`, otherwise the
first config you own ([The engine](engine.md#config-selection)).

## The configs list

Each config is a card showing: its **name** (click it to open the builder) · its copyable mono **id** ·
**Published v…** or **Never published** · a **Draft changes** badge when the draft was edited after the
last publish · its **group tag** (a display label, with a group menu on the card to assign it —
nothing more) · how many components of each kind it selects · when it was last published · and a
**Versions** link to its [version timeline](#the-version-timeline). Configs shared *with* you appear
read-only with a "shared by" badge. A filter box above the cards searches names, ids and owners.

**New config**: type a name → the server mints a platform-unique `<name>_<suffix>` id → the builder
opens. On a brand-new account, the page shows a single **Create your first configuration** card
instead. While you have configs but none is published, a banner says the engine can't be used yet,
with a **Publish my first config** button that jumps to the publish step.

Every card you own carries **Edit** (pencil) and **Delete** (trash) actions. Delete asks for
confirmation and removes the config's draft and its share grants; machines pinned to a published
version keep using their cached copy until you point them elsewhere. Configs **shared with you** are
read-only and offer no delete (only the owner can delete).

## The config builder

Opening a config starts the **guided config builder**: a rail of steps on the left, grouped into
phases, and the current step on the right, with **Back** and **Next** buttons under it.

| Step | Phase | What you set |
|---|---|---|
| **Resources** | Resources | How much of the serving machine the config may use ([below](#resources)) |
| **Execution flow** | Execution flow | The stages the engine runs for every turn ([Execution flow](execution-flow.md)) |
| **Models** | Components | One model per role group ([below](#models-step)) |
| **Agents**, **Templates**, **Skills**, **Roles**, **Loops**, **Routes**, **Cells**, **MCP servers**, **Connectors** | Components | Which of your own items the config ships ([below](#components)) |
| **Global paths** | Paths | Where the engine stores each kind of data ([below](#global-paths)) |
| **Token caps** | Token caps | Per-component token budgets ([below](#token-caps)) |
| **Settings** | Settings | Functionalities, review, machine profile, storage point, loop posture and plugins ([below](#the-settings-panel)) |
| **Review & publish** | Publish | Version, notes, diff, validation ([Publishing](#publishing)) |

- **Every step can be revisited**; nothing is locked behind an earlier step. Each step shows its
  status in the rail: **Done**, **Needs attention** or **Blocked**, or nothing while you haven't
  touched it. **Models** shows Blocked while it has no pick and no embedded core is on, **Settings**
  while no functionality or embedded core is on, and **Review & publish** while any blocking problem
  remains. Only the problems in the Validation list stop a publish.
- **The flow decides which steps show.** If your execution flow uses no agents, the Agents step is
  hidden; every other step always shows.
- **The draft saves itself.** Unlike the Console's other editors, the builder saves your draft
  automatically a moment after each change; the header shows **Saving…**, **Unsaved changes** or
  **Saved**. Leaving while a save is in flight asks you to confirm. Publishing is still a separate,
  explicit step.
- **The status strip** under the header lists every problem (click one to jump to its step) and the
  environment variables the config requires. An ⓘ in the strip explains how references and
  placeholders resolve.
- A config shared with you opens read-only.

### Resources

Four sliders set the share of the serving machine the config may claim: **CPU**, **GPU**, **Memory**
and **Storage**. They take percentages only, never absolute numbers, so one config scales from a laptop
to a workstation. Each starts at **10%**, the safe default. The engine's governor admits work within
these shares cooperatively; it doesn't impose OS-level limits. The published engine is CPU-only, so the
GPU share has nothing to govern there, and catalog models that run in your own Ollama daemon are
outside the governor. An operator
can override the CPU and memory shares on one machine with `OPENENG_RESOURCE_FRACTION`
([The engine](engine.md#environment)).

### Models

One section per engine **role group**. For each group you pick exactly one model from **your own
models**; models are created or added in the Models page, never here ([Models & role defaults](models.md)).
Picking a model pins a frozen copy of it into the config.

- Options that need more than the machine profile (set in Settings) provides are disabled.
- A group you leave unset falls back to its embedded default on the engine. The routing group may stay
  unset: the engine's built-in complexity algorithm then routes each turn.
- The planner group's **Use default** is the included **Cloud Planner**, which runs on your OpenEng
  planning credit ([Plans & billing](account.md)).
- A separate slot binds the **Device Use** model: a vision model that looks at the screen and clicks
  and types to finish a goal. Only models tagged with the vision modality are offered; leave it empty
  to keep Device Use off. Device Use needs an engine build with the X11 device backend, which the
  published Linux x86_64 engine doesn't include yet.

The step shows **Blocked** while it has no pick at all and no embedded core is switched on in
Settings. That alone doesn't stop a publish: every group you leave unset uses its embedded default.

### Components: agents, skills, cells and the rest

The steps from **Agents** to **Connectors** each list **your own items** of one kind, and you tick the
ones this config ships. The list never shows the public catalog: adopt or import a catalog item on its
own page first (Agents, Skills, Loops, Library and so on), and it appears here. Each empty list links
to the page where you add items.

- **Templates** also sets the default template the engine prepends to every prompt.
- **Roles** are behavioral rule sets, not the model roles of the Models step.
- **Routes** are your Gateway routing policies ([Limits & guardrails](govern.md)).
- **Cells** lists only registered deployments, because the engine drops a cell without a deployment
  URL ([Cells](cells.md)).
- **Connectors** are the Console's remote integrations (each with a declared sandbox tier), not the engineering apps'
  [connectors](connectors.md).
- Credentials are always `${ENV}` placeholder names, never values.

Picking an item that belongs to another config makes a **copy** for this one; the builder never moves
an item out of another config. Clearing the tick removes the copy again.

### Global paths

A row for each storage component the engine uses (home, models, threads, memory, skills, dashboards,
workers, logs, config, checkpoints, missions, research, cas), each showing the engine's default as
its placeholder: `~/.openeng` for home and memory, `~/.openeng/<component>` for the rest. A value
overrides the default; it must be an absolute or `~`-relative directory and can't contain `..`. The
engine resolves these paths on its own machine, and a per-component environment variable there always
wins ([The engine](engine.md#files)).

### Token caps

Per-component token budgets. Each cap names what it limits (an **Agent**, **Delegator**,
**Sub-delegator**, **Sub-agent**, **Planner**, **Reviewer** or **Worker**, or everything **Per turn**
or **Per day**), can be narrowed to one named component, and sets a budget from 100 thousand to 5
billion tokens (type `500k`, `2M` or `1B` into the value). Its **breach action** is either **prompt**
(the default: the engine pauses the run and asks whether to boost the budget or proceed) or **stop**.
A config can carry several caps; one without caps runs unbudgeted.

### Settings

The config-level defaults, gathered in one step:

| Setting | What it does |
|---|---|
| **Functionalities** | What the engine serves for this config: **Chat**, **Coding**, **Agentic runs** (multi-step plan-then-execute runs, routed by complexity), **Research** and **Device Use**. Research and Device Use need Pro; Device Use is off until you switch it on, and it needs an engine build with the X11 device backend, which the published Linux x86_64 engine doesn't include yet. Two **embedded cores** sit alongside: **self-improving skills** and **embedded research**. At least one functionality or embedded core must be on, or the step is Blocked. |
| **Review** | The review depth: **Every layer (all)**, **Layer boundaries only (boundary)** or **Final response only (final)**, with the reviewer model and its caps. The final-response review is always on and can't be switched off. |
| **Device Use** | Shows which vision model drives Device Use; you pick it in the Models step. |
| **Machine profile** | The machine the config targets (RAM, cores, storage). It must meet the floor your selected models need; otherwise the step Needs attention. |
| **Storage point** | Where run results are to be delivered, or **none**: results then stay on the node that produced them. Needs Pro; the engine doesn't deliver to storage points yet ([Storage points](storage-points.md)). |
| **Loop posture** | Which agent-loop strategies the config allows and the default for each category ([Loops](loops.md)). The loops you ship are picked in the Loops step. |
| **Plugins** | The plugins that run at their attach point on every call. External plugins take `${ENV}` placeholders for credentials. |

### What the engine receives

Two inline surfaces show exactly what the engine will get, computed from the **live projection**: the
artifact shape the engine deserializes, not an approximation.

- **What the engine will receive**, a card under every step: per-domain counts, the role bindings (an
  unknown or deleted model falls back to the role's embedded default, with a visible notice), the
  machine floor and the enabled capabilities.
- **Required environment**, in the status strip: every distinct `${VAR}` in the whole artifact, sorted
  and de-duplicated, collected with **exactly the engine's own rules** (names are
  `[A-Za-z_][A-Za-z0-9_]*`; the `$${…}` escape is skipped). This set is byte-identical to what the
  engine computes for the same publish, so it's your per-machine checklist. Give each name a value on
  the Web Console's **Placeholder values** screen for this config, or export it as an environment
  variable on the engine's machine; the environment variable wins. A variable with no value disables
  the MCP server or cell that uses it; a blank secret is never sent.

## Publishing

The last step, **Review & publish**, publishes a version:

*Figure: The builder's last step — version, release notes, required placeholders, the changes against the current version, validation, and Publish; the step rail on the left shows each step's status.*

1. **Version**: semver, pre-filled as a patch bump (1.0.0 for a first publish); **patch**, **minor**
   and **major** buttons bump it for you. It must be higher than the highest published version, and
   published versions are immutable.
2. **Release notes**: frozen into the version's metadata and shown on the timeline.
3. **Required placeholders**: the `${ENV}` names the version will need, which the publish stamps into
   the artifact as `requiredPlaceholders`.
4. **Changes vs current**: added, removed and changed items per domain against the current published
   version. Human-readable, never a JSON diff.
5. **Validation**: every blocking problem, which disables **Publish**:

| Problem | Why it blocks |
|---|---|
| Agent with no system prompt / scheduler missing cron or prompt | The engine would silently drop them |
| A cron expression outside the 5-field dialect | The node could never fire it |
| Credential over plain `http://` to a remote host (cells/MCP) | The engine refuses the entry — use https |
| A raw value in a credential-shaped field | Secrets must be `${ENV_VAR}` placeholders |
| A connector that isn't a remote https endpoint at a host-isolated tier | The engine refuses to run it |
| More enabled schedulers than your plan allows | Mirrors the server's entitlement gate |
| A default template or storage point that no longer resolves | Dangling reference |
| A selected model that needs more than the machine profile, or a profile below the models' floor | The machine couldn't run it |
| Research switched on with no research model bound | The functionality couldn't run |
| No functionality and no role model at all | The config could do nothing |

Press **Publish v…**. The builder first saves any pending draft change, so the version always matches
what you see; if that save fails, nothing is published. The server independently enforces all of this
— a 403 `entitlement_exceeded` is surfaced with its true used/limit message.

Once the OpenEng AI services are live, a published version is live at once: it appears in the Web Console's config picker within seconds, and
engines fetch it the first time a session uses it ([How the engine picks up what you publish](ai-getting-started.md#4-how-the-engine-picks-up-what-you-publish)).

## The version timeline

**Versions** (the link on each config card) lists every published version with its notes, timestamp,
and the **current** marker. Each row offers the copyable pinned id, **`<id>@<version>`**, which names
that exact version for good. Select any **two** versions to see their domain-level diff, computed in
the browser from the two frozen artifacts.

## The advanced composer

The editor the builder replaced is still reachable for now: add `?legacy=1` to a config's address
(`console.openeng.app/configs/<id>?legacy=1`). It's also the only place with the **Share** button.
The header carries **Versions · Share · Save · Publish**. Unlike the builder, it saves only when you
press **Save** (disabled with the reason while invalid, with a toast on the result), and opening
**Publish** first saves any unsaved settings. Publishing opens a slide-over with the same version,
notes, diff and validation as the builder's last step. The same status strip and "What the engine
will receive" card sit under the header and beside the picker.

*Figure: The advanced composer — the composition tree (left) and the domain picker (right), with the status strip under the header. Reached with ?legacy=1 on a config's address.*

### The composition tree

Every attachable domain in order (Models & role defaults, Agents, Templates, Schedulers, MCP servers,
Cells, Connectors, Token limits, Directories, Gateway policies, Plugins, Roles), each a **drop slot**
showing what's attached, plus rows for Functionalities, Sandboxes, Storage point and Settings that
open the settings panel. Attached items offer one-click detach (×).

### The domain picker

Selecting a domain shows its **global list**: every item of that kind you own, searchable,
multi-select, with **Attach/Detach** buttons (the keyboard path; dragging rows onto the tree does the
same).

Here an item belongs to **one config at a time** (move semantics):

- Attaching an item that belongs to another config shows an *"in {config}"* chip and a **move
  confirmation**: it leaves the old config.
- **Duplicate into** clones the item under a fresh id into this config instead: it stays in both,
  and the original doesn't move.

Disabled items wear a **"Not publishable"** chip: they stay authored, the engine skips them, and
they don't count against plan limits. Schedulers show their account-level
entitlement meter right in the picker header.

The composer's **settings panel** holds the config-level settings that the builder spreads over its
Resources, Models and Settings steps (the embedded toggle, resource caps, role default models, the
default template, the storage point, functionalities and review), plus a few only it offers: the
headless flag, the sandbox attachment, the adaptation model and a media provider endpoint. Each role's
dropdown lists your models by name (the stable id is stored); `(unknown — embedded fallback)` appears
only for an id that no longer exists. Several fields still carry a "Not yet consumed by the CLI" note
written before the current engine; the engine does apply the resource caps, the role models, the
adaptation model and the media endpoint ([The engine](engine.md#start)).

## Sharing

**Share** (owner only, in the [advanced composer](#the-composer)) grants read access by **email**. The
address must belong to an existing OpenEng account; an unknown email gets the inline error
*"No OpenEng account with this email"*, and there are no pending invites. The access list shows avatar,
email and grant date, with per-row revoke behind a confirmation.

Recipients see the config read-only in their list, and their engine can pull it. **Revocation takes
effect on the recipient's next fetch of the config**; an engine that fetched it before you revoked
can keep using that copy until it fetches again.

## Plan & tier notes

Creating configs, building them, publishing, versioning and sharing are open on **every plan**. The
gates live inside: enabled schedulers above your plan's limit block publishing, the storage point
setting and the Research and Device Use functionalities need Pro, and running the engine at all needs
Pro ([Plans & billing](account.md)).

## Troubleshooting

**Publish is disabled.** The Validation list and the status strip name every blocking problem; click
one in the strip to jump to its step. Fix it, or **disable** the offending item (the engine skips
disabled items, and they don't count against limits).

**A step says Blocked.** Models shows it with no model picked and no embedded core on; Settings,
with no functionality or embedded core on. Pick a model or switch a capability on. Only the Validation
list on the last step decides whether you can publish.

**A component list is empty.** The builder lists only your own items. Adopt, import or create items on
their own pages first (each empty list links there); for cells, register a deployment.

**I attached an item in the advanced composer and it vanished from another config.** That's move
semantics — one config per item there. Use **Duplicate into** when you want it in both. (The builder
copies instead of moving.)

**The engine doesn't run the new version.** In the Web Console, pick the new version for your
session; published versions never change, so a session keeps the version it picked. Also confirm the
machine isn't pinned to an old `<id>@<version>`.

**A shared user still has access after revoking.** Their engine may still hold the copy it fetched
before the revocation; its next fetch of the config is refused.

**The status strip lists a `${VAR}` I don't recognize.** Something the config selects references
it (the strip aggregates the *whole* artifact); open the recently selected items to find it. Unset
variables don't leak: they disable the owning item on that machine.
