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

# Manifest setup and auth fields

Manifest fields that setup, onboarding, and config UI surfaces read before plugin runtime loads. Part of the [Plugin manifest](/plugins/manifest) reference; the [top-level field reference](/plugins/manifest#top-level-field-reference) lists every field.

## Native conversation discovery

Plugins exposing conversations created outside OpenClaw declare
`setup.nativeSessionCatalog` with a `label`, optional `description`, and optional
`nodeCommands` containing their catalog read/list/resume command names. The
contract uses the plugin's existing `config.sessionCatalog.enabled` preference.
Core checks this preference before registered catalog reads, lists, activity
checks, and the declared node commands execute. Schema-generated defaults for
`enabled` remain available in plugin-local configuration, but the root runtime
config retains only an authored value so a default cannot impersonate consent.

Declare commands that expose the native catalog, not independently authorized
execution transports. Disabling discovery must preserve turns in an already-bound
conversation; those turns retain their existing execution and node permissions.

New declarations default to off when no preference is authored, including plugins
installed after configuration creation. Their schemas should also default `enabled`
to `false`. New configuration files persist `false` for the host-generated catalog
inventory, including installable official plugins. Explicit values are always kept.
These opt-out-only entries do not request installation or widen a plugin allowlist;
an explicit plugin selection or other authored configuration still does.
They also do not produce disabled-plugin config warnings. Existing opt-outs remain
valid and need no Doctor rewrite; removing one can restore legacy discovery behavior.

The host-generated `legacyDefaultEnabled: true` declaration preserves the shipped
Claude/Codex implicit-on behavior only for existing readable configurations. It is
an upgrade exception, not a permission an installed third-party manifest can grant.
Future catalogs do not inherit that exception merely by joining the generated
inventory. Existing undeclared catalogs retain their previous behavior.

Onboarding offers an unchecked enablement choice when all declared catalogs are
off; selecting an agent does not imply consent. Explicit selection persists the
choice for installed declarations too. Detection itself writes no preferences.

Run `pnpm native-catalogs:gen` after changing these declarations and
`pnpm native-catalogs:check` to verify the official catalog metadata and packaged
macOS resource. The required `pnpm check` preflight runs this verification. Fresh native configuration creation fails if its privacy-default
resource is missing.

## providerAuthChoices reference

Each `providerAuthChoices` entry describes one onboarding or auth choice. OpenClaw reads this before provider runtime loads. Provider setup lists use these manifest choices, descriptor-derived setup choices, and install-catalog metadata without loading provider runtime.

When a manifest choice is selected, setup resolves its `provider` and `method` in the owning installed plugin. The runtime auth method does not need to repeat `choiceId` in its wizard metadata. A different plugin or auth method cannot satisfy that declared choice. Explicit `provider-plugin:<provider>:<method>` choices retain their encoded target.

| Field | Required | Type | What it means |
| - | - | - | - |
| `provider` | Yes | `string` | Provider id this choice belongs to. |
| `method` | Yes | `string` | Auth method id to dispatch to. |
| `choiceId` | Yes | `string` | Stable auth-choice id used by onboarding and CLI flows. |
| `platforms` | No | `string[]` | Supported Gateway host platforms, such as `["darwin"]`. Omission allows every platform; an empty or invalid restriction offers the choice on none. |
| `choiceLabel` | No | `string` | User-facing label. If omitted, OpenClaw falls back to `choiceId`. |
| `choiceHint` | No | `string` | Short helper text for the picker. |
| `icon` | No | HTTPS URL | Artwork shown beside this choice in supported onboarding clients. |
| `website` | No | HTTPS URL | Product, sign-in, or installation page shown by supported onboarding clients. |
| `assistantPriority` | No | `number` | Lower values sort earlier in assistant-driven interactive pickers. |
| `assistantVisibility` | No | `"visible"` \| `"manual-only"` \| `"detected-only"` | Control picker visibility. `manual-only` permits manual selection; `detected-only` requires successful provider-owned discovery before offering the model. |
| `deprecatedChoiceIds` | No | `string[]` | Legacy choice ids that should redirect users to this replacement choice. |
| `groupId` | No | `string` | Optional group id for grouping related choices. |
| `groupLabel` | No | `string` | User-facing label for that group. |
| `groupHint` | No | `string` | Short helper text for the group. |
| `onboardingFeatured` | No | `boolean` | Surface this group in the featured tier of the interactive onboarding picker, before the "More..." entry. |
| `optionKey` | No | `string` | Internal option key for simple one-flag auth flows. |
| `cliFlag` | No | `string` | CLI flag name, such as `--openrouter-api-key`. |
| `cliOption` | No | `string` | Full CLI option shape, such as `--openrouter-api-key <key>`. |
| `cliDescription` | No | `string` | Description used in CLI help. |
| `personalAccount` | No | `boolean` | Offer this method in Connected accounts; it must stage one inline credential without importing host logins or writing shared state. |
| `appGuidedSecret` | No | `boolean` | One pasted secret plus provider defaults is sufficient for app-guided setup. |
| `appGuidedActionLabel` | No | `string` | Short command label shown when starting provider-owned app-guided setup. |
| `appGuidedDiscovery` | No | `boolean` | The matching runtime auth method owns read-only local discovery through `appGuidedSetup`. |
| `appGuidedAuth` | No | `"oauth"` \| `"device-code"` | Provider-owned interactive login that native setup clients can render generically. |
| `credentialOnly` | No | `boolean` | The method supports saving credentials without starter-model discovery or activation. Omitted means setup only. |
| `channelLogin` | No | `{ aliases?: string[] }` | A fixed-input OAuth or device-code method that private chat can run. Requires `credentialOnly`; aliases enable explicit commands such as `/login codex`. |
| `onboardingScopes` | No | `Array<"text-inference" \| "image-generation" \| "music-generation">` | Which onboarding surfaces this choice should appear in. If omitted, it defaults to `["text-inference"]`. |

`platforms` uses Node.js platform names; unknown names are removed. The restriction
applies before setup, login, CLI flag, and install-catalog choices are offered. It describes the host running OpenClaw,
not the connected app or browser. It does not change saved plugin enablement or
provider configuration. The provider still checks model and operating-system
availability when the selected setup method runs.

`assistantVisibility: "detected-only"` keeps the choice out of metadata-only
setup, sign-in, enable, and install rows, including manual pickers. App-guided
setup offers it only as a candidate returned by the provider's current
`appGuidedSetup.detect` probe. Classic setup includes the provider choice only
after `detectAvailability` succeeds. Both probes must apply the provider's
actual model eligibility rules. Explicit CLI auth-choice selection remains
supported and the setup method still rechecks availability before activation.

For a provider whose setup methods all require detection, saved and configured
models are also withheld from offered candidates until current discovery confirms
the matching model. The configured model and setup-complete state remain recorded;
an unavailable model does not turn an existing installation into fresh setup.
Providers with an ordinary supported setup method retain their existing behavior.

An optional `modelTarget: "utility"` uses the existing per-agent or default
`utilityModel` setting; omission selects the primary role. Setup verifies the
utility role without replacing a working primary or its runtime and credentials.
If no regular primary is configured, the system setup assistant can use the
explicit utility model. Automatic utility defaults never bootstrap setup. A regular
primary takes precedence once configured, and ordinary agent readiness remains
separate from utility setup.
Explicit `provider-plugin:<provider>:<method>` choices retain the role declared
for that same plugin, provider, and method. Runtime wizard metadata does not need
to repeat the manifest's role.
Bare provider choices also retain the role of the method selected by setup.
An exact manifest choice ID still owns dispatch for unprefixed choices.

Clients must echo `modelTarget: "utility"` when activating a utility choice.
Missing or mismatched role acknowledgement is rejected before provider preparation,
so older clients cannot accidentally treat a utility activation as primary-ready.
Detection and successful activation/verification report the role. Detection keeps
`configuredModel` and `setupComplete` primary-only, exposes an explicit `utilityModel`,
and exposes `setupModel` only when that utility is the no-primary setup fallback.
Verification accepts the utility target explicitly, including alongside a primary.

When `appGuidedDiscovery` is true, the matching provider auth method must expose
`appGuidedSetup.detect` and `appGuidedSetup.prepare`. Detection must be
read-only: no login, model pull, download, or config write. Preparation rechecks
the exact selected model and returns a config proposal. OpenClaw saves any
returned credential, runs one confirmation turn without tools, and activates
the proposal only after success. Failed activation retains the saved credential
for retry; a replacement remains inactive until the user accepts activation.
A provider can also
expose `appGuidedSetup.detectAvailability` to mark its setup choice as detected
when the local service is reachable but no model qualifies for automatic setup.
The availability probe is also read-only.

### Login choices

**Connect** in Models requires `credentialOnly: true` plus `appGuidedAuth` or
`appGuidedSecret`. Choices marked `appGuidedDiscovery`, `manual-only`, or outside
text-inference onboarding do not become credential-only actions. Descriptor-only
`setup.providers[].authMethods` entries do not create executable login choices.

Bare `/login` groups visible browser and device-code choices into provider
buttons without starting sign-in. A provider with several methods opens a second
choice. Channels without command buttons show commands to copy. Core builds
this menu from the manifest; channels do not keep separate provider lists.

`channelLogin` opts a credential-only browser or device-code method into private
chat. Use `{}` when no alias is needed. The method must complete without asking
chat for a secret, endpoint, or other free-text input. Methods that need such
input hand off to the matching Control UI login or setup flow. The host owns any
model-access consent after saving credentials; the plugin cannot grant it through
its configuration patch.

Browser-based `channelLogin` methods use `ctx.oauth.authorize` when the host
supplies it. Pass the provider-generated `state`, a `timeoutMs` deadline, and
`buildAuthorizationUrl(redirectUrl)`. The host owns the HTTPS callback, consumes
each response once, and returns `{ code, state }`. The plugin retains its PKCE
verifier and exchanges the code. Forward `ctx.signal` and recheck
`ctx.assertCurrent` before external effects. Keep local and remote CLI completion
when this capability is absent. A received code is not a persisted credential;
the host reports success only after saving it.

When `personalAccount` is true, the method runs through the shared wizard protocol
with a credential-free environment/config, no agent directory or preseeded secret,
and plaintext input mode. It must return exactly one inline credential for its
provider and honor cancellation. It must not import a native CLI login, resolve a
SecretRef, write credentials/config, or require shared model activation. The
Gateway owns the private per-person commit; `configPatch`, `defaultModel`, and the
returned shared profile id are not applied. Mark credential prompts sensitive.
Use this capability only when the provider permits this credential use.

Personal-account calls always supply `ctx.assertCurrent`. Preserve this
closure-bound check through provider helpers and invoke it immediately before
external effects, including discovery, polling and token exchange after any
interactive or asynchronous wait. With `fetchWithSsrFGuard`, pass it as
`beforeRequest` so it runs after DNS/proxy preparation and on redirects. Keep
forwarding `ctx.signal` to cancel in-flight work; a signal alone does not recheck
the person's current permission. Standalone CLI/onboarding calls may omit the
check because they do not carry a Gateway person's authority.

An optional `matchesPersonalAccount(credential, existing)` auth-method hook can
prove that an OAuth reconnect is the same provider account. Match the complete
identity, not an email or a shared workspace alone. Without that proof, a new
OAuth account slot is created and old chat pins retain their original credential.
API keys and static tokens reuse a slot only when their literal value matches.

## setup reference

Use `setup` when setup and onboarding surfaces need cheap plugin-owned metadata before runtime loads.

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "setup": {
    "providers": [
      {
        "id": "openai",
        "authMethods": ["api-key"],
        "envVars": ["OPENAI_API_KEY"],
        "authEvidence": [
          {
            "type": "local-file-with-env",
            "fileEnvVar": "OPENAI_CREDENTIALS_FILE",
            "requiresAllEnv": ["OPENAI_PROJECT"],
            "credentialMarker": "openai-local-credentials",
            "source": "openai local credentials"
          }
        ]
      }
    ],
    "cliBackends": ["openai-cli"],
    "configMigrations": ["legacy-openai-auth"],
    "requiresRuntime": false
  }
}
```

Top-level `cliBackends` stays valid and continues to describe CLI inference backends. `setup.cliBackends` is the setup-specific descriptor surface for control-plane/setup flows that should stay metadata-only.

When present, `setup.providers` and `setup.cliBackends` are the preferred descriptor-first lookup surface for setup discovery. If the descriptor only narrows the candidate plugin and setup still needs richer setup-time runtime hooks, set `requiresRuntime: true` and keep `setup-api` in place as the fallback execution path.

Without an explicit `openclaw.setupEntry`, OpenClaw resolves the conventional `setup-api` file at the package root or in package-local `dist/`. Standalone runtime builds include that public surface automatically.

OpenClaw includes `setup.providers[].envVars` in generic provider auth and env-var lookups. Put setup and status env metadata there.

Use `providerUsageAuthEnvVars` when a billing or organization-level credential must activate `resolveUsageAuth` without becoming an inference credential. These names join workspace dotenv blocking, ACP child-process stripping, sandbox secret filtering, and broad secret scrubbing. The provider runtime still reads and classifies the value inside `resolveUsageAuth`.

OpenClaw can also derive simple setup choices from `setup.providers[].authMethods` when no setup entry is available, or when `setup.requiresRuntime: false` declares setup runtime unnecessary. Explicit `providerAuthChoices` entries stay preferred for custom labels, CLI flags, onboarding scope, and assistant metadata.

Set `requiresRuntime: false` only when those descriptors are sufficient for the setup surface. OpenClaw treats explicit `false` as a descriptor-only contract and will not execute `setup-api` or `openclaw.setupEntry` for setup lookup. If a descriptor-only plugin still ships one of those setup runtime entries, OpenClaw reports an additive diagnostic and continues ignoring it. Omitted `requiresRuntime` keeps legacy fallback behavior so existing plugins that added descriptors without the flag do not break.

Because setup lookup can execute plugin-owned `setup-api` code, normalized `setup.providers[].id` and `setup.cliBackends[]` values must stay unique across discovered plugins. Ambiguous ownership fails closed instead of picking a winner from discovery order.

When setup runtime executes, setup registry diagnostics report providers or CLI backends that `setup-api` registers without matching manifest declarations. CLI backend descriptors also report a missing runtime registration because setup lookup needs the registered backend configuration. Provider descriptors may remain metadata-only even when the same setup module contributes migrations, CLI backends, probes, or selected provider runtimes.

### setup fields

| Field | Required | Type | What it means |
| - | - | - | - |
| `providers` | No | `object[]` | Provider setup descriptors exposed during setup and onboarding. |
| `cliBackends` | No | `string[]` | Setup-time backend ids used for descriptor-first setup lookup. Keep normalized ids globally unique. |
| `configMigrations` | No | `string[]` | Config migration ids owned by this plugin's setup surface. |
| `requiresRuntime` | No | `boolean` | Whether setup still needs `setup-api` execution after descriptor lookup. Explicit `false` disables it; omission preserves the legacy fallback. |

### setup.providers reference

| Field | Required | Type | What it means |
| - | - | - | - |
| `id` | Yes | `string` | Provider id exposed during setup or onboarding. Keep normalized ids globally unique. |
| `authMethods` | No | `string[]` | Setup/auth method ids this provider supports without loading full runtime. |
| `envVars` | No | `string[]` | Env vars that generic setup/status surfaces can check before plugin runtime loads. |
| `authEvidence` | No | `object[]` | Cheap local auth evidence checks for providers that can authenticate through non-secret markers. |

`authEvidence` is for provider-owned local credential markers that can be verified without loading runtime code. These checks must stay cheap and local: no network calls, no keychain or secret-manager reads, no shell commands, and no provider API probes.

Supported evidence entries:

| Field | Required | Type | What it means |
| - | - | - | - |
| `type` | Yes | `string` | Always `local-file-with-env`. |
| `fileEnvVar` | No | `string` | Env var containing an explicit credential file path. |
| `fallbackPaths` | No | `string[]` | Local credential file paths checked when `fileEnvVar` is absent or empty. Supports `${HOME}` and `${APPDATA}`. |
| `requiresAnyEnv` | No | `string[]` | At least one listed env var must be non-empty before the evidence is valid. |
| `requiresAllEnv` | No | `string[]` | Every listed env var must be non-empty before the evidence is valid. |
| `credentialMarker` | Yes | `string` | Non-secret marker returned when the evidence is present. |
| `source` | No | `string` | User-facing source label for auth/status output. |

## configGroups reference

`configGroups` organizes the plugin’s Settings page into titled sections. It is
presentation metadata beside `configSchema`; it does not add configuration keys
or change validation, defaults, or runtime behavior.

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "configGroups": [
    {
      "id": "connection",
      "title": "Connection",
      "order": 10,
      "properties": ["apiKey", "endpoint"]
    },
    { "id": "history", "title": "History", "order": 20, "properties": ["storage"] }
  ]
}
```

