Skip to content

feat: api_key_env for custom_providers - #4674

Closed
iws17 wants to merge 3 commits into
NousResearch:mainfrom
iws17:feat/api-key-env
Closed

feat: api_key_env for custom_providers#4674
iws17 wants to merge 3 commits into
NousResearch:mainfrom
iws17:feat/api-key-env

Conversation

@iws17

@iws17 iws17 commented Apr 3, 2026

Copy link
Copy Markdown

Summary

  • Adds api_key_env field to custom_providers entries in config.yaml — names an environment variable to resolve at runtime instead of storing the literal API key in the config file
  • When both api_key and api_key_env are present, api_key_env wins (incremental migration)
  • Write-back paths are guarded so resolved secrets are never leaked back into config.yaml or auth.json

Motivation

Custom providers currently require hardcoding API keys in config.yaml and auth.json. This is a security concern — config files end up in backups, dotfile repos, and are readable by any process. Environment variables are the standard way to manage secrets, and every other provider type in Hermes already supports env var resolution.

Example

# Before (literal key in config file)
custom_providers:
- name: Api.x.ai
  base_url: https://api.x.ai/v1
  api_key: xai-LITERAL-SECRET-HERE

# After (secret stays in env)
custom_providers:
- name: Api.x.ai
  base_url: https://api.x.ai/v1
  api_key_env: XAI_API_KEY

Changes

File What
hermes_cli/runtime_provider.py New resolve_custom_api_key() helper; patched _get_named_custom_provider and _resolve_named_custom_runtime
agent/credential_pool.py _seed_custom_pool() uses resolver instead of literal read
hermes_cli/main.py Menu builder resolves via helper; _model_flow_named_custom guards write-back to prevent secret leakage

Test plan

  • Unit smoke tests: env resolution, precedence, fallback, missing var
  • Full test suite: 4007 passed (2 pre-existing failures unrelated to this change)
  • Manual: configure api_key_env, verify hermes resolves and authenticates
  • Manual: run hermes model flow, verify config.yaml is not polluted with resolved secret

🤖 Generated with Claude Code

… env vars

Adds an `api_key_env` field to custom_providers entries in config.yaml
that names an environment variable to read at runtime, instead of storing
the literal API key in the config file.

When both `api_key` and `api_key_env` are present, `api_key_env` wins so
operators can migrate incrementally. The credential pool, runtime provider
resolution, and model setup flows all use the new resolver. Write-back
paths are guarded so resolved secrets are never leaked back into config.yaml.

Example config:
```yaml
custom_providers:
- name: Api.x.ai
  base_url: https://api.x.ai/v1
  api_key_env: XAI_API_KEY
```

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 3, 2026 00:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds support for resolving API keys for custom_providers entries from an environment variable (api_key_env) at runtime, to avoid storing secrets in config.yaml/auth.json and to support incremental migration from literal api_key.

Changes:

  • Introduces resolve_custom_api_key() and uses it when resolving named custom providers at runtime.
  • Updates CLI custom-provider selection/model flow to avoid writing env-resolved secrets back into config.yaml.
  • Updates custom credential pool seeding to use the same resolver for custom_providers entries.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
hermes_cli/runtime_provider.py Adds resolve_custom_api_key() and uses it when loading named custom provider config for runtime resolution.
hermes_cli/main.py Resolves custom provider API key via helper for menu flows and guards config write-back to prevent secret leakage.
agent/credential_pool.py Seeds custom provider pools using the resolver (supports api_key_env as well as api_key).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hermes_cli/runtime_provider.py Outdated
Comment thread hermes_cli/main.py Outdated
Comment thread hermes_cli/main.py
Comment on lines 970 to 979
saved_model = entry.get("model", "")
model_hint = f" — {saved_model}" if saved_model else ""
providers.append((key, f"{name} ({short_url}){model_hint}"))
from hermes_cli.runtime_provider import resolve_custom_api_key
_custom_provider_map[key] = {
"name": name,
"base_url": base_url,
"api_key": entry.get("api_key", ""),
"api_key": resolve_custom_api_key(entry),
"api_key_env": entry.get("api_key_env", ""), # preserve source flag
"model": saved_model,

Copilot AI Apr 3, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Importing resolve_custom_api_key inside the for-loop causes a redundant import statement on each iteration and makes the loop harder to read. Prefer moving the import to the top of select_provider_and_model() (or at least above the loop) since this isn’t a conditional dependency.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot apply changes based on this feedback

Comment thread agent/credential_pool.py
iws17 and others added 2 commits April 2, 2026 19:35
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@iws17

iws17 commented Apr 28, 2026

Copy link
Copy Markdown
Author

Closing this — the underlying capability (env-var-resolved API keys for custom providers) now exists upstream via pconfig.api_key_env_vars, which _seed_custom_pool consumes natively in agent/credential_pool.py on main. That mechanism replaced the api_key_env-on-the-config-entry approach this PR took, and ties into the credential-source-removal unification (2c69b3ec, b341b19f, 8443998d) which arrived after this PR.

No need to carry this forward — api_key_env_vars covers the same use case more cleanly.

@iws17 iws17 closed this Apr 28, 2026
@alt-glitch alt-glitch added type/feature New feature or request P2 Medium — degraded but workaround exists area/config Config system, migrations, profiles area/auth Authentication, OAuth, credential pools labels Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools area/config Config system, migrations, profiles P2 Medium — degraded but workaround exists type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants