adr 0023 model provider policies - Alshival-Ai/neural-labs GitHub Wiki
ADR 0023: Scoped model connections and versioned workload defaults
Design history: for current instructions, see AI accounts and models. See the decision index for amendments and related records.
- Status: Accepted; Claude extension superseded by ADR 0034
- Date: 2026-09-05
- Partially supersedes ADR 0013 for Team Chat after administrator activation
Decision
Personalization retains identity, phone, sign-in methods and appearance. The new personal Model Provider page contains the owner-bound ChatGPT connection and agent defaults. Workspace administrators configure Background AI, a dedicated Team Alshival connection/default, and Voice separately. Runtime health is distinct from credential presence and model availability; absence of ChatGPT OAuth no longer implies that an API-backed workspace is disconnected.
The provider-neutral catalog is a server-side projection of OpenClaw
models.list with account/agent availability, supported reasoning levels and
tool capabilities. Unknown availability is not presented as ready. Tool flags
follow native semantics: omitted supportsTools is enabled for legacy
catalog rows, while explicit false opts out. Cache keys
include both agent and personal/admin scope, concurrent discoveries coalesce,
failed refreshes retain a visibly stale last-good result, and authentication
changes invalidate the relevant cache. No credentials or endpoints are included
in catalog responses. An hourly reconciliation refreshes configured policies.
PostgreSQL migration 8 stores nonsecret desired policies, revisions, last applied resolutions, and pending/error state. Compare-and-swap rejects stale edits. Desired state commits before native configuration is changed; a failed apply is visibly pending and can be retried. Model/effort fields are applied together with OpenClaw's native validated batch configuration implementation. Its pinned CLI can retain provider handles after writing, so a bounded adapter exits after the native mutation returns, rejecting native errors and incompatible exports. No utility model, explicit session pin, job pin, tool policy, or unrelated configuration is rewritten.
Follow-latest is limited to the same provider and workload. The versioned recommendation registry is a fallback for recommendation metadata that this runtime does not expose; availability/capability metadata always constrains it. It never sorts model names to guess a successor. An incompatible explicit effort holds the previous compatible resolution. Inherited Sol/Astra flagship defaults are enrolled in follow-latest during reconciliation; explicit and lower-cost agent defaults become pins. New disconnected accounts remain pending until their connection can be used. Claude and arbitrary provider switching are not silently enabled by a model appearing in a catalog.
Alshival's conversation picker uses the owner's existing scoped Gateway connection
and native sessions.patch ownership checks, expected session identity and
strict user pins. Clearing model/reasoning restores the corresponding agent
default. Automations use the assigned agent's catalog and credentials; model
pins explicitly send fallbacks: []. Reasoning off is an actual value, not an
absent override. CLI/script jobs retain their existing non-model controls.
Credential and execution boundaries
The startup controller imports an explicitly configured workspace OpenAI API key into the native main-agent credential store through stdin, not process arguments. The key is removed from text Gateway and personal/team CLI environments to avoid ambient API fallback; the audio controller retains its server-only binding. Import failure is logged safely and does not take Files/Terminal offline. Imported credentials persist natively after an environment variable is removed; operators must revoke/remove the native profile to retire that credential.
Team Alshival uses nl-teamneura and openai:nl-teamneura, with its own native OAuth
refresh owner. It does not copy a member's or background agent's subscription
tokens. This distinction matters: OpenClaw's isolated agent exec deliberately
excludes shared OAuth from its temporary read-through scope. A dedicated local
credential avoids creating a second refresh owner. The account must be suitable
and authorized for workspace use; the UI does not assert that a subscription
permits arbitrary pooling.
An administrator must connect the Team account and explicitly confirm/save its defaults. Until its first successful activation, the legacy summoner-owned route is retained for compatibility. Afterwards new requests snapshot the last applied Team model/effort/revision in the same database transaction that queues the run. They no longer require a personal connection. Later settings changes cannot rewrite an accepted run. Each execution uses an isolated config with the captured model and no model fallback, retaining the existing channel-scoped capability and bounded channel context. A missing dedicated credential fails rather than falling back to the summoner. This is application isolation inside the existing trusted shared workspace, not an OS security boundary against co-maintainers.
Background sign-in and status commands explicitly select main; multi-agent
runtimes reject ownerless login commands. Sign-in does not reset model defaults
or force-remove existing credentials. Team catalog discovery waits for dedicated
agent provisioning, coalesces concurrent requests, and does not initiate OAuth
or activate the Team policy.
Voice models and voice choice use a separate nonsecret versioned policy. Initial environment audio pins are preserved. Audio options are a versioned compatible endpoint registry intersected with API-key model availability on manual refresh; unverified availability is shown explicitly. Calls and memo transcriptions capture their configuration before the first await. Text provider/model changes do not reconfigure audio or replace active WebRTC sessions.
API and operational contract
- Personal:
/api/account/model-providers/catalogand/defaults. - Admin:
/api/admin/workspace/model-providers/catalog,/defaults(?workload=teamselects Team rather than Background),/team/connection(plus/connectand/cancel),/voice(plus/refresh). - Catalog refresh is POST; defaults and voice updates are PUT with a revision.
- Existing
/api/account/openaiand admin workspace ChatGPT routes remain compatible. Browser-provided owner IDs cannot choose another personal agent. - Internal runtime routes require the existing workspace control bearer token. Public writes require active/admin authorization, same origin and CSRF; expensive catalog/default/login operations are rate limited.
Release requires an operator-managed database/native-state backup, image build, migration and coordinated control-plane/workspace restart. Deployment and real provider calls are separate operator steps, not part of repository validation. After restart verify background API auth, two independent personal accounts, dedicated Team sign-in/activation, a summon by a member without personal auth, an explicit automation pin, and WebRTC/memo transcription. Do not claim provider smoke tests have passed based only on synthetic tests. Rollback must preserve the native credential stores and restore the prior policy/config backup together; do not drop policy tables or newly created credentials as an automatic rollback.
Remaining release gates and extensions
Managed Codex version consistency
The image points both plugin-local and application-level managed Codex launchers to the pinned workspace installation, covering source and packaged plugin roots. OpenClaw's package-first resolution otherwise selects its older bundled dependency despite a newer Codex being present on PATH. We retain managed launch semantics and account-isolated homes rather than using the custom command override, which would alter managed feature discovery. Startup verifies both managed and shell launcher versions against the release pin; the catalog exposes that verified version. Refresh performs model discovery, not software installation or policy application. Model eligibility remains account-scoped; fixing the runtime version does not guarantee access to a specific model.
Claude personal and shared subscription connections are intentionally unavailable. They require a provider-approved third-party route and a pinned, per-account native Claude CLI/SDK integration that owns login/refresh and passes isolation tests. No pasted subscription tokens, pooled personal logins, connector OAuth substitution, or API-billing masquerade is implemented. API-only Claude would not fulfill the subscription requirement. General user-created named connections and advanced service-tier controls remain extensions beyond the fixed bindings implemented here; they must not be enabled without corresponding native capability/credential routing support.
References: OpenAI model metadata, Astra compatibility, Realtime voices, Claude SDK authentication gate.