Skip to content

feat(config): extra HTTP headers for LLM API calls (#3526 salvage) - #841

Merged
hashbender merged 1 commit into
mainfrom
mirror/pr-57038
Jul 2, 2026
Merged

feat(config): extra HTTP headers for LLM API calls (#3526 salvage)#841
hashbender merged 1 commit into
mainfrom
mirror/pr-57038

Conversation

@hashbender

Copy link
Copy Markdown
Owner

Summary

Salvage of PR NousResearch#3526 by @jneeee ("support extra headers"), reimplemented against current main. Named providers / custom_providers entries in config.yaml now accept an extra_headers dict scoped to that endpoint — for reverse proxies, API gateways, and custom auth schemes (e.g. Cloudflare Access service tokens). model.extra_headers is also accepted as an alias of the existing global model.default_headers.

providers:
  my-proxy:
    base_url: "https://llm.internal.example.com/v1"
    key_env: "MY_PROXY_API_KEY"
    extra_headers:
      CF-Access-Client-Id: "xxxx.access"
      CF-Access-Client-Secret: "${CF_ACCESS_SECRET}"
      X-Client-Name: "hermes-agent"

Scope decisions vs. the original PR:

  • Main has since grown a global model.default_headers (Custom OpenAI-compatible provider can fail when upstream blocks OpenAI Python SDK default headers NousResearch/hermes-agent#40033); the remaining gap this PR fills is per-provider headers. Instead of threading a new extra_headers kwarg through AIAgent.__init__ → cli.py → gateway → smart routing (the original approach, 7 call sites), headers are resolved from config by base_url at client-construction time, mirroring the established per-provider TLS plumbing (apply_custom_provider_tls_to_client_kwargs). This automatically covers CLI, gateway, smart routing, credential swaps, and client rebuilds with zero signature churn.
  • Applied on the OpenAI-wire path only (chat_completions / codex_responses via the OpenAI SDK default_headers kwarg). Native Anthropic / Bedrock clients are explicitly scoped out, matching the existing model.default_headers behavior.
  • Headers survive _apply_client_headers_for_base_url re-application (credential rotation, interrupt rebuilds) — the original PR only set them at first construction.
  • The credential-pool propagation fix (pool result dropping extra_headers) flagged in the original PR review is included, with a regression test.
  • Header values are treated as secrets and are never logged.

Changes

  • hermes_cli/config.py — accept extra_headers in _normalize_custom_provider_entry (+ providers-dict translation, known-keys list); new get_custom_provider_extra_headers() / apply_custom_provider_extra_headers_to_client_kwargs() helpers (base_url match: case + trailing-slash insensitive, no substring bypass)
  • hermes_cli/runtime_provider.py — surface extra_headers in resolved runtimes for named custom providers: providers dict, legacy custom_providers list, and the credential-pool path
  • run_agent.py / agent/agent_init.py — merge per-provider headers onto OpenAI client default_headers at construction and on every header re-application; most-specific level wins
  • agent/auxiliary_client.pymodel.extra_headers alias for model.default_headers (merged, alias wins)
  • cli-config.yaml.example — commented documentation + example
  • scripts/release.py — AUTHOR_MAP attribution for @jneeee
  • Tests: tests/hermes_cli/test_custom_provider_extra_headers.py (7 new), tests/run_agent/test_custom_provider_extra_headers_client.py (4 new), +6 resolution tests in tests/hermes_cli/test_runtime_provider_resolution.py

Validation

Check Result
scripts/run_tests.sh tests/hermes_cli/test_custom_provider_extra_headers.py tests/run_agent/test_custom_provider_extra_headers_client.py -q ✅ 11/11 passed
scripts/run_tests.sh tests/hermes_cli/test_runtime_provider_resolution.py -q (153 incl. 6 new) ✅ passed
Regression: test_custom_provider_tls.py, test_provider_attribution_headers.py, test_auxiliary_user_default_headers.py, test_provider_config_validation.py ✅ 195/195 passed
ruff check on all touched files ✅ clean
Rebased on origin/main (rev-list count 0)

Infographic

extra headers infographic

Nous Research


Mirror-of: NousResearch#57038
NousResearch#57038

@hashbender
hashbender merged commit 04a72f2 into main Jul 2, 2026
2 checks passed
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