Skip to content

feat(providers): add SCX.ai as a JSON-configured OpenAI-compatible provider - #34752

Merged
mateo-berri merged 12 commits into
BerriAI:litellm_internal_stagingfrom
SouthernCrossAI:litellm_scx_ai_provider
Aug 22, 2026
Merged

feat(providers): add SCX.ai as a JSON-configured OpenAI-compatible provider#34752
mateo-berri merged 12 commits into
BerriAI:litellm_internal_stagingfrom
SouthernCrossAI:litellm_scx_ai_provider

Conversation

@bhuvan2134686

@bhuvan2134686 bhuvan2134686 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • SCX.ai is not a supported provider, so callers have to route through openai/ with a custom api_base
  • SCX.ai takes max_tokens rather than max_completion_tokens, and caps temperature

How it solves it:

  • Registers scx-ai in litellm/llms/openai_like/providers.json with the parameter mapping and the ceiling as a constraint, so no Python module is needed
  • Adds GLM-5.2 and Qwen3.8 Max to the cost map, and registers the provider in the endpoint matrix and the dashboard

Relevant issues

Docs live in the other repo, so the provider page goes up separately in BerriAI/litellm-docs#808. That one is a prerequisite here: documentation and code-quality both run tests/documentation_tests/test_env_keys.py, which checks out BerriAI/litellm-docs and fails while SCX_API_KEY is read under ./litellm but mentioned nowhere in the docs. Both jobs go green once it merges

Linear ticket

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

All captured at 1e24f93d3 against the real SCX.ai API, with the proxy started as LITELLM_LOCAL_MODEL_COST_MAP=True python litellm/proxy/proxy_cli.py --config scx_config.yaml --port 4000 on a config with both models pointed at os.environ/SCX_API_KEY

Chat completions, with the cost header showing the new rates being applied

$ for m in scx-glm-5.2 scx-qwen3.8-max; do
    curl -sS -D /tmp/h_$m.txt http://localhost:4000/v1/chat/completions \
      -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" \
      -d "{\"model\":\"$m\",\"messages\":[{\"role\":\"user\",\"content\":\"Reply with exactly: hello from SCX\"}],\"max_tokens\":2048}" \
      | jq -c "{m:\"$m\", content: .choices[0].message.content}"
    grep -i "^x-litellm-response-cost:" /tmp/h_$m.txt
  done

{"m":"scx-glm-5.2","content":"hello from SCX"}
x-litellm-response-cost: 0.0002285815
{"m":"scx-qwen3.8-max","content":"hello from SCX"}
x-litellm-response-cost: 0.0004901237

Tool calling and json_schema structured output on both

$ for m in scx-glm-5.2 scx-qwen3.8-max; do
    curl -sS http://localhost:4000/v1/chat/completions -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" \
      -d "{\"model\":\"$m\",\"messages\":[{\"role\":\"user\",\"content\":\"What is the weather in Sydney? Use the tool.\"}],\"tools\":[{\"type\":\"function\",\"function\":{\"name\":\"get_weather\",\"description\":\"Get the weather for a city\",\"parameters\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"]}}}],\"max_tokens\":2048}" \
      | jq -c "{m:\"$m\", tool: .choices[0].message.tool_calls[0].function}"
  done

{"m":"scx-glm-5.2","tool":{"arguments":"{\"city\": \"Sydney\"}","name":"get_weather"}}
{"m":"scx-qwen3.8-max","tool":{"arguments":"{\"city\": \"Sydney\"}","name":"get_weather"}}

$ for m in scx-glm-5.2 scx-qwen3.8-max; do
    curl -sS http://localhost:4000/v1/chat/completions -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" \
      -d "{\"model\":\"$m\",\"messages\":[{\"role\":\"user\",\"content\":\"City is Sydney\"}],\"response_format\":{\"type\":\"json_schema\",\"json_schema\":{\"name\":\"c\",\"schema\":{\"type\":\"object\",\"properties\":{\"city\":{\"type\":\"string\"}},\"required\":[\"city\"],\"additionalProperties\":false}}},\"max_tokens\":2048}" \
      | jq -c "{m:\"$m\", content: .choices[0].message.content}"
  done

