Skip to content

custom provider named codex is rewritten to openai-codex in auxiliary paths #17488

@zhonghui5207

Description

@zhonghui5207

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsarea/configConfig system, migrations, profilescomp/agentCore agent loop, run_agent.py, prompt buildertype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions