hermes - ✅(Solved) Fix custom provider named codex is rewritten to openai-codex in auxiliary paths [2 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#17488Fetched 2026-04-30 06:47:11
View on GitHub
Comments
0
Participants
1
Timeline
7
Reactions
0
Participants
Timeline (top)
labeled ×4cross-referenced ×2referenced ×1

Error Message

  1. If codex is intended to be a reserved provider alias, reject or warn when users create a custom provider with that name.

Root Cause

agent/auxiliary_client.py normalizes the provider name before resolving named custom providers:

def _normalize_aux_provider(provider: Optional[str]) -> str:
    normalized = (provider or "auto").strip().lower()
    if normalized.startswith("custom:"):
        suffix = normalized.split(":", 1)[1].strip()
        if not suffix:
            return "custom"
        normalized = suffix
    if normalized == "codex":
        return "openai-codex"

Because this happens before named custom provider resolution, a legitimate custom provider named codex is forcibly rewritten to openai-codex. That sends the request down the built-in OAuth provider path instead of the configured custom endpoint.

This is especially confusing because custom:<name> syntax still strips to the same suffix and then applies the same alias:

custom:codex -> codex -> openai-codex

Fix Action

Workaround

Rename the custom provider from codex to something not reserved, e.g. ccs-codex.

PR fix notes

PR #17498: fix(agent): preserve custom codex provider aliases

Description (problem / solution / changelog)

What does this PR do?

Fixes auxiliary provider resolution when a user-defined provider is named codex.

Before this change, resolve_provider_client() normalized aliases before checking named custom providers:

custom:codex -> codex -> openai-codex
codex        -> openai-codex

That meant a configured local/custom endpoint named codex was bypassed and Hermes tried to find OpenAI Codex OAuth credentials instead. This PR gives the raw requested provider name a chance to resolve against providers: / custom_providers: before the built-in codex -> openai-codex alias wins.

The existing alias behavior is preserved when no custom provider named codex exists.

Related Issue

Fixes #17488

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • agent/auxiliary_client.py
    • Preserve the raw requested provider string in resolve_provider_client().
    • Resolve named custom providers with that raw name before built-in aliases route to OAuth-backed providers.
    • Keep the normalized-provider custom lookup so existing named-provider behavior remains intact.
  • tests/agent/test_auxiliary_named_custom_providers.py
    • Add regression coverage for a custom provider named codex.
    • Add coverage for explicit custom:codex.
    • Add coverage that bare codex still resolves to built-in openai-codex when no custom provider shadows it.

How to Test

  1. Configure a custom provider named codex:

    model:
      default: gpt-5.4
      provider: codex
    
    custom_providers:
      - name: codex
        base_url: http://127.0.0.1:8317/api/provider/codex
        api_key: ccs-internal-managed
        model: gpt-5.4
  2. Resolve an auxiliary client for codex.

  3. Confirm it uses the configured custom endpoint instead of the built-in openai-codex OAuth path.

Automated checks run:

PYTHONPATH=/private/tmp/hermes-agent-pr /Users/ansel/.hermes/hermes-agent/venv/bin/python -m pytest tests/agent/test_auxiliary_named_custom_providers.py tests/agent/test_auxiliary_client.py::TestNormalizeAuxProvider tests/agent/test_auxiliary_client.py::TestTryPaymentFallback -q
# 35 passed

PYTHONPATH=/private/tmp/hermes-agent-pr /Users/ansel/.hermes/hermes-agent/venv/bin/python -m pytest tests/agent/test_auxiliary_client.py -q
# 110 passed

git diff --check

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

For New Skills

N/A.

Screenshots / Logs

N/A. This is provider-resolution logic covered by unit tests.

Changed files

  • agent/auxiliary_client.py (modified, +103/-82)
  • tests/agent/test_auxiliary_named_custom_providers.py (modified, +56/-0)

PR #17504: fix(agent): preserve explicit custom:codex auxiliary routing

Description (problem / solution / changelog)

Avoid rewriting custom:codex to the built-in openai-codex alias in auxiliary provider normalization so named custom providers can be resolved reliably. Add regression tests for normalization and end-to-end custom provider client resolution.

Made-with: Cursor

What does this PR do?

This PR fixes an auxiliary provider normalization bug where custom:codex was incorrectly rewritten to the built-in openai-codex alias.
That rewrite prevented users from targeting a named custom provider literally called codex.

The fix preserves explicit custom:codex routing while keeping the existing codex -> openai-codex alias behavior for non-custom paths.
This is a minimal, targeted change with regression coverage to prevent future breakage.

Related Issue

Fixes #17488

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • Updated agent/auxiliary_client.py:
    • In _normalize_aux_provider(...), preserve explicit custom:codex instead of rewriting it to openai-codex.
    • Keep existing alias mapping for bare codex unchanged.
  • Updated tests/agent/test_auxiliary_named_custom_providers.py:
    • Added regression test to assert custom:codex normalization is preserved.
    • Added end-to-end resolution test for resolve_provider_client("custom:codex", ...) against a named custom provider.

How to Test

  1. Run:
    pytest tests/agent/test_auxiliary_named_custom_providers.py -q -n 4

Changed files

  • agent/auxiliary_client.py (modified, +5/-0)
  • tests/agent/test_auxiliary_named_custom_providers.py (modified, +17/-0)

Code Example

model:
  default: gpt-5.4
  provider: codex
  context_length: 200000

custom_providers:
  - name: codex
    base_url: http://127.0.0.1:8317/api/provider/codex
    api_key: ccs-internal-managed
    api_mode: anthropic_messages
    model: gpt-5.4
    models:
      gpt-5.4:
        context_length: 200000

---

WARNING agent.auxiliary_client: resolve_provider_client: openai-codex requested but no Codex OAuth token found (run: hermes model)

---

http://127.0.0.1:8317/api/provider/codex

---

model:
  default: gpt-5.4
  provider: ccs-codex

custom_providers:
  - name: ccs-codex
    base_url: http://127.0.0.1:8317/api/provider/codex
    api_key: ccs-internal-managed
    api_mode: anthropic_messages
    model: gpt-5.4

---

def _normalize_aux_provider(provider: Optional[str]) -> str:
    normalized = (provider or "auto").strip().lower()
    if normalized.startswith("custom:"):
        suffix = normalized.split(":", 1)[1].strip()
        if not suffix:
            return "custom"
        normalized = suffix
    if normalized == "codex":
        return "openai-codex"

---

custom:codex -> codex -> openai-codex
RAW_BUFFERClick to expand / collapse

Bug Description

A user-defined custom_providers entry named codex is treated as the built-in openai-codex provider in auxiliary paths. This causes auxiliary/title/compression routing to look for OpenAI Codex OAuth credentials even though the main model is configured to use a local/custom endpoint with its own base_url and api_key.

Renaming the custom provider from codex to a non-reserved name such as ccs-codex immediately stops the warning and allows auxiliary auto-detection to use the custom endpoint.

Steps to Reproduce

Example config:

model:
  default: gpt-5.4
  provider: codex
  context_length: 200000

custom_providers:
  - name: codex
    base_url: http://127.0.0.1:8317/api/provider/codex
    api_key: ccs-internal-managed
    api_mode: anthropic_messages
    model: gpt-5.4
    models:
      gpt-5.4:
        context_length: 200000

Run a normal Hermes agent invocation or gateway message that triggers auxiliary work such as title generation / compression / auto-detect.

Expected Behavior

If custom_providers[].name == "codex" exists, Hermes should resolve provider: codex to the user-defined custom provider for auxiliary paths, or at minimum avoid silently remapping it to the built-in OAuth provider.

Custom provider names should not be shadowed by provider aliases without an explicit conflict warning.

Actual Behavior

Auxiliary routing logs:

WARNING agent.auxiliary_client: resolve_provider_client: openai-codex requested but no Codex OAuth token found (run: hermes model)

In the affected setup, no OpenAI Codex OAuth token is expected or required because the configured endpoint is a local CCS / CLIProxy bridge:

http://127.0.0.1:8317/api/provider/codex

Renaming the provider fixes the issue:

model:
  default: gpt-5.4
  provider: ccs-codex

custom_providers:
  - name: ccs-codex
    base_url: http://127.0.0.1:8317/api/provider/codex
    api_key: ccs-internal-managed
    api_mode: anthropic_messages
    model: gpt-5.4

After the rename, repeated hermes -z health checks completed without the openai-codex requested warning.

Affected Component

  • Agent Core
  • Configuration

Platform

N/A (CLI and gateway auxiliary paths)

Environment

  • OS: macOS
  • Hermes source: NousResearch/hermes-agent
  • Local bridge: CCS CLIProxy Plus at http://127.0.0.1:8317
  • Model: gpt-5.4
  • Custom provider API mode: anthropic_messages

Root Cause Analysis

agent/auxiliary_client.py normalizes the provider name before resolving named custom providers:

def _normalize_aux_provider(provider: Optional[str]) -> str:
    normalized = (provider or "auto").strip().lower()
    if normalized.startswith("custom:"):
        suffix = normalized.split(":", 1)[1].strip()
        if not suffix:
            return "custom"
        normalized = suffix
    if normalized == "codex":
        return "openai-codex"

Because this happens before named custom provider resolution, a legitimate custom provider named codex is forcibly rewritten to openai-codex. That sends the request down the built-in OAuth provider path instead of the configured custom endpoint.

This is especially confusing because custom:<name> syntax still strips to the same suffix and then applies the same alias:

custom:codex -> codex -> openai-codex

Proposed Fix

Resolve named custom providers before applying built-in aliases, or preserve the custom:<name> namespace as authoritative.

Possible approaches:

  1. In _normalize_aux_provider, do not alias codex to openai-codex when the original provider was prefixed as custom:codex.
  2. In resolve_provider_client, check custom_providers / providers for an exact name match before the built-in codex -> openai-codex alias is applied.
  3. If codex is intended to be a reserved provider alias, reject or warn when users create a custom provider with that name.

Preferred behavior: user-defined provider names should win over aliases when the current config contains an exact custom provider match.

Workaround

Rename the custom provider from codex to something not reserved, e.g. ccs-codex.

extent analysis

TL;DR

Renaming the custom provider from codex to a non-reserved name, such as ccs-codex, resolves the issue by avoiding the forced rewrite to openai-codex.

Guidance

  • Identify if the custom provider name conflicts with built-in provider aliases.
  • Check the _normalize_aux_provider function to see if it's rewriting the custom provider name to a built-in alias.
  • Consider renaming the custom provider to a unique name that doesn't conflict with built-in aliases.
  • Verify that the custom provider is correctly resolved by checking the resolve_provider_client function.

Example

# Before
custom_providers:
  - name: codex
    base_url: http://127.0.0.1:8317/api/provider/codex

# After
custom_providers:
  - name: ccs-codex
    base_url: http://127.0.0.1:8317/api/provider/codex

Notes

The issue is specific to the codex provider name, which is being forcibly rewritten to openai-codex. Renaming the custom provider to a unique name resolves the issue. A more permanent fix would involve modifying the _normalize_aux_provider function to preserve the custom:<name> namespace as authoritative.

Recommendation

Apply workaround: rename the custom provider to a non-reserved name, such as ccs-codex, to avoid conflicts with built-in aliases. This is a simple and effective solution that resolves the issue without requiring changes to the underlying code.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix custom provider named codex is rewritten to openai-codex in auxiliary paths [2 pull requests, 1 participants]