OpenClaw EnterpriseDOCSGitHub

Agent Presets flow

Overview

The console reads a Namespace-owned Preset, renders its variables, and saves an independent Configuration and Agent through the existing APIs. This flow starts with Preset CRUD or selection and stops at a saved Agent draft. Deployment continues through revision admission.

Entry Points

Flow

graph TD
  S0["API startup with defaults enabled"] --> S1["Authorize and lock eligible Namespaces"]
  S1 --> S2["Create missing names; preserve existing copies"]
  S2 --> C
  N["Authorized Namespace creation"] --> S2
  A["Operator writes Preset"] --> B["OCC authorizes and validates template"]
  B --> C["Store Namespace-owned Preset"]
  C --> D["Console reads selected Preset once"]
  D --> E["User supplies variables and selects Use Preset"]
  E --> F["Renderer copies launch settings"]
  F --> G["Chooser closes; user edits and saves ordinary draft"]
  G --> S["Password input: create Secret in current Namespace"]
  S --> H["Configuration API admits and saves"]
  G -->|Existing credential binding| H
  H --> I["Agent API admits and saves"]
  I -->|Model Secret selected| O["Grant Agent access to the selected model Secret"]
  I -->|No model Secret| J
  O --> J["Independent Agent draft"]
  O -->|Grant fails| R["Retain Agent and retry credential access"]
  F -->|Invalid variable| E
  I -->|Agent save fails| K["Keep Configuration ID for safe retry"]
  J --> L["Credential preparation and revision admission"]

Execution Trace

Before serving requests, migration 0024 creates Preset storage and adds Preset CRUD grants to the unchanged built-in administrator Role. Its guarded update preserves customized Roles; the exact eligibility rules belong to the Preset contract.

1. Include configured defaults

apps/controller/src/composition/installation-config.ts:loadInstallationConfiguration

The loader validates the opt-in boolean and file list. It loads bundled JSON when enabled, resolves explicit JSON paths beside the startup YAML, validates each name/template definition, and rejects missing, malformed, invalid, or duplicate-name definitions before composition. API and worker share the startup snapshot and its source path; files are not watched. Production composition and development composition pass generic definitions into ControllerOptions.defaultPresets, select an authorized persisted administrator through IAM, and initialize defaults after selecting Configuration and IAM Drivers. Native template contents remain in the application bundle; OCC owns generic Preset lifecycle. The standard Codex artifact requests on-request approvals with the user as reviewer, cached hosted search, and the exact build hosts in the standard Preset guide. Seeding and rendering copy that native policy; the deployed Codex plugin owns its enforcement. Updating the bundle does not replace already installed copies.

packages/occ/src/index.ts:OpenClawController.initializeDefaultPresets

Initialization authorizes Installation administration, locks Namespaces in ID order in one transaction, and skips failed/deleting Namespaces. Missing names require Preset create permission and ordinary template/Driver validation before storage and mutation audit. Existing names are untouched. Any failure rolls back the transaction and prevents API startup. Namespace creation uses the same helper before queuing provisioning, so denied or invalid defaults also roll back the new Namespace. Disabling defaults leaves persisted copies alone.

2. Admit and store a template

packages/occ/src/index.ts:OpenClawController.createPreset

OpenClawController.createPreset and admitPresetTemplate lock the Namespace, check the exact collection grant and ready state, then call normalizePresetTemplate. The normalizer copies the template and fills omitted namespaceId fields in Harness authentication and Configuration Secret binding sources from the locked Namespace. Explicit scopes remain unchanged for same-Namespace validation. Template structure, variable declarations, default types, and credential references are checked without requiring unfilled variables. Password definitions have no defaults and can appear only as whole tokens at agent.harnessAuth.secret; literal credentials and substitution into ordinary settings are rejected. Ordinary Agent field validation is deferred to the creation APIs. When native values exist, the selected Configuration Driver's validateValues checks their native credential rules; missing capability fails closed. Core owns no native configuration interpretation.

The repository stores the whole template in occ.presets. PATCH locks the resource and replaces an included template atomically. DELETE removes its exact IAM bindings in the transaction. Presets prevent Namespace deletion while present. The controller's normal audit path records mutations and denials without template or variable contents.

3. Read and render the selected copy

apps/controller/src/console/agents/presets.mjs:createPresetFields

