providers.json

Provider configuration lives in a global file at ~/.posit/ai/providers.json, separate from the general Config File, ~/.posit/assistant/settings.json.

The provider configuration modal writes this file for you as you add and edit providers.

Credentials never go in this file. Set API keys and tokens through the modal, which stores them separately.

For the list of supported providers, and for per-provider authentication and setup, see Providers.

Schema

The JSON schema lives at:

Posit Assistant points your file’s $schema at that URL when it first creates providers.json, and repairs the pointer if it is out of date. An editor with JSON Schema support then gives you completion, hover descriptions, and validation as you edit.

Settings reference

providers.json Settings Reference lists every key the file accepts, one table per provider. Look up a provider by its id:

ProviderProvider id
Posit AI Passpositai
Amazon Bedrockbedrock
Anthropicanthropic
Databricksdatabricks
DeepSeekdeepseek
GitHub Copilotcopilot
Google Geminigemini
Google Vertex AIgoogle-vertex
LiteLLMlitellm
LM Studiolmstudio
Microsoft Foundryms-foundry
Ollamaollama
OpenAIopenai
OpenAI Compatibleopenai-compatible
OpenRouteropenrouter
Portkeyportkey
Snowflake Cortexsnowflake-cortex
Custom providerscustom
Default (applies to every provider)default

Common configurations

You can combine any of these in one file.

Choosing which models appear

The models block controls what shows up in the model picker: discovery decides whether to ask the provider at all, allow and deny filter what comes back, overrides patches metadata on models it returns, and custom declares models it does not return itself. A provider that discovers its own models (through a /models endpoint) doesn’t need custom, but allow, deny, and overrides are still useful for trimming or adjusting what it reports.

{
  "providers": {
    "openai": {
      "models": {
        "allow": ["gpt-5.6", "gpt-5.6-mini"],
        "overrides": {
          "gpt-5.6": { "maxOutputTokens": 32000 }
        }
      }
    }
  }
}

Only allow specific providers

Set providers.default.enabled to false to hide every provider, then enable just the ones you want:

{
  "providers": {
    "default": { "enabled": false },
    "anthropic": { "enabled": true },
    "openai": { "enabled": true }
  }
}

Enforce settings from an administrator

An administrator can supply the same provider configuration through the POSIT_AI_PROVIDERS_ENFORCED environment variable, which users cannot override, or POSIT_AI_PROVIDERS_DEFAULT, which sets defaults. Each holds JSON with "version": 1 and a providers object.

Assistant applies every rule it understands, so a payload with settings it doesn’t know still keeps the rest of the rules:

  • A setting the installed version doesn’t recognize is removed and logged as a warning. The rest of the payload applies.
  • A provider block with a value the installed version can’t accept is dropped and logged as a warning. Other providers’ blocks still apply. This includes a block that uses a new allowed value for an existing setting, such as a provider type or protocol that an older version doesn’t know.
  • Neither case shows a notification in the app. Check the logs if a rule doesn’t take effect.
  • A payload that is unusable is ignored entirely, and the app shows a notification naming the environment variable. That happens for invalid JSON, a root or providers that isn’t an object, or a version other than 1.

Earlier releases are stricter: they ignore the whole payload, including the rules they understand, if it contains any setting they don’t recognize. Each Posit product that reads these variables includes its own copy of this logic, so update every one of them before adding new settings to a payload.

Route a provider through an enterprise proxy or gateway

Set a baseUrl for the proxy, plus any tenancy or routing headers it needs on every request:

{
  "providers": {
    "anthropic": {
      "baseUrl": "https://my-proxy.example.com/v1",
      "customHeaders": {
        "x-gateway-tenant": "team-42"
      }
    }
  }
}

Some providers need a version segment in that URL. See the baseUrl row in the settings reference.

customHeaders carries non-secret tenancy or routing metadata only. Assistant strips reserved headers such as Authorization and x-api-key, so use the provider’s credential field for anything that needs to authenticate. Four providers ignore customHeaders altogether: copilot, google-vertex, ollama, and lmstudio.

Connect Portkey to a self-hosted open-source gateway

A self-hosted Portkey OSS gateway is stateless: it forwards the API key of one upstream service, so the built-in portkey provider needs "keyType": "upstream". One connection serves one upstream; for many providers through one connection, use hosted Portkey or a hybrid gateway. The gateway lists no models, so declare the ones you use in models.custom. /v1 is added to the base URL.

Fronting Anthropic (the default upstream), the key is your Anthropic API key. Claude models need no protocol; they use the Anthropic wire protocol, with prompt caching and extended thinking:

{
  "providers": {
    "portkey": {
      "baseUrl": "http://localhost:8787",
      "keyType": "upstream",
      "models": {
        "custom": [
          {
            "id": "claude-sonnet-4-6",
            "name": "Claude Sonnet 4.6",
            "maxContextLength": 200000,
            "supportsTools": true,
            "supportsImages": true,
            "supportsToolResultImages": true,
            "supportsWebSearch": false
          }
        ]
      }
    }
  }
}

