Skip to content

OpenAI fallback graph uses active-provider model IDs #324

Description

@jstar0

Bug

When SkillSpector falls back to OPENAI_API_KEY, the graph still assigns model
IDs from the active metadata provider. The analyzer client and model label can
therefore disagree.

With the default provider unconfigured and only OPENAI_API_KEY set, current
main produces:

active provider : NvBuildProvider
graph default   : deepseek-ai/deepseek-v4-flash
chat client     : ChatOpenAI
client model    : deepseek-ai/deepseek-v4-flash

build_context() calls build_model_config(), which resolves every slot from
get_metadata_provider(). The analyzers then pass those labels explicitly to
get_chat_model(model=...). Because the model is explicit, the OpenAI-aware
default in _resolve_default_chat_model() is not used, even though
create_chat_model() selects the OpenAI fallback client.

Reproduction

On current main, clear the provider-specific credentials and provider/model
selection, set a test OPENAI_API_KEY, then inspect the graph model and the
constructed client:

from skillspector.constants import build_model_config
from skillspector.llm_utils import get_chat_model

model = build_model_config()["default"]
llm = get_chat_model(model=model)
print(model)
print(type(llm).__name__)
print(getattr(llm, "model_name", None) or getattr(llm, "model", None))

The result is a ChatOpenAI client configured with
deepseek-ai/deepseek-v4-flash rather than the OpenAI default.

Expected behavior

Generated model configuration should follow the provider that will construct
the chat model. Explicit global/per-slot overrides, configured active providers,
CLI providers, and scoped provider bindings should retain their existing
precedence.

Related work

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions