Extend apiKeyOptional to built-in providers
Background
#91 asked for authentication-free enterprise proxy endpoints: a local proxy performs SSO authentication, so the assistant must not send or store an API key.
That was delivered for custom providers via a new per-entry apiKeyOptional: true field in providers.json (ai-lib: posit-dev/ai-lib#109):
- Custom
openai-compatible entries were already key-optional by provider type.
- Custom
anthropic entries can now set apiKeyOptional: true. When set, an empty API key means "send no credentials": model discovery sends only the anthropic-version header, and chat strips x-api-key/Authorization before the request is sent (with care taken so an ambient ANTHROPIC_API_KEY environment variable is never picked up).
- The field flows through layered config, so an administrator can set or enforce it fleet-wide.
The gap
Built-in (non-custom) providers still always require a key. Their key-requirement is fixed per provider type, and the providers.json schema does not accept apiKeyOptional on built-in entries.
This matters for the same enterprise-proxy scenario: a user may point a built-in provider's baseUrl at a pre-authenticated endpoint — for example the built-in anthropic provider with baseUrl set to a local SSO proxy, or openai/gemini/deepseek/openrouter/ms-foundry pointed at a corporate gateway. Today the only workarounds are to redeclare the endpoint as a custom provider (not possible for every protocol) or to configure a dummy key (misleading, and may cause an unnecessary Authorization header to be sent).
Provider types that already work without a key (openai-compatible, litellm, portkey) and types that use non-API-key authentication (aws, google-vertex, snowflake, and the local providers ollama/lmstudio) would not need this field.
Proposal
Allow apiKeyOptional: true on built-in provider entries in providers.json, with the same semantics as the custom-provider field:
- A provider is key-optional if its type is inherently key-optional OR the entry sets the flag.
- The field participates in layered config (user / admin default / admin enforced), and each resolved entry records where the policy came from.
- Editing only this field triggers a live reload of the provider.
- When the policy is on, no auth headers are sent on the wire for discovery or chat, and no credential is stored.
Considerations
- Per-protocol wire behavior. The keyless handling added for Anthropic (placeholder key for the SDK, header stripping before sending and before raw request logging) was protocol-specific. Each additional protocol needs the same treatment and wire-level tests proving no auth header — and no ambient environment variable — leaks onto the wire.
- UI surfaces. Positron's native provider dialog and the Posit Assistant provider manager currently require a key for these types; they would need to accept a blank key when the policy is on.
- Host compatibility. As with the custom-provider field, older hosts that don't know the field may drop or reject config that uses it; the same capability-gating approach used for the custom field should apply.
Extend
apiKeyOptionalto built-in providersBackground
#91 asked for authentication-free enterprise proxy endpoints: a local proxy performs SSO authentication, so the assistant must not send or store an API key.
That was delivered for custom providers via a new per-entry
apiKeyOptional: truefield inproviders.json(ai-lib: posit-dev/ai-lib#109):openai-compatibleentries were already key-optional by provider type.anthropicentries can now setapiKeyOptional: true. When set, an empty API key means "send no credentials": model discovery sends only theanthropic-versionheader, and chat stripsx-api-key/Authorizationbefore the request is sent (with care taken so an ambientANTHROPIC_API_KEYenvironment variable is never picked up).The gap
Built-in (non-custom) providers still always require a key. Their key-requirement is fixed per provider type, and the
providers.jsonschema does not acceptapiKeyOptionalon built-in entries.This matters for the same enterprise-proxy scenario: a user may point a built-in provider's
baseUrlat a pre-authenticated endpoint — for example the built-inanthropicprovider withbaseUrlset to a local SSO proxy, oropenai/gemini/deepseek/openrouter/ms-foundrypointed at a corporate gateway. Today the only workarounds are to redeclare the endpoint as a custom provider (not possible for every protocol) or to configure a dummy key (misleading, and may cause an unnecessaryAuthorizationheader to be sent).Provider types that already work without a key (
openai-compatible,litellm,portkey) and types that use non-API-key authentication (aws,google-vertex,snowflake, and the local providersollama/lmstudio) would not need this field.Proposal
Allow
apiKeyOptional: trueon built-in provider entries inproviders.json, with the same semantics as the custom-provider field:Considerations