For a different upstream, set the x-portkey-provider routing header and give each model the matching protocol. Here the key is your OpenAI API key:

{
  "providers": {
    "portkey": {
      "baseUrl": "http://localhost:8787",
      "keyType": "upstream",
      "customHeaders": {
        "x-portkey-provider": "openai"
      },
      "models": {
        "custom": [
          {
            "id": "gpt-4o-mini",
            "name": "GPT-4o mini",
            "maxContextLength": 128000,
            "supportsTools": true,
            "supportsImages": true,
            "supportsToolResultImages": false,
            "supportsWebSearch": false,
            "protocol": "openai-chat"
          }
        ]
      }
    }
  }
}

Then enter the provider’s key in the settings UI, which keeps the key type, or set PORTKEY_API_KEY. PORTKEY_KEY_TYPE=upstream is the environment-variable equivalent of keyType. A non-hosted base URL without keyType also means a provider key, so when the settings UI saves this connection it leaves keyType out of providers.json, because older Posit Assistant versions ignore a portkey block that sets it.

Redirect models that use different protocols

When a provider’s models do not all use the same API protocol, one baseUrl cannot redirect them all. Use endpoints to redirect every model on one protocol, or models.overrides to redirect a single model. Bedrock is the provider where this usually comes up:

{
  "providers": {
    "bedrock": {
      "endpoints": {
        "openai-chat": "https://my-proxy.example.com/bedrock/openai"
      },
      "models": {
        "overrides": {
          "openai.gpt-oss-120b": { "baseUrl": "https://my-proxy.example.com/gpt-oss" }
        }
      }
    }
  }
}

For each model, Assistant uses the first URL it finds in this order:

OrderWhere the URL comes fromApplies to
1models.overrides["<model-id>"].baseUrlThe single model named in the key
2endpoints["<protocol>"]Every model using that protocol, such as openai-chat for gpt-oss models or openai-responses for GPT-5.x
3The endpoint the provider reportsModels with no override above
4baseUrlModels the provider reports no endpoint for

Claude models on Bedrock are the exception: they always go through the Anthropic Messages or Converse API using its AWS SDK endpoint, so none of the above applies to them.

Supply the API key from a command

Set apiKeyHelper to run a command that prints the provider’s API key, for keys that rotate or come from a secrets vault. Assistant runs the command when it needs the key and uses the first non-empty line the command prints:

{
  "providers": {
    "anthropic": {
      "apiKeyHelper": {
        "command": "vault",
        "args": ["kv", "get", "-field=api_key", "secret/anthropic"]
      }
    },
    "custom": {
      "Acme Gateway": {
        "type": "openai-compatible",
        "baseUrl": "https://llm.acme.internal/v1",
        "apiKeyHelper": { "command": "acme-token --audience llm" }
      }
    }
  }
}

With args, command is the program to run and nothing passes through a shell. Without args, command is one line run by the system shell, so pipes and quoting work. The command runs in your home directory with the PA_PROVIDER environment variable set to the provider id. Assistant reuses a key for refreshIntervalMs (default 300000, five minutes; 0 keeps it until restart) and stops waiting after timeoutMs (default 10000).

When a provider has an apiKeyHelper, the command is the only source of its key. A saved key or an API key environment variable for that provider is ignored, and the provider shows as managed by an API key helper command, with no way to change its key in the app. If the command fails, the provider is unavailable and shows one of these messages until the command works again. Assistant waits 30 seconds before retrying a failed command.

MessageMeaning
The API key helper command could not be started.The program was not found or could not be run.
The API key helper command timed out.The command ran longer than timeoutMs.
The API key helper command exited with an error.The command exited with a non-zero status.
The API key helper command produced no output.The command printed nothing but blank lines.
The API key helper command’s output was too long.The command printed more than 64 KB.

For your security, Assistant never logs or displays the command line, its output, or its error output. To debug a failing command, run it yourself in a terminal.

Some notes:

  • An administrator can enforce a helper through POSIT_AI_PROVIDERS_ENFORCED. An enforced apiKeyHelper replaces a user’s whole apiKeyHelper rather than merging with it.
  • On a multi-user Standalone server, the command runs as the server’s user for every signed-in user, the same as an API key environment variable.
  • apiKeyHelper is not available for Snowflake Cortex, or for providers that don’t use an API key.
  • On a custom provider with apiKeyOptional, a failing command can still let one request go out with no key, which the endpoint rejects.
  • If the command exits but leaves a background process that keeps its output open, Assistant waits the full timeoutMs every time it runs the command before using the key.
  • Posit Assistant in Positron honors apiKeyHelper, but Positron’s own AI features read the same providers.json and don’t. Current Positron releases ignore any provider entry that contains apiKeyHelper, including that entry’s other settings such as baseUrl and customHeaders, so a custom provider with a helper does not appear in Positron at all. Positron shows a configuration warning and can’t save its own changes to the file while the field is present. Builds older than 2026.09.0-128 reject the whole file. If you also use Positron, add a helper only to providers you don’t need there.