Skip to content

feat: add Mistral as first-class provider - #42357

Open
ElPadreLulu wants to merge 1 commit into
NousResearch:mainfrom
ElPadreLulu:feat-mistral-provider
Open

feat: add Mistral as first-class provider#42357
ElPadreLulu wants to merge 1 commit into
NousResearch:mainfrom
ElPadreLulu:feat-mistral-provider

Conversation

@ElPadreLulu

@ElPadreLulu ElPadreLulu commented Jun 8, 2026

Copy link
Copy Markdown

Fixes #20859

Summary

This PR adds Mistral AI as a first-class LLM provider using the current Hermes ProviderProfile / plugins/model-providers architecture.

It keeps the integration small and aligned with the existing API-key provider path: no provider-specific transport, no mistralai SDK dependency, and no custom reasoning replay logic.

The bundled provider exposes:

  • canonical provider: mistral
  • aliases: mistral-ai, mistralai
  • OpenAI-compatible Chat Completions transport
  • default endpoint: https://api.mistral.ai/v1
  • API key environment variable: MISTRAL_API_KEY
  • base URL override: MISTRAL_BASE_URL
  • default auxiliary model: mistral-small-latest
  • a small, stable fallback model set for offline provider selection
  • supports_prompt_cache_key=True, so Hermes can use its existing prompt-cache-key gate for Mistral long-session caching

Notes

This version incorporates feedback received during review and discussion:

  • uses the current plugins/model-providers architecture;
  • relies on generic API-key provider registration instead of direct changes in hermes_cli/auth.py or hermes_cli/main.py;
  • removes the previous Mistral-specific reasoning_content handling because main now performs this cleanup generically for strict OpenAI-compatible providers;
  • keeps tests focused on behavioral invariants rather than a snapshot of the Mistral model catalog;
  • opts Mistral into Hermes’ existing prompt_cache_key transport gate via supports_prompt_cache_key=True.

The prompt-cache-key flag is provider-scoped and opt-in. It does not change behavior for other OpenAI-compatible providers.

Validation

Current branch is rebased on main at 7cd91114.

Targeted provider and transport tests:

66 passed

Provider validation, fallback, and runtime tests:

95 passed

Additional checks:

git diff --check: passed
compileall provider/profile paths: passed

Live smoke tests with MISTRAL_API_KEY from the local environment and the default endpoint:

config-driven smoke test: CONFIG_MISTRAL_OK
live Mistral smoke test with prompt cache key enabled: MISTRAL_CACHE_OK

Prompt-cache-key transport check:

supports_prompt_cache_key=True
has_prompt_cache_key=True
prompt_cache_key_prefix=pck_

@ElPadreLulu
ElPadreLulu marked this pull request as draft June 8, 2026 20:26
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have provider/nous Nous Research API (OAuth) comp/cli CLI entry point, hermes_cli/, setup wizard labels Jun 8, 2026
@ElPadreLulu
ElPadreLulu force-pushed the feat-mistral-provider branch 4 times, most recently from 213704c to 5ae7116 Compare June 9, 2026 06:12
@ElPadreLulu
ElPadreLulu marked this pull request as ready for review June 9, 2026 21:34
@neborion

Copy link
Copy Markdown

I would also like to see this feature added. Thanks @DevAgarwal2! @teknium1 @OutThisLife @kshitijk4poor.
+1 this PR. Could we add Mistral to be first-class provider please?

@turnercore

Copy link
Copy Markdown

This is great!

@mhorlacher

Copy link
Copy Markdown

When can we expect the merge?

@alt-glitch alt-glitch removed the provider/nous Nous Research API (OAuth) label Jun 28, 2026
@ElPadreLulu

Copy link
Copy Markdown
Author

Update: another PR, #50289, has been opened for the same goal: adding Mistral as a first-class provider.

After comparing both approaches, I think #50289 is probably the better base now because it follows the current plugins/model-providers architecture. This PR was useful for identifying the need and the strict-provider reasoning_content replay issue, but that concern now appears to be handled more generically on main.

I’ve left a comment on #50289 with a few non-blocking points from this PR that may still be worth considering before merge.

Unless maintainers prefer this implementation, I’m happy to treat this PR as superseded by #50289.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the Mistral-provider work. The first-class provider feature is still absent on current main, but this branch needs a targeted salvage rather than a direct cherry-pick.

Problems

  • The Mistral-specific replay branch duplicates current generic behavior: agent/agent_runtime_helpers.py:2821-2838 strips reasoning_content for all non-echo providers, and :2931-2937 handles already-built fallback history. Commit 2b3a4f0af added the direct Mistral regression at tests/run_agent/test_deepseek_reasoning_content_echo.py:576-649.
  • Current main expects new API-key providers to be a plugins/model-providers/<name>/ ProviderProfile: hermes_cli/auth.py:447-477 auto-registers those profiles and hermes_cli/main.py:2774-2780 dispatches them generically. The direct auth.py and main.py additions here are therefore stale.
  • The new catalog assertions pin mutable Mistral model names; AGENTS.md:80-83 requires behavioral invariants instead of catalog snapshots.

Suggested changes

  • Re-scope the provider entry to the current plugin-profile path and retain only still-needed picker/docs integration.
  • Drop the now-redundant reasoning cleanup and tests.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users labels Jul 14, 2026
@alt-glitch alt-glitch added needs-decision Awaiting maintainer decision before any implementation comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint area/auth Authentication, OAuth, credential pools and removed sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 14, 2026
@ElPadreLulu
ElPadreLulu force-pushed the feat-mistral-provider branch from 5ae7116 to 3babc7d Compare July 16, 2026 12:50
@alt-glitch alt-glitch added comp/plugins Plugin system and bundled plugins area/config Config system, migrations, profiles sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades and removed comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint area/auth Authentication, OAuth, credential pools labels Jul 16, 2026
@ElPadreLulu

Copy link
Copy Markdown
Author

@teknium1 Thanks for the guidance.

I’ve refreshed this PR to address the review feedback and align it with the current provider-plugin architecture.

The updated version now:

  • moves Mistral to a bundled plugins/model-providers provider;
  • removes the previous direct auth.py / main.py registration;
  • drops the Mistral-specific reasoning_content handling since main now covers strict providers generically;
  • updates the tests to focus on behavioral invariants rather than a fixed model catalog;
  • refreshes the related documentation.

I also re-ran the targeted test suites and additional live config-driven smoke tests against the Mistral API.

At this point I’m mainly waiting for the GitHub checks to run, but I’m happy to make any further adjustments if needed.

@QuentinDEME97

Copy link
Copy Markdown

I'm waiting for this 👀

I've been struggling configuring Mistral Small...

@ElPadreLulu
ElPadreLulu force-pushed the feat-mistral-provider branch from 3babc7d to 1f6737c Compare July 22, 2026 12:57
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #61160 and #20859: the live patch now uses a combined CLI catalog plus ProviderProfile path. It remains a competing Mistral implementation; maintainers should choose the canonical wiring.

@ElPadreLulu

Copy link
Copy Markdown
Author

Updated this PR against the latest main / Hermes v0.19.0 (9acc4b47).

The patch still applies cleanly. I also fixed one new merge-result issue from the latest main: the newer alias-resolution path in resolve_provider_full() was dropping base_url_env_var / auth_type for Mistral aliases (mistral-ai, mistralai), so MISTRAL_BASE_URL is now preserved there too.

Validated locally:

151 passed
live Mistral smoke test: MISTRAL_OK

Alias checks:

mistral     -> MISTRAL_BASE_URL
mistral-ai  -> MISTRAL_BASE_URL
mistralai   -> MISTRAL_BASE_URL

@merouaneagar

Copy link
Copy Markdown

Just a heads-up for anyone following this: I attempted an in-tree PR (#76391), but per the maintainers' in-tree-provider-integration policy (AGENTS.md), third-party LLM provider integrations ship as standalone plugin repositories, not bundled plugins. So the only supported route is a standalone plugin.

It is now published and installable in one command:

hermes plugins install merouaneagar/hermes-mistral-provider

Production-grade profile for api.mistral.ai: reasoning gating per model family (handles the medium->high rejection and the stream-crash on high), vision support, live model catalog, never emits extra_body.think. 12 unit tests, validated E2E on 34 chat models. Docs, quirks and license in the README.

@ElPadreLulu
ElPadreLulu force-pushed the feat-mistral-provider branch from 1f6737c to 9c436b8 Compare August 10, 2026 16:35
@ElPadreLulu

Copy link
Copy Markdown
Author

Rebased again on current main / Hermes v0.20.0 (03fa32c9) and resolved the latest config conflict.

The conflict came from the recent config/env-var refactor, so I kept the new config_defaults.py / ProviderProfile env-var injection path from main instead of reintroducing the old OPTIONAL_ENV_VARS block.

Validated locally:

64 passed
config-driven smoke test: CONFIG_MISTRAL_OK
live Mistral smoke test: MISTRAL_OK

I understand the standalone-provider policy, but I still think Mistral is a reasonable first-class exception: broad general-purpose LLM provider, strong user demand in #20859, existing Mistral surface in Hermes, and low maintenance footprint through ProviderProfile-only wiring.

If maintainers confirm standalone-only is final for Mistral too, I’ll stop refreshing this PR; until then I’m keeping this implementation mergeable as the current consolidated in-tree path.

@ElPadreLulu
ElPadreLulu force-pushed the feat-mistral-provider branch from 9c436b8 to 9cf311f Compare August 17, 2026 18:14
@ElPadreLulu

Copy link
Copy Markdown
Author

Rebased again on current main / Hermes v0.20.2 (eb63c254).

The patch still applies cleanly on the latest provider/config routing, and I kept this as a single ProviderProfile-style wiring commit.

Validated locally:

64 passed
config-driven smoke test: CONFIG_MISTRAL_OK
live Mistral smoke test: MISTRAL_OK

The PR is mergeable again (mergeable: true). GitHub checks are not visible yet on this refreshed head.

@ElPadreLulu
ElPadreLulu force-pushed the feat-mistral-provider branch from 9cf311f to dcf63be Compare August 17, 2026 18:58
@ElPadreLulu

Copy link
Copy Markdown
Author

Rebased again on current main / Hermes v0.20.3 (7339f5f1).

The patch still applies cleanly. Validated locally:

64 passed
config-driven smoke test: CONFIG_MISTRAL_OK
live Mistral smoke test: MISTRAL_OK

PR is mergeable again (mergeable: true); GitHub checks are still not visible on the refreshed head.

@LeBaronDeCharlus

Copy link
Copy Markdown

Wired Hermes to Mistral locally and independently landed on the same profile shape as this PR, it works well. One addition worth considering: supports_prompt_cache_key=True.

Mistral bills cached input at 10% of the standard input rate, but unlike DeepSeek and OpenAI it does not cache implicitly, the top-level prompt_cache_key field has to be present. Measured against api.mistral.ai with mistral-large-latest on 2026-08-18, using an 8,298-token stable prefix:

without prompt_cache_key:  cached_tokens = 0, 0, 0
with    prompt_cache_key:  cached_tokens = 8272, 8272, 0    (99.7% of the prefix on a hit)

End-to-end through Hermes, one 4-turn session with the flag enabled on the profile:

mistral-large-latest   calls=4   input_tokens=62,274   cache_read_tokens=62,176

That is 50% of the session's prompt tokens served from cache, with one call showing 31,072/31,096 (99.9%). Hermes re-sends a ~21k-token system+tools prefix every turn, so on a long session this is roughly a 2x difference on the bill.

The flag is opt-in upstream because many OpenAI-compatible endpoints reject unknown top-level fields rather than ignoring them. Mistral accepts it (HTTP 200, no 400), so opting in looks safe here. The existing _add_prompt_cache_key() gate and its session-scoped content-addressed key handle the rest, no transport changes needed.

Caveat from the same measurements: hits are not guaranteed even on an identical prefix (2 of 3 in the direct test, roughly 2 of 3 eligible turns live), which matches Mistral's documentation. A solid win, not a free lunch.

Happy to open a follow-up PR with the one-liner plus a test if that is easier than folding it in here.

@ElPadreLulu
ElPadreLulu force-pushed the feat-mistral-provider branch from dcf63be to 06b0131 Compare September 1, 2026 18:09
@ElPadreLulu

Copy link
Copy Markdown
Author

Thanks @LeBaronDeCharlus, folded this in.

The Mistral profile now sets supports_prompt_cache_key=True, with coverage confirming that the profile opts into Hermes’ existing prompt-cache-key transport gate. This keeps the field provider-scoped, so it is only emitted for profiles that explicitly declare support for it.

I also rebased the PR on the latest main (7cd91114) and resolved the docs/env conflicts while keeping the new upstream provider entries.

Validated locally:

66 passed
95 passed
config-driven smoke test: CONFIG_MISTRAL_OK
live Mistral smoke test with prompt cache key enabled: MISTRAL_CACHE_OK

Transport check:

supports_prompt_cache_key=True
has_prompt_cache_key=True
prompt_cache_key_prefix=pck_

@alt-glitch alt-glitch added comp/cli CLI entry point, hermes_cli/, setup wizard and removed comp/cli CLI entry point, hermes_cli/, setup wizard sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Support for Mistral as LLM provider

9 participants