{"m":"scx-glm-5.2","content":"{\n  \"city\": \"Sydney\"\n}"}
{"m":"scx-qwen3.8-max","content":"{\"city\":\"Sydney\"}"}

Image input on Qwen3.8 Max, which is the one of the two that declares supports_vision, sending a 64x64 solid red PNG as a data URI

$ IMG=$(base64 -i red64.png)
$ curl -sS http://localhost:4000/v1/chat/completions -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" \
    -d "{\"model\":\"scx-qwen3.8-max\",\"messages\":[{\"role\":\"user\",\"content\":[{\"type\":\"text\",\"text\":\"What colour fills this image? One word.\"},{\"type\":\"image_url\",\"image_url\":{\"url\":\"data:image/png;base64,$IMG\"}}]}],\"max_tokens\":2048}" \
    | jq -c '{content: .choices[0].message.content, image_tokens: .usage.prompt_tokens_details.image_tokens}'

{"content":"Red","image_tokens":66}

The Add Model form reads /public/providers/fields, which now returns the provider

$ curl -sS http://localhost:4000/public/providers/fields | jq -c '.[] | select(.litellm_provider=="scx-ai") | {provider, provider_display_name, default_model_placeholder}'

{"provider":"SCX_AI","provider_display_name":"SCX.ai","default_model_placeholder":"scx-ai/GLM-5.2"}

With that proxy running and npm run dev in ui/litellm-dashboard, Models and Endpoints then Add Model lists SCX.ai in the Provider dropdown with its logo

Type

New Feature

Changes

providers.json carries the base URL, SCX_API_KEY, the SCX_API_BASE override, the max_completion_tokens to max_tokens mapping and a temperature_max of 1.99. SCX accepts temperature in [0.0, 2.0) and returns a 400 on 2.0 exactly, and the clamp is an inclusive min(), so 2.0 would let through a value the endpoint rejects. The slug is registered in LlmProviders, the OpenAI-compatible provider and endpoint lists, the api base autodetection branch, and the endpoint support matrix

Two chat models go into the cost map. GLM-5.2 has a 1M context window and is text only; Qwen3.8 Max has a 1M window and takes image input. Both cap output at 131072, which is what the endpoint's own validator enforces rather than what the catalogue advertises, and both do implicit prompt caching, so each carries a cache read rate

The dashboard needs both the display metadata in provider_info_helpers.tsx and an entry in provider_create_fields.json, since the Add Model form renders from the latter

Tests cover registration, config values, model resolution, api base override and autodetection, the temperature clamp, the parameter mapping, router config, cost map and backup sync, the create-fields entry and the dashboard helpers

I work at SCX.ai

QA runbook

Export SCX_API_KEY, start the proxy on the config above and run the curl commands in the proof section

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

Note

Low Risk
Additive provider registration and pricing metadata only; no changes to auth, routing core, or existing providers.

Overview
Adds native scx-ai routing so callers can use scx-ai/<model> instead of a custom OpenAI api_base.

Registers the provider in providers.json with SCX_API_KEY / SCX_API_BASE, maps max_completion_tokensmax_tokens, and clamps temperature to 1.99 (SCX rejects 2.0). Chat-only. Cost map includes scx-ai/GLM-5.2 (text, ~1M context) and scx-ai/Qwen3.8-Max (vision), both with prompt-cache rates.

Dashboard Add Model lists SCX.ai with logo and credential fields. Tests cover resolution, autodetection, param mapping, temperature clamp, and metadata sync.

Reviewed by Cursor Bugbot for commit 7d9e375. Bugbot is set up for automated code reviews on this repo. Configure here.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@CLAassistant

CLAassistant commented Jul 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@greptile-apps

greptile-apps Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds SCX.ai as a JSON-configured OpenAI-compatible provider.

  • Registers provider resolution, endpoint support, environment configuration, parameter mapping, and temperature constraints.
  • Adds pricing and capability metadata for GLM-5.2 and Qwen3.8-Max.
  • Adds SCX.ai to the Add Model form with credential fields, display metadata, placeholder, and logo.
  • Adds tests covering provider registration, request parameter transformation, model metadata, and dashboard integration.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the SCX.ai entry now reaches the Add Model dropdown and maps through the form’s existing provider and credential submission contracts.

