Skip to main content

Locked settings (runtime.locked)

runtime.locked holds settings the publisher fixes for every install of an app - unlike the rest of runtime, these are not meant to be changed per-installer by default. The first field is byok; byok_editable controls whether an installer may still override it.

yaml
runtime:
locked:
byok: true
byok_editable: false # default - see "Editable vs hard-locked" below

Why this exists​

Whether an app calls its provider directly (Local/BYOK - the installer's own key or a local server like Ollama) or through the Digitorn gateway is normally a per-install toggle, stored on the app's own row. That toggle defaults to off (gateway) on a brand-new install.

For an app whose brain is a local-only provider (Ollama, LM Studio, vLLM), that default is wrong by construction: the gateway has no route to the installer's own machine, so every call fails until someone flips the flag by hand - once per daemon that ever installs the app. runtime.locked.byok: true removes that manual step: the publisher declares the routing the app actually needs, and it is correct from the very first call, on every daemon.

byok: false is also valid - a publisher can just as well fix an app to always route through the gateway, refusing local/BYOK routing even if an installer's vault has a matching credential.

Where it's applied - and where it isn't​

Applied once, at install time - not on every request. internal/appmgr/install.go's InstallWithOpts is the single choke point every install path goes through (Studio deploy, Hub install, CLI install); when the compiled manifest declares runtime.locked.byok, that value is written straight into the app's own row (the same byok column the manual per-install toggle flips by hand) as part of the same install transaction. There is no separate "apply the lock" step, and nothing re-reads the YAML after that.

Turn execution never touches the YAML for this. The agent loop's actual routing decision reads app.Meta.BYOK - a plain boolean already sitting on the in-memory RuntimeApp the daemon keeps for every installed app. Adding locked did not add a YAML parse, a database read, or a lock to that path; it changes what value install seeds into a column that was already being read for every LLM call.

An app that never declares runtime.locked.byok behaves exactly as before this field existed - byok keeps whatever value it already had (manual toggle, or the builder's "Test" button syncing it), and a redeploy doesn't touch it. Declaring the lock is what makes redeploys start re-asserting the value; leaving it undeclared keeps byok a free-standing per-install setting.

Tracking an installer's override under byok_editable: true - a redeploy needs to tell "the installer explicitly chose this" apart from "this is still just the manifest's default" to decide whether to reassert. BYOKUserSet on the app row is that marker: the manual toggle (SetBYOK) sets it on every successful change, and install only re-seeds byok from the manifest when it's still false. Switching to a hard lock (byok_editable: false) always reasserts and clears the marker, regardless of its value.

Editable vs hard-locked​

byok_editable decides what "locked" actually means once an installer has their own copy running:

  • false or unset (default) - hard-locked. The installer cannot change byok at all: their app settings toggle is disabled, and a direct attempt to flip it is rejected. Every redeploy reasserts the publisher's value regardless.
  • true - editable. byok is only the default a fresh install starts from. The installer's own app settings toggle stays enabled, and once they change it, that choice survives future redeploys of the same manifest - it stops being silently reasserted. If the publisher later redeploys with byok_editable removed or set back to false, the hard lock reasserts itself and clears any installer override.

byok_editable also works with no pinned byok value at all - runtime.locked.byok_editable: true alone grants editing without fixing a starting value, which only matters on a cloud host (see below); a desktop install is already fully editable with nothing declared.

Desktop vs. cloud default​

The default for an app that declares no lock at all - genuinely nothing under runtime.locked - depends on where the daemon runs:

  • Desktop / self-hosted (the default): byok stays a fully free, per-install toggle. Nothing changed here from before this feature existed.
  • Cloud / multi-tenant (server.cloud: true in the daemon's own config, not the app's): an undeclared lock defaults to non-editable instead. An installer on someone else's published app can't flip themselves to direct/BYOK routing unless the publisher explicitly allows it - either by pinning a value with byok_editable: true, or by granting editability alone with no pinned value (runtime.locked.byok_editable: true and no byok key at all).

An explicit byok_editable always wins over this default, on either kind of host. A pinned byok value with no explicit byok_editable is a hard lock everywhere, desktop or cloud, exactly as described above - the desktop/cloud distinction only changes what "nothing declared" defaults to.

Set from the builder​

The Studio canvas never asks you to write this YAML by hand. Switching the entry agent's Brain node between Gateway / Local / BYOK writes or clears runtime.locked.byok for you:

Mode pickedEffect on runtime.locked.byok
Local or BYOKWritten as true
GatewayCleared (the whole locked block is removed if it's now empty)

Only the entry agent's own brain drives this - a fallback brain or a secondary agent's brain never writes it, since routing is an app-wide decision, not a per-agent one.

When the entry agent's mode is Local or BYOK, its Brain panel also shows a checkbox: "Let installers change this for their own install". Unchecked (default) writes/keeps byok_editable unset - a hard lock. Checking it writes byok_editable: true. Switching back to Gateway clears byok_editable along with byok, so relocking later starts from a hard lock again unless the checkbox is re-ticked.

Client behavior when locked​

The daemon exposes two views of the lock to the client:

  • The app settings BYOK toggle reads byok_locked off the app's detail row. Hard-locked disables the toggle outright, with a hint explaining it's fixed by the publisher; editable-locked leaves it enabled like an unlocked app.
  • The chat session's model picker reads a locked_byok flag off the session-model endpoint - true only when hard-locked. It greys out and blocks (not hides) any model that would require switching the app's fixed routing mode, instead of the usual "want to enable BYOK?" prompt (that prompt would just be undone by the next redeploy). An editable lock behaves like an unlocked app here: nothing greyed out, since the app settings toggle is the one place that actually changes it.

Cross-references​

  • Setting this from Studio, in plain terms: Lock model routing
  • Unlocked apps can still toggle BYOK by hand, per install - freely on desktop, only if the publisher granted it on a cloud host
  • App-config block reference: App Configuration → runtime
  • Credentials vault (what a BYOK app's own key actually resolves to): Credentials