createPresetFields lists only readable Presets, then reads the selected resource once. The user reviews prefilled scalar defaults and fills typed inputs. The bound password variable offers a new masked token or an existing same-Namespace Secret. The chooser fetches only Secret metadata, validates the original template, and replaces the password token with the selected reference in a temporary copy. Mode changes clear discarded tokens; stale catalog responses cannot replace a later selection. The user then selects Use Preset. The shared renderPresetTemplate walks JSON once, rejects missing or mistyped inputs and duplicate rendered native keys, and preserves runtime placeholders and unresolved SecretRefs.

Rendering makes no requests and fetches no credentials. On success, the chooser is replaced by the ordinary Agent form; the form keeps only the rendered settings and, when selected, ephemeral existing-Secret metadata for access grants. The chooser lists Presets alphabetically by display name. Password values move into the ordinary masked credential input; the chooser clears its detached password controls. Preset updates or deletion cannot alter them. Before saving, Start over discards the unsaved draft after confirmation and opens a fresh chooser. After a save succeeds or its outcome becomes uncertain, restart is disabled so the user follows ordinary creation recovery.

apps/controller/src/console/console.mjs:loadPage

Before resetting the view, Console captures the unsaved form's raw editor text, model controls, workspace files, repository selections, and staged Secret references. The in-memory map is scoped to the signed-in user and Namespace. Returning to a Preset form through navigation or browser history reconstructs it from that copy; capability and repository discovery run again against current access. A form started without a Preset registers for discard on exit. After flushing captures, loadPage removes its creation and channel snapshots and its retained view when navigation leaves creation or changes Namespace. Re-entry opens the initial choices; resources already saved through the API remain. Invalid JSON survives as text. Password controls and plugin discovery results are excluded. Start over removes the copy; session loss, logout, a different signed-in user, and page exit clear the map. Starting a save removes its capture before any mutation, so a later route return cannot replay a pre-save copy as a new Agent. Existing partial-save recovery remains local to its form.

4. Save an independent draft

apps/controller/src/console/agents/create.mjs:renderCreateAgent

The creation form copies rendered settings into editable fields and checks their form representation. A method-only Preset authentication default selects API key or Service Accounts without binding a Secret. The shared Secret picker requires a same-Namespace selection. Create new Secret... saves immediately and stages the reference; the browser never reads existing Secret bytes. Final Agent admission still requires a complete authentication binding. Rendered agent.pluginApprovers remains ordinary Agent draft data. Omission inherits the form default, an empty array keeps the explicit no-approver default, and selected channel identities are submitted through the normal Agent create body. The Agent API and selected Plugin Driver validate the concrete approvers after variable rendering. Preset agent.initialWorkspaceFiles override matching workspace defaults, including explicit empty strings. The shared Preset validator checks supported filenames, Unicode, NUL, and byte limits before and after expansion; password variables remain confined to the credential field. User-edited workspace bytes follow the existing private workspace setup path in both regular and provisioning creation. The form keeps Secret bindings internally and exposes channel-specific Secret controls rather than a raw bindings editor. Selected model Secret metadata and references survive draft navigation; raw passwords do not. Provider or authentication-method changes clear the selection. For an existing selection or a Secret reference already bound in the Preset, Save uses the reference without creating another Secret. Ordinary creation grants the new Agent's service principal exact Secret operate access and retains the reference through Agent-conflict and grant retries. The caller needs permission to manage the grant; if it fails, the saved Agent remains and the form offers a retry. Provisioning derives the grant from harnessAuth.source. For a password input, Save first creates a same-Namespace Secret, clears the credential input, and retains the returned reference. It then creates a Configuration and an Agent that refers to the Configuration and Secret, and grants the Agent access. Dedicated provisioning uses the existing provisioning flow after Secret creation. Password bytes are sent only to the Secret creation endpoint, never as Agent or Configuration fields. Each server request owns full schema, native credential, and authorization admission before its persistence boundary; browser validation is not that boundary.

If Secret creation fails, the masked input remains for correction or retry. If a later save fails, its saved Secret reference is reused. If Configuration creation succeeds but Agent creation fails, the form retains the Configuration ID and locks Configuration-affecting controls. A safe retry reuses the saved Configuration. An uncertain response requires inspection before another creation attempt. See creation recovery.

5. Hand off to deployment

packages/occ/src/index.ts:OpenClawController.deployAgent

The saved Agent has a new identity and no Preset reference. Variable inputs are not stored as a separate map. Rendered values are ordinary Agent/Configuration settings. Credential preparation and revision admission read those resources, not the Preset. Later Preset changes cannot change a draft or an immutable admitted revision.

Debugging and Verification

Search documentation