Important Files Changed

Filename Overview
litellm/llms/openai_like/providers.json Defines the SCX.ai base URL, environment variables, token-parameter mapping, temperature ceiling, and supported chat-completions endpoint.
litellm/litellm_core_utils/get_llm_provider_logic.py Adds SCX.ai provider and API-key detection for its canonical API base.
model_prices_and_context_window.json Registers SCX.ai model pricing, context limits, caching rates, and supported capabilities.
litellm/proxy/public_endpoints/provider_create_fields.json Adds the SCX.ai provider record consumed by the Add Model dropdown, fully resolving the prior missing-option report.
ui/litellm-dashboard/src/components/provider_info_helpers.tsx Adds SCX.ai display-name, slug, logo, and model-placeholder mappings.
tests/test_litellm/llms/openai_like/test_scx_ai_provider.py Tests provider registration, resolution, parameter transformation, metadata synchronization, and Add Model form availability.

Reviews (6): Last reviewed commit: "Merge remote-tracking branch 'origin/lit..." | Re-trigger Greptile

Comment thread ui/litellm-dashboard/src/components/provider_info_helpers.tsx
@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@bhuvan2134686

Copy link
Copy Markdown
Contributor Author

Good catch on the Add Model dropdown, the display mapping on its own was not enough. The provider is now in litellm/proxy/public_endpoints/provider_create_fields.json with a required API key and an optional api base, so /public/providers/fields returns it and the form can render it, plus a test in test_scx_ai_provider.py that fails if the entry ever goes missing

Verified against the live proxy

$ curl -sS http://localhost:4000/public/providers/fields | jq -c '.[] | select(.litellm_provider=="scx-ai")'

{"provider":"SCX_AI","provider_display_name":"SCX.ai","litellm_provider":"scx-ai","credential_fields":[{"key":"api_base","label":"API Base","placeholder":"https://api.scx.ai/v1","tooltip":null,"required":false,"field_type":"text","options":null,"default_value":null},{"key":"api_key","label":"API Key","placeholder":null,"tooltip":null,"required":true,"field_type":"password","options":null,"default_value":null}],"default_model_placeholder":"scx-ai/gpt-oss-120b"}

The same push adds the five chat models to the cost map with published rates and capability flags, which restores cost tracking and lets tools through, since supports_function_calling is derived from there. Tool calls now round trip against the live API

$ curl -sS http://localhost:4000/v1/chat/completions -H "Authorization: Bearer sk-1234" -H "Content-Type: application/json" \
    -d '{"model":"scx-gemma-4","messages":[{"role":"user","content":"What is the weather in Sydney? Use the tool."}],"tools":[{"type":"function","function":{"name":"get_weather","description":"Get the weather for a city","parameters":{"type":"object","properties":{"city":{"type":"string"}},"required":["city"]}}}],"max_tokens":128}' \
    | jq -c '.choices[0].message.tool_calls[0].function'

{"arguments":"{\"city\":\"Sydney\"}","name":"get_weather"}

The PR description is updated with the full run

@greptileai

@codspeed-hq

codspeed-hq Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 31 untouched benchmarks


Comparing SouthernCrossAI:litellm_scx_ai_provider (7d9e375) with litellm_internal_staging (ff02d5c)

Open in CodSpeed

@bhuvan2134686

Copy link
Copy Markdown
Contributor Author

Placeholder note is addressed, the Add Model model field now defaults to scx-ai/MiniMax-M2.7 for SCX.ai rather than falling back to the generic value, matching the default_model_placeholder in the provider metadata

Description trimmed as well

@greptileai

Replaces the five launch models with the two that SCX.ai now leads on.
Both are live on api.scx.ai and both were verified against it for tool
calling, json_object and json_schema output, reasoning, prompt caching,
and, for Qwen3.8 Max, image input

Pricing follows SCX's published USD rates. GLM-5.2 lands at $0.55/M input
and $1.9255/M output, tracking the recent GLM-5.2 market repricing;
Qwen3.8 Max at $1.815/M and $5.4461/M sits under the only other seller of
that model, and is the first Qwen3.8 Max entry in the catalog

Also corrects a metadata bug the removed entries carried: they set
max_tokens equal to max_input_tokens, conflating the context window with
the output cap. Both new entries declare a max_output_tokens of 131072,
which is what the endpoint's own validator enforces

The Add Model placeholder moves to scx-ai/GLM-5.2 now that MiniMax-M2.7
is no longer in the catalog
The constraint was 1.0, so anything above that was silently clamped down.
SCX accepts [0.0, 2.0), verified live against both GLM-5.2 and Qwen3.8
Max: 1.5, 1.99 and 1.999 all return 200, while 2.0 returns 400 with
"Temperature should be in [0.0, 2.0)"

Since the clamp is an inclusive min(), 2.0 cannot be the ceiling or it
would pass through a value the endpoint rejects. 1.99 is the practical
maximum

The clamp test now pins both ends: 2.5 comes back as 1.99, and 1.7 rides
through untouched where it used to be flattened to 1.0
@bhuvan2134686

Copy link
Copy Markdown
Contributor Author

Docs page is up in BerriAI/litellm-docs#808; the documentation and code-quality jobs here go green once it merges.

@bhuvan2134686

bhuvan2134686 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@greptileai please re-review. The model list changed since your last pass. @tin-berri, this adds SCX.ai; docs page is in BerriAI/litellm-docs#808.

…itellm_scx_ai_provider

# Conflicts:
#	ui/litellm-dashboard/src/components/provider_info_helpers.tsx
@bhuvan2134686

Copy link
Copy Markdown
Contributor Author

All review comments are addressed. The Greptile P1 on the Add Model dropdown is fixed and I have replied in the thread and resolved it; that was the only inline comment on this PR.

On the two red checks, code-quality and documentation both fail on the same assertion and neither is a defect in this branch. test-code-quality.yml checks out BerriAI/litellm-docs into docs/my-website without a ref, so it always reads litellm-docs main. The page that documents SCX_API_KEY lives on the branch behind BerriAI/litellm-docs#808, which is still open, so test_env_keys.py cannot see it and raises "Environment variables read under ./litellm but mentioned nowhere in the docs: [SCX_API_KEY]". No commit on this PR can turn those jobs green.

I reproduced both sides locally. Pointing docs/my-website at litellm-docs main gives exactly the CI error; pointing it at the #808 branch prints "Every environment variable read under ./litellm is documented". Merging #808 clears both jobs here.

I have also added SCX_API_KEY and SCX_API_BASE as rows in the environment variables reference table in docs/proxy/config_settings.md on #808, so the credentials are listed alongside the other providers rather than only on the provider page.

@greptileai please re-review. @tin-berri @ryan-crabbe-berri this is ready on the code side; the only thing gating green CI is the docs PR at BerriAI/litellm-docs#808.

@bhuvan2134686

Copy link
Copy Markdown
Contributor Author

@krrish-berri-2 @mateo-berri @ryan-crabbe-berri asking for a look when one of you has a moment. This has been open since 27 July with a review request that has not been picked up, and I cannot add or re-request reviewers from a fork, the API returns 404, so a comment is the only ping I have.

This follows the same shape you approved in #24294 for AIHubMix, a JSON entry in litellm/llms/openai_like/providers.json against litellm_internal_staging rather than a Python module. All review feedback is addressed and the Greptile P1 on the Add Model dropdown is fixed and its thread resolved.

CI is 77 passing and 2 failing. The two failures are code-quality and documentation, and they are not fixable here. test-code-quality.yml checks out litellm-docs main with no ref:, so test_env_keys.py cannot see SCX_API_KEY documented until BerriAI/litellm-docs#808 lands. Merging that docs PR turns both jobs green.

mateo-berri pushed a commit to BerriAI/litellm-docs that referenced this pull request Aug 21, 2026
* docs(providers): add the SCX.ai provider page

Documents the scx-ai route ahead of BerriAI/litellm#34752, which
registers SCX.ai as a JSON-configured OpenAI-compatible provider

Covers the two chat models on the route, GLM-5.2 and Qwen3.8 Max, with
their context and output limits, plus SDK and proxy usage for streaming,
function calling, structured output and image input. Every capability
listed was checked against the live endpoint

Also records two behaviours worth knowing: max_completion_tokens is sent
upstream as max_tokens, and temperature is accepted in [0.0, 2.0) with
2.0 itself rejected, so LiteLLM clamps to 1.99

The page also gives SCX_API_KEY somewhere to live, which the env-key
documentation gate in the main repo requires before that PR can go green

* docs(proxy): document the SCX.ai environment variables

Add SCX_API_KEY and SCX_API_BASE to the environment variables reference
table so the credential names are discoverable from the proxy settings
page, matching how the other providers list theirs.

@mateo-berri mateo-berri 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.

Rates don't match https://scx.ai/pricing, the suggestions below have the right ones. The docs URL is wrong too, and staging needs merging in

Comment thread model_prices_and_context_window.json Outdated
Comment thread litellm/model_prices_and_context_window_backup.json Outdated
Comment thread model_prices_and_context_window.json Outdated
Comment thread litellm/model_prices_and_context_window_backup.json Outdated
Comment thread provider_endpoints_support.json Outdated
Comment thread litellm/provider_endpoints_support_backup.json Outdated
…itellm_scx_ai_provider

Resolves the three conflicts against the JSON provider registry refactor. The
hardcoded api.scx.ai base-url branch in get_llm_provider_logic.py is dropped in
favour of the generic JSONProviderRegistry.get_by_base_url lookup, which reads
the same base_url and api_key_env from providers.json and additionally honours
an explicitly passed api_key. constants.py and types/utils.py keep both the
cognition and scx-ai entries added on either side.
Applies the review suggestions. The cost map now carries the rates published on
https://scx.ai/pricing, GLM-5.2 at 0.61 in, 0.22 cached, 1.98 out and
Qwen3.8-Max at 1.65 in, 0.21 cached, 4.99 out per million tokens, and cites that
page as the source rather than a third party gateway. The provider link is
corrected to https://docs.litellm.ai/docs/providers/scx_ai to match the page
that shipped as scx_ai.md. Both the primary files and their backup mirrors are
updated.
@bhuvan2134686

Copy link
Copy Markdown
Contributor Author

@mateo-berri thanks for the review, all six suggestions are applied and the branch is up to date with litellm_internal_staging.

Prices now match https://scx.ai/pricing exactly, GLM-5.2 at 0.61 in, 0.22 cached, 1.98 out and Qwen3.8-Max at 1.65 in, 0.21 cached, 4.99 out per million tokens, in model_prices_and_context_window.json and its backup mirror, with source pointing at that page instead of a third party gateway. The provider link is https://docs.litellm.ai/docs/providers/scx_ai in provider_endpoints_support.json and its mirror, matching the page that shipped as scx_ai.md in BerriAI/litellm-docs#808.

The staging merge dropped the hardcoded api.scx.ai branch in get_llm_provider_logic.py in favour of the JSONProviderRegistry.get_by_base_url lookup that landed on staging, so the provider resolves purely from providers.json and the PR no longer touches that elif chain. Routing verified both ways after the merge, scx-ai/GLM-5.2 by prefix and GLM-5.2 with api_base=https://api.scx.ai/v1 by base url, and the twelve tests in test_scx_ai_provider.py pass.

The docs jobs that were red are green now that #808 has merged. Ready for another look when you have a moment.

@mateo-berri

Copy link
Copy Markdown
Contributor

bugbot run

@cursor cursor Bot 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 7d9e375. Configure here.

@mateo-berri mateo-berri 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.

LGTM. Thanks for the contribution!

@mateo-berri
mateo-berri merged commit 3029f7e into BerriAI:litellm_internal_staging Aug 22, 2026
73 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.

4 participants