Each entry requires a nonempty `id`, `title`, and `properties` array. Properties
name exact immediate keys in `configSchema.properties`; they are not nested
paths. A nested object and its descendants stay in that property’s section.
Group ids and property assignments must be unique. Optional integer `order`
sorts sections from lowest to highest (default `0`); ties retain manifest order.
Properties appear in the order authored within each group.

There is one level of sections, all visible by default. Settings search matches
field names, labels, descriptions, and group titles. Unassigned properties appear
under **Other**. Missing or invalid grouping metadata leaves the complete flat
form available; it never hides fields or prevents the plugin from loading.
Hosts without grouping support ignore this optional metadata.

## uiHints reference

`uiHints` is a map from config field names to small rendering hints. Keys can use dots for nested config fields, but no path segment may be `__proto__`, `constructor`, or `prototype`; setup rejects those names.

```json theme={"theme":{"light":"min-light","dark":"min-dark"}}
{
  "uiHints": {
    "apiKey": {
      "label": "API key",
      "help": "Used for OpenRouter requests",
      "placeholder": "sk-or-v1-...",
      "sensitive": true
    }
  }
}
```

Each field hint can include:

| Field | Type | What it means |
| - | - | - |
| `label` | `string` | User-facing field label. |
| `help` | `string` | Short helper text. |
| `tags` | `string[]` | Optional UI tags. |
| `advanced` | `boolean` | Marks the field as advanced. |
| `sensitive` | `boolean` | Marks the field as secret or sensitive. |
| `placeholder` | `string` | Placeholder text for form inputs. |
| `presentation` | `"phone-number"` | Display-only localized phone formatting for parseable international (`+...`) values; raw values remain unchanged. |

Channel config sections inherit `help` for the leaves every channel shares
(`enabled`, `allowFrom`, `dmPolicy`, `groupPolicy`, `streaming`, and similar) at
the channel root and under `accounts.<id>`. A channel that declares its own
`help` for one of those keys always wins, so override it whenever the shared
wording is wrong for your provider. Provider-specific keys such as credentials,
hosts, and webhooks still need their own hints.

When multiple plugins declare the same channel, the selected plugin owns its
schema and presentation hints. Redaction preserves `sensitive: true` and
`tags: ["url-secret"]` declarations from every discovered owner, so credentials
left in config stay protected after switching plugins. The `url-secret` tag
protects credentials embedded in URLs while leaving public URLs visible.
Setting `sensitive: false` disables name-based secret detection, but does not
override another owner's positive declaration or URL credential protection.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.