Skip to content

feat: add Requesty as an OpenAI-compatible provider#978

Open
Thibaultjaigu wants to merge 4 commits into
getnao:mainfrom
Thibaultjaigu:add-requesty-provider
Open

feat: add Requesty as an OpenAI-compatible provider#978
Thibaultjaigu wants to merge 4 commits into
getnao:mainfrom
Thibaultjaigu:add-requesty-provider

Conversation

@Thibaultjaigu

@Thibaultjaigu Thibaultjaigu commented Jun 25, 2026

Copy link
Copy Markdown

What

Adds Requesty as a named LLM provider in the CLI configuration, mirroring the existing OpenRouter wiring 1:1.

Requesty is an OpenAI-compatible LLM gateway. It uses the same provider/model naming convention as OpenRouter (e.g. openai/gpt-4o-mini), so it slots into the existing provider machinery without special handling.

Changes

In cli/nao_core/config/llm/__init__.py:

  • LLMProvider enum: add REQUESTY = "requesty"
  • PROVIDER_AUTH: add ProviderAuthConfig(env_var="REQUESTY_API_KEY", api_key="required", base_url_env_var="REQUESTY_BASE_URL")
  • DEFAULT_ANNOTATION_MODELS: add LLMProvider.REQUESTY: "openai/gpt-4o-mini"
  • promptConfig picker: add questionary.Choice("Requesty", value="requesty")

Each entry is placed directly alongside the corresponding OpenRouter entry.

Tested

  • Verified live against https://router.requesty.ai/v1/chat/completions with model openai/gpt-4o-mini → HTTP 200.
  • Confirmed at runtime that LLMProvider("requesty"), PROVIDER_AUTH, DEFAULT_ANNOTATION_MODELS, and a LLMConfig(provider=REQUESTY, api_key=...) round-trip all resolve correctly (default annotation model applied, requires_api_key=True).

The TypeScript backend provider (apps/backend) can be wired the same way using the official @requesty/ai-sdk (createRequesty) provider; I kept this PR scoped to the self-contained CLI surface and am happy to follow up with the backend wiring in a separate PR.


I work at Requesty. This mirrors the existing OpenRouter provider as closely as possible. Happy to adjust wording/placement or close it if it's not a fit.

Review in cubic

@github-actions

Copy link
Copy Markdown
Contributor

This PR was auto-closed. Only contributors approved with lgtm can open PRs. Open an issue first.

Maintainers review auto-closed issues daily. Issues that do not meet the quality bar in CONTRIBUTING.md will not be reopened or receive a reply.

If a maintainer replies lgtmi, your future issues will stay open. If a maintainer replies lgtm, your future issues and PRs will stay open.

See CONTRIBUTING.md.

@Bl3f

Bl3f commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Hello @Thibaultjaigu, thank you for this. If the ts backend implementation is not done it's a bit useless because all the agentic stuff is done there.

So the best would be to support it there as well.

@cubic-dev-ai cubic-dev-ai 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.

No issues found across 5 files

Re-trigger cubic

@socallmebertille socallmebertille 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.

Hi, thanks a lot for your contribution! However it remains a lot of changes so that we can merge this add as is, I'll let you know which points is missing :

Functional

  • apps/backend/src/agents/provider-meta.ts — invalide model IDswrong values on related fields (see inline comments).
  • cli/nao_core/commands/debug.py_check_available_models doesn't handle requesty → returns "Unknown provider: requesty". Add an elif provider == "requesty": branch with base_url="https://router.requesty.ai/v1" (copy of the openrouter branch).
  • cli/nao_core/templates/engine.py — (a) add REQUESTY to the OpenAI-compatible set (l.120), otherwise ai_summary raises "Unsupported LLM provider". (b) add the Requesty base_url fallback (l.157), otherwise the call hits the default OpenAI endpoint.

Consistency

  • cli/nao_core/deps.py — add "requesty": "openai" to _PROVIDER_ALIASES, otherwise the openai extra is never detected/installed for Requesty.
  • apps/frontend/src/components/ui/llm-provider-icon.tsx — add case 'requesty' + the icons/requesty.svg asset. The SVG must be monochrome and use fill="currentColor" (no hardcoded colors, no fixed width/height — only a viewBox) so it inherits the theme color like the other provider icons (text-foreground opacity-50).

Quality / docs

  • apps/backend/src/agents/provider-meta.ts — add costPerM to Requesty models (see inline comments).
  • cli/tests/nao_core/commands/test_debug.py — add Requesty tests (mirroring test_openrouter_*).
  • cli/README.md — (l.89) add Requesty to the providers list.
  • Verify the model IDs actually exist on router.requesty.ai (especially anthropic/claude-haiku-4.5 and openai/gpt-4o-mini).

id: 'openai/gpt-4o-mini',
name: 'GPT-4o mini',
default: true,
contextWindow: 128_000,

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.

The costPerM variable must be implemented in order to continue tracking costs in the cost setting section and also for the budget setting section that can be set by admins.

Suggested change
contextWindow: 128_000,
contextWindow: 128_000,
costPerM: { inputNoCache: 0.15, inputCacheRead: 0.075, inputCacheWrite: 0, output: 0.6 },

Comment on lines +205 to +206
extractorModelId: 'anthropic/claude-haiku-4.5',
summaryModelId: 'anthropic/claude-haiku-4.5',

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.

These 2 models anthropic/claude-haiku-4.5 and anthropic/claude-sonnet-4.5 don't exist in https://router.requesty.ai/v1/models.

Suggested change
extractorModelId: 'anthropic/claude-haiku-4.5',
summaryModelId: 'anthropic/claude-haiku-4.5',
extractorModelId: 'anthropic/claude-haiku-4-5',
summaryModelId: 'anthropic/claude-haiku-4-5',

{
id: 'deepseek/deepseek-chat',
name: 'DeepSeek Chat',
contextWindow: 128_000,

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.

It was not the correct amount for contextWindow.

Suggested change
contextWindow: 128_000,
contextWindow: 1_000_000,
costPerM: { inputNoCache: 0.14, inputCacheRead: 0.028, inputCacheWrite: 0, output: 0.28 },

contextWindow: 128_000,
},
{
id: 'anthropic/claude-sonnet-4.5',

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.

Suggested change
id: 'anthropic/claude-sonnet-4.5',
id: 'anthropic/claude-sonnet-4-5,

{
id: 'anthropic/claude-sonnet-4.5',
name: 'Claude Sonnet 4.5 (Requesty)',
contextWindow: 1_000_000,

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.

Suggested change
contextWindow: 1_000_000,
contextWindow: 1_000_000,
costPerM: { inputNoCache: 3, inputCacheRead: 0.3, inputCacheWrite: 0, output: 15 },

@Thibaultjaigu

Copy link
Copy Markdown
Author

Thanks for the careful review. I pushed a commit addressing all of it:

  1. Corrected the Anthropic model ids to the ones Requesty actually serves: anthropic/claude-haiku-4-5 and anthropic/claude-sonnet-4-5 (the 4.5 variants do not exist in https://router.requesty.ai/v1/models). This covers both the extractorModelId / summaryModelId and the listed model.
  2. Added costPerM to every Requesty model so cost and budget tracking work, using the live values from the Requesty models endpoint.
  3. Fixed the context windows against the live metadata: deepseek/deepseek-chat is 1,000,000 (not 128k), and I added anthropic/claude-haiku-4-5 (200,000) since it is the extractor/summary model.

Live values used for costPerM (USD per 1M tokens, inputNoCache / inputCacheRead / inputCacheWrite / output):

  • openai/gpt-4o-mini: 0.15 / 0.075 / 0 / 0.6 (ctx 128k)
  • deepseek/deepseek-chat: 0.14 / 0.028 / 0 / 0.28 (ctx 1M)
  • anthropic/claude-haiku-4-5: 1 / 0.1 / 1.25 / 5 (ctx 200k)
  • anthropic/claude-sonnet-4-5: 3 / 0.3 / 3.75 / 15 (ctx 1M)

On the backend point: the agentic path is wired in apps/backend/src/agents/providers.ts, where requesty has a create that builds an OpenAI-compatible client at https://router.requesty.ai/v1 (Requesty is OpenAI-compatible, so it reuses the same thin client as OpenRouter). Happy to adjust any of the defaults.

@socallmebertille

Copy link
Copy Markdown
Contributor

@Thibaultjaigu Thanks for the update, and I appreciate the changes you've made so far!

The backend model IDs and metadata look much better now. However, there are still several of the points from my previous review that haven't been addressed yet, including the CLI changes, provider aliases, frontend icon, tests, and documentation updates.

Could you please go through the remaining items from my original review and address those as well? Once those are covered, we should be much closer to being able to merge this PR.

Thanks again for your work!

P.S. The inputCacheWrite value for anthropic/claude-sonnet-4-6 in costPerM should be 0.

Signed-off-by: Thibault Jaigu <thibault.jaigu@gmail.com>
@Thibaultjaigu

Copy link
Copy Markdown
Author

Thanks, I pushed another commit covering the remaining items:

  1. Frontend icon: added a Requesty provider icon (apps/frontend/src/components/icons/requesty.svg) and wired the requesty case in llm-provider-icon.tsx, mirroring the OpenRouter entry.
  2. CLI provider alias: added requesty -> openai to _PROVIDER_ALIASES in cli/nao_core/deps.py, so the OpenAI extra is installed for Requesty (same as OpenRouter). The CLI provider enum and auth config were already added in cli/nao_core/config/llm/__init__.py.
  3. Docs: added Requesty to the provider list in cli/README.md.

On the backend client: Requesty reuses the @openrouter/ai-sdk-provider client in providers.ts (it is a thin OpenAI-compatible client pointed at https://router.requesty.ai/v1), so no new dependency is needed in apps/backend/package.json.

On the P.S.: the claude-sonnet-4-6 entry with inputCacheWrite is in the existing anthropic provider block, not in the Requesty block this PR adds (the Requesty Anthropic models I added use the live cache-write prices from the Requesty models endpoint: sonnet-4-5 is 3.75, haiku-4-5 is 1.25). Happy to also correct the anthropic claude-sonnet-4-6 value to 0 in this PR if you would like, just confirm and I will include it.

For tests: I did not find an existing test that enumerates providers or covers OpenRouter specifically (the CLI test_debug.py only exercises a few named providers). If there is a particular test you would like added for the Requesty path, point me at the pattern and I will mirror it.

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="cli/README.md">

<violation number="1" location="cli/README.md:89">
P3: Requesty is documented as a selectable LLM provider but the README installation section does not indicate which extra is required. Since `pyproject.toml` has no `requesty` extra and `deps.py` maps Requesty to the `openai` extra, users may try to install a non-existent extra or be unsure how to enable the provider.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread cli/README.md
- **Database connections** (BigQuery, DuckDB, Databricks, Snowflake, PostgreSQL, Redshift, MSSQL, Trino, StarRocks)
- **Git repositories** to sync
- **LLM provider** (OpenAI, Anthropic, Mistral, Gemini, OpenRouter, Ollama)
- **LLM provider** (OpenAI, Anthropic, Mistral, Gemini, OpenRouter, Requesty, Ollama)

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.

P3: Requesty is documented as a selectable LLM provider but the README installation section does not indicate which extra is required. Since pyproject.toml has no requesty extra and deps.py maps Requesty to the openai extra, users may try to install a non-existent extra or be unsure how to enable the provider.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At cli/README.md, line 89:

<comment>Requesty is documented as a selectable LLM provider but the README installation section does not indicate which extra is required. Since `pyproject.toml` has no `requesty` extra and `deps.py` maps Requesty to the `openai` extra, users may try to install a non-existent extra or be unsure how to enable the provider.</comment>

<file context>
@@ -86,7 +86,7 @@ This will create a new nao project in the current directory. It will prompt you
 - **Database connections** (BigQuery, DuckDB, Databricks, Snowflake, PostgreSQL, Redshift, MSSQL, Trino, StarRocks)
 - **Git repositories** to sync
-- **LLM provider** (OpenAI, Anthropic, Mistral, Gemini, OpenRouter, Ollama)
+- **LLM provider** (OpenAI, Anthropic, Mistral, Gemini, OpenRouter, Requesty, Ollama)
 - **`ai_summary` template + model** (prompted only when you enable `ai_summary` for databases)
 - **Slack integration**
</file context>

@socallmebertille socallmebertille 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.

I checked again your changes and it's almost there !

A few points :

  • cubic comment's isn't particularly relevant this time, you can skip it
  • cli/nao_core/commands/debug.py still misses the elif provider == "requesty": branch so the debug CLI command handles the new provider
  • cli/nao_core/templates/engine.py still misses the provider wiring : add LLMProvider.REQUESTY to the set at l.120 — if self.llm_config.provider in {LLMProvider.OPENAI, LLMProvider.OPENROUTER, LLMProvider.REQUESTY}: — and the base_url fallback at l.157 :
     elif self.llm_config and self.llm_config.provider == LLMProvider.REQUESTY:
                 kwargs["base_url"] = "https://router.requesty.ai/v1"
  • for the tests, the file is located at the following path cli/tests/nao_core/commands/test_debug.py, I was referring the 2 def test_openrouter_connection_success(self) and def test_openrouter_exception_returns_failure(self) (1 that succeed and 1 that fail) that I encourage you to follow for the requesty one (I will cover the 3 providers tests's missing in another PR)

My bad on the P.S., you were right !

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