Skip to content

feat(config, llm): Read an API key from a list of env vars - #1244

Merged
JeanMertz merged 2 commits into
mainfrom
multi-key-support
Oct 6, 2026
Merged

JeanMertz merged 2 commits into
mainfrom
multi-key-support

Conversation

@JeanMertz

Copy link
Copy Markdown
Collaborator

api_key_env accepts a list of environment variables. The list is one key: JP reads the variables in order and uses the first one holding a non-empty value. A blank value falls through to the next variable, as it already falls through between auth chain entries.

[providers.llm.vllm]
api_key_env = ["WORK_KEY", "USER_KEY"]

A named key in the map form may be a list too. api_key:work then tries each of its variables before the auth chain moves on to the next entry, and still reports the credential as api_key:work:

api_key_env = { work = ["WORK_KEY", "WORK_KEY_OLD"], personal = "KEY" }

When nothing in a list is set, the error names every variable tried (Missing environment variable: WORK_KEY or USER_KEY). A named key with an empty list is reported by its name rather than as a missing variable with no name. --cfg accepts both shapes in JSON form, e.g. --cfg 'providers.llm.vllm.api_key_env:=["A","B"]', where it rejected arrays before. jp provider ls lists one api_key row per variable, in the order they are tried, so it shows which one is set.

Applies to every provider with an api_key_env: Anthropic, Cerebras, DeepSeek, Google, OpenAI, OpenRouter, and vLLM. Existing string and map configs are unchanged.

`api_key_env` accepts a list of environment variables. The list is one
key: JP reads the variables in order and uses the first one holding a
non-empty value. A blank value falls through to the next variable, as
it already falls through between `auth` chain entries.

```toml
[providers.llm.vllm]
api_key_env = ["WORK_KEY", "USER_KEY"]
```

A named key in the map form may be a list too. `api_key:work` then
tries each of its variables before the `auth` chain moves on to the
next entry, and still reports the credential as `api_key:work`:

```toml
api_key_env = { work = ["WORK_KEY", "WORK_KEY_OLD"], personal = "KEY" }
```

When nothing in a list is set, the error names every variable tried
(`Missing environment variable: WORK_KEY or USER_KEY`). A named key
with an empty list is reported by its name rather than as a missing
variable with no name. `--cfg` accepts both shapes in JSON form, e.g.
`--cfg 'providers.llm.vllm.api_key_env:=["A","B"]'`, where it rejected
arrays before. `jp provider ls` lists one `api_key` row per variable,
in the order they are tried, so it shows which one is set.

Applies to every provider with an `api_key_env`: Anthropic, Cerebras,
DeepSeek, Google, OpenAI, OpenRouter, and vLLM. Existing string and map
configs are unchanged.

Signed-off-by: Jean Mertz <git@jeanmertz.com>
Nothing converts a `String` into `KeyVariables`; every caller builds one
from a `&str` or a variant constructor. The impl was also a trivial
wrap, which rustqual counts as boilerplate (BP-001), and it pushed
`boilerplate_warnings` one above the committed baseline, failing
`just qual-ci`.

Signed-off-by: Jean Mertz <git@jeanmertz.com>
@JeanMertz
JeanMertz merged commit c50cd1d into main Oct 6, 2026
45 checks passed
@JeanMertz
JeanMertz deleted the multi-key-support branch October 6, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant