Skip to content

feat(llm): add Atlas Cloud provider - #1510

Merged
erni-a merged 3 commits into
caura-ai:mainfrom
binyangzhu000-sudo:feat/atlascloud-provider
Sep 26, 2026
Merged

erni-a merged 3 commits into
caura-ai:mainfrom
binyangzhu000-sudo:feat/atlascloud-provider

Conversation

@binyangzhu000-sudo

Copy link
Copy Markdown
Contributor

Summary

Atlas Cloud is an OpenAI-compatible gateway, so it joins the _OPENAI_COMPATIBLE set next to OpenRouter and rides the existing OpenAILLMProvider — no new transport, no new dependency. The change is the enum member, the endpoint constants, and the three-tier credential resolution the other providers already use.

  • common/provider_names.py — ATLASCLOUD = "atlascloud"
  • common/llm/constants.py — ATLASCLOUD_CHAT_BASE_URL, ATLASCLOUD_DEFAULT_MODEL (overridable via env, same as the OpenRouter default)
  • common/llm/_credentials.py — _TENANT_KEY_ATTR entry, _env_key branch, and the resolve_openai_compatible branch
  • common/llm/registry.py — add to _OPENAI_COMPATIBLE
  • core-api/config.py — atlascloud_api_key setting and its ATLASCLOUD_API_KEY bridge entry
  • core-api/services/organization_settings.py — tenant-key property, and the provider in the enrichment fallback candidates
  • tests/test_atlascloud_provider.py — 13 unit tests
  • tests/test_credential_bridge.py — ATLASCLOUD_API_KEY added to the bridge-key snapshot so the bridge's writes are restored like the others

Tenant key → env var → empty resolution works exactly as it does for OpenRouter, so ResolvedConfig.atlascloud_api_key overrides ATLASCLOUD_API_KEY.

Validation

  • pytest tests/test_atlascloud_provider.py --noconftest → 13 passed (constants, enum membership, _env_key set/unset, has_credentials with and without a tenant key, tenant-over-env precedence, env fallback, unset behaviour, plus two regression checks that OpenRouter still resolves and unknown providers still return empty)
  • live run against the real gateway:
resolve_openai_compatible("atlascloud", None)
  -> key=apikey-4e168…  base_url=https://api.atlascloud.ai/v1  model=openai/gpt-4.1-mini
get_llm_provider("atlascloud")
  -> OpenAILLMProvider | model: openai/gpt-4.1-mini | provider_name: atlascloud
await provider.complete_text(...) -> 'caura atlascloud ok'

I used --noconftest because the session-scoped fixture in tests/conftest.py pulls in FastAPI and the rest of the API stack, which I didn't install locally. tests/test_contradiction_providers.py fails to collect in my environment for the same reason — it fails identically on unmodified main, so this change doesn't move it.

No docs, README, or sponsor placement touched — just the provider wiring and its tests.

@binyangzhu000-sudo
binyangzhu000-sudo requested a review from a team as a code owner September 15, 2026 03:34
arkash20 added a commit that referenced this pull request Sep 15, 2026
…h _model_for_provider

Forward guard for providers added after M-11. Each branch used to end in
`return key, <BASE_URL>, <DEFAULT_MODEL>` — the shape that made the bug
possible, since a hardcoded default silently ignores `model_attr`. A new
provider copied from an existing branch inherits it, and nothing notices: the
knob just quietly does nothing for that one provider.

The invariant is structural rather than per-provider, so it covers branches
that do not exist yet. #1510 (Atlas Cloud) adds exactly such a branch and will
trip this until it routes through the resolver — which is the point.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Signed-off-by: Arkady Mankovsky <arkash20@gmail.com>
@arkash20

Copy link
Copy Markdown
Contributor

Heads-up on an interaction with #1522, which is open against the same file — no action needed from you yet, and nothing wrong with this PR as written.

#1522 fixes 09/02 M-11: resolve_openai_compatible never accepted model_attr, so the per-service model knobs (contradiction_model, recall_model, …) were inert on every OpenAI-compatible provider. It replaces the return key, <BASE_URL>, <DEFAULT_MODEL> ending in each branch with a resolver:

model = _model_for_provider(provider, tenant_config, model_attr, ATLASCLOUD_DEFAULT_MODEL)
return key, ATLASCLOUD_CHAT_BASE_URL, model

The two PRs touch different lines, so git will merge them cleanly — but the result would be inconsistent: Atlas Cloud would keep ignoring model_attr while the other three providers honour it, which is silent and easy to miss.

#1522 carries a structural test asserting every branch resolves through _model_for_provider, so whichever of us merges second will see it go red rather than have the gap slip through. Whoever lands first, the other rebases and it's a one-line change.

One thing that may be worth a look independently: ATLASCLOUD_DEFAULT_MODEL = "openai/gpt-4.1-mini" is a vendor/model id, so it won't be mistaken for another provider's model by #1522's family check (that only matches bare prefixes like gpt-, claude-, gemini-). But if a tenant sets enrichment_model = "gpt-4o" while on Atlas Cloud, #1522 would treat it as an OpenAI id and fall back to the Atlas default. If Atlas accepts bare OpenAI model names, tell me and I'll exclude it from that check.

arkash20 added a commit that referenced this pull request Sep 15, 2026
…h _model_for_provider

Forward guard for providers added after M-11. Each branch used to end in
`return key, <BASE_URL>, <DEFAULT_MODEL>` — the shape that made the bug
possible, since a hardcoded default silently ignores `model_attr`. A new
provider copied from an existing branch inherits it, and nothing notices: the
knob just quietly does nothing for that one provider.

The invariant is structural rather than per-provider, so it covers branches
that do not exist yet. #1510 (Atlas Cloud) adds exactly such a branch and will
trip this until it routes through the resolver — which is the point.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Signed-off-by: Arkady Mankovsky <arkash20@gmail.com>
arkash20 added a commit that referenced this pull request Sep 15, 2026
…h _model_for_provider

Forward guard for providers added after M-11. Each branch used to end in
`return key, <BASE_URL>, <DEFAULT_MODEL>` — the shape that made the bug
possible, since a hardcoded default silently ignores `model_attr`. A new
provider copied from an existing branch inherits it, and nothing notices: the
knob just quietly does nothing for that one provider.

The invariant is structural rather than per-provider, so it covers branches
that do not exist yet. #1510 (Atlas Cloud) adds exactly such a branch and will
trip this until it routes through the resolver — which is the point.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Signed-off-by: Arkady Mankovsky <arkash20@gmail.com>
@binyangzhu000-sudo

Copy link
Copy Markdown
Contributor Author

Thanks @arkash20. Rebased onto current main after #1522 and pushed 615bc76. The Atlas branch now calls _model_for_provider(provider, tenant_config, model_attr, ATLASCLOUD_DEFAULT_MODEL).

On bare IDs: support is model-specific, not universal. The Atlas-side live checks shared with me returned 400/not found for gpt-4o and gemini-3-pro, but accepted gpt-4.1-mini (resolved to openai/gpt-4.1-mini) and claude-sonnet-4-6 (resolved to anthropic/claude-sonnet-4.6). I did not repeat those paid calls. So the family-prefix guard would incorrectly replace some valid Atlas choices. I scoped an exemption to Atlas only: preserve the explicit ID and let the API validate availability. The canonical default remains unchanged; other providers retain their existing guard.

Added coverage for tenant/env per-service overrides, those bare aliases, and default fallback. Validation: 54 tests passed across test_atlascloud_provider.py, test_m10_m11_provider_aware_models.py, and test_credential_bridge.py using pytest --noconftest to isolate these unit tests from the global PostgreSQL fixture. Focused Ruff lint/format and git diff --check passed. The full database-backed suite was not run locally.

@erni-a

erni-a commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Approved by @arkash20 and I updated the branch so CI could run, but the DCO check fails: the first commit (3840ebe4 feat(llm): add Atlas Cloud provider) has no Signed-off-by trailer. Branch protection will not let it merge until every commit carries one. git rebase --signoff origin/main && git push --force-with-lease fixes it in one step. Ping when pushed and we will merge.

@erni-a

erni-a commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

@binyangzhu000-sudo the only thing between this and main is the sign-off on 3840ebe4. Everything else is approved and the branch is current. If we have not heard back by Tuesday 23 Sep we will carry the two commits into a maintainer PR with your authorship preserved so the work lands and stays credited to you. Prefer that you push it yourself, since it is a one-liner: git rebase --signoff origin/main && git push --force-with-lease.

@arkash20 for visibility, since the approval is yours.

Atlas Cloud is an OpenAI-compatible gateway, so it joins the set that rides
OpenAILLMProvider alongside OpenRouter — no new transport, just the enum
member, the endpoint constants, and credential resolution.

- common/provider_names.py: ATLASCLOUD member
- common/llm/constants.py: chat base URL and default model
- common/llm/_credentials.py: tenant-attr map, _env_key, and the
  resolve_openai_compatible branch
- common/llm/registry.py: add to _OPENAI_COMPATIBLE
- core-api config + organization_settings: atlascloud_api_key, the env
  bridge entry, and the tenant-key property
- tests: 13 unit tests, plus ATLASCLOUD_API_KEY in the bridge-key snapshot

Signed-off-by: binyangzhu000-sudo <224954946+binyangzhu000-sudo@users.noreply.github.com>
Signed-off-by: binyangzhu000-sudo <224954946+binyangzhu000-sudo@users.noreply.github.com>
@binyangzhu000-sudo

Copy link
Copy Markdown
Contributor Author

Pushed — both commits now carry Signed-off-by (git rebase --signoff origin/main, force-pushed). Branch is current with main as of the merge you did this morning. Let me know if anything else is needed.

@erni-a

erni-a commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Sign-off landed, branch current, CI green. Merging. Thanks @binyangzhu000-sudo for the provider and for the quick turnaround on the DCO.

@erni-a
erni-a merged commit 0ee34f4 into caura-ai:main Sep 26, 2026
14 checks passed
@caura-deploy-bot caura-deploy-bot Bot mentioned this pull request Sep 26, 2026
ghost pushed a commit that referenced this pull request Sep 26, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>backend: 3.20.0</summary>

##
[3.20.0](backend-v3.19.2...backend-v3.20.0)
(2026-09-26)


### Features

* **llm:** add Atlas Cloud provider
([#1510](#1510))
([0ee34f4](0ee34f4))


### Bug Fixes

* **api:** align ConflictOut OpenAPI response with runtime schema fields
([#1536](#1536))
([1f929dc](1f929dc))
* **client-python:** ship the Apache-2.0 LICENSE in the published
package ([#1031](#1031))
([820d60b](820d60b))
* **client-ts:** ship the Apache-2.0 LICENSE in the npm package
([#1032](#1032))
([26231d4](26231d4))
* **contradiction:** give the forward chain-edge writes the CAS their
comments claimed
([#1727](#1727))
([4599871](4599871))
* **plugin:** stop re-requesting agent keys after the provision route
404s ([#1718](#1718))
([b5fe391](b5fe391))
* **worker:** stop warning that the async path does not fan out — it has
since A70 (oss-0924-m-03)
([#1724](#1724))
([cb84511](cb84511))
</details>

<details><summary>plugin: 2.23.3</summary>

##
[2.23.3](plugin-v2.23.2...plugin-v2.23.3)
(2026-09-26)


### Bug Fixes

* **plugin:** stop re-requesting agent keys after the provision route
404s ([#1718](#1718))
([b5fe391](b5fe391))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Signed-off-by: release-please[bot] <release-please[bot]@users.noreply.github.com>
Signed-off-by: Eldad Caura <eldad@caura.ai>
Co-authored-by: caura-deploy-bot[bot] <265395343+caura-deploy-bot[bot]@users.noreply.github.com>
Co-authored-by: Eldad Caura <eldad@caura.ai>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

3 participants