Skip to content

feat: add model fallback support for resilient AI in DDIL environments#594

Draft
crspeller wants to merge 5 commits intomasterfrom
cursor/ai-model-fallback-8e2c
Draft

feat: add model fallback support for resilient AI in DDIL environments#594
crspeller wants to merge 5 commits intomasterfrom
cursor/ai-model-fallback-8e2c

Conversation

@crspeller
Copy link
Copy Markdown
Member

Summary

Add a service-level model fallback mechanism so AI automatically switches between LLM providers when the primary is unavailable — using cloud LLMs when connected and falling back to on-prem/local models in DDIL (Denied, Disrupted, Intermittent, Limited) environments.

How it works:

Each AI service can now optionally specify a Fallback Service — another configured service to try when the primary fails (network error, rate limit, model unavailable). Fallback chains are supported (e.g., OpenAI → Anthropic → Local Ollama), with automatic cycle detection.

This leverages Bifrost's built-in fallback mechanism, which handles sequential failover automatically on every request. When the primary provider recovers, it's automatically used again — no manual intervention needed.

Key behavior:

  • Automatic (no user action required)
  • Graceful degradation (degraded capability instead of total loss)
  • Per-request failover (not sticky — primary is always tried first)
  • Minimal disruption to workflow

Backend changes:

  • Added FallbackServiceID field to ServiceConfig for chaining services
  • Added ResolveFallbackChain() with cycle detection (visited-set algorithm)
  • Created multiProviderAccount to register multiple providers with Bifrost
  • Updated Bifrost request builders to attach fallback chain to every request
  • Updated bot initialization to resolve and pass fallback chains
  • Updated optimistic change detection to include fallback service configs

Frontend changes:

  • Added "Fallback Service" dropdown to the service configuration panel
  • Self-selection excluded from dropdown to prevent trivial cycles
  • Help text explains the feature and chain support

Tests added (28 new test cases):

  • ResolveFallbackChain: no fallback, simple chain, multi-hop chain, cycle detection, self-cycle, missing/invalid services
  • multiProviderAccount: single/multiple providers, unknown provider, duplicate handling, Azure/Bedrock configs
  • Fallback request building: Chat API and Responses API with/without fallbacks
  • NewFromServiceConfig: no fallbacks, single/multiple fallbacks, bot model override isolation
  • serviceConfigToFallbackEntry: provider mapping, URL normalization

Ticket Link

N/A — Feature request for resilient AI in DDIL environments

Release Note

Added model fallback support for AI services. Each service can now specify a fallback service that will be used automatically when the primary provider is unavailable. Fallback chains are supported (e.g., cloud → on-prem → local). This enables graceful degradation instead of total AI loss in DDIL (disconnected) environments.
Open in Web Open in Cursor 

cursoragent and others added 4 commits April 5, 2026 20:36
…egration

Add service-level model fallback so AI automatically switches between
providers when the primary fails (network error, rate limit, model
unavailable). Each service can optionally specify a FallbackServiceID
pointing to another service, forming a chain (A→B→C) with cycle detection.

Backend changes:
- Add FallbackServiceID field to ServiceConfig
- Add ResolveFallbackChain() for walking the fallback chain with cycle detection
- Create multiProviderAccount to register multiple providers with Bifrost
- Add FallbackEntry type and wire fallbacks through Config/LLM/New()
- Update convertToBifrostRequest and convertToBifrostResponsesRequest
  to attach fallbacks to every outgoing request
- Update NewFromServiceConfig to accept and map fallback services
- Update bots.go getLLM() and resolveServiceCfgs() to resolve and
  pass fallback chains, including change detection for fallback services

Co-authored-by: Christopher Speller <crspeller@users.noreply.github.com>
Add a 'Fallback Service' dropdown to the service configuration panel in
the system console. When a service is unavailable, requests automatically
fall back to the selected service. Chains are supported (A→B→C).

- Add fallbackServiceID field to LLMService TypeScript type
- Add SelectionItem dropdown showing all other services as fallback options
- Self-selection is excluded from the dropdown to prevent trivial cycles
- Pass services list from parent Services component to each Service
- Include fallbackServiceID in default new service template

Co-authored-by: Christopher Speller <crspeller@users.noreply.github.com>
Add tests for:
- ResolveFallbackChain: no fallback, simple chain, multi-hop chain,
  cycle detection, self-cycle, missing/invalid services
- FallbackServiceID JSON serialization (round-trip, omitempty)
- multiProviderAccount: single/multiple providers, unknown provider,
  duplicate provider handling, Azure/Bedrock key configs
- Fallback request building: both Chat and Responses API with/without fallbacks
- NewFromServiceConfig: no fallbacks, single fallback, multiple fallbacks,
  bot model override isolation, serviceConfigToFallbackEntry mapping

Co-authored-by: Christopher Speller <crspeller@users.noreply.github.com>
Co-authored-by: Christopher Speller <crspeller@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 5, 2026

🤖 LLM Evaluation Results

OpenAI

Overall: 19/19 tests passed (100.0%)

Provider Total Passed Failed Pass Rate
✅ OPENAI 19 19 0 100.0%

Anthropic

⚠️ Overall: 17/19 tests passed (89.5%)

Provider Total Passed Failed Pass Rate
⚠️ ANTHROPIC 19 17 2 89.5%

❌ Failed Evaluations

Show 2 failures

ANTHROPIC

1. TestReactEval/[anthropic]_react_cat_message

  • Score: 0.00
  • Rubric: The word/emoji is a cat emoji or a heart/love emoji
  • Reason: The output is the text "heart_eyes_cat", which is not an actual cat emoji or a heart/love emoji character.

2. TestThreadsOpenQuestionsFromExportedData/[anthropic]_open_questions_from_eval_timed_dnd.json

  • Score: 0.00
  • Rubric: does not list any questions that went completely unanswered
  • Reason: The output includes an explicit unanswered question: it states “The question raised: should the inconsistency be fixed..., left as-is..., or should the API auto-detect...?” and does not provide a concluded answer/resolution. Therefore it lists a question that went completely unanswered, viola...

This comment was automatically generated by the eval CI pipeline.

@mm-cloud-bot
Copy link
Copy Markdown

Creating a Plugin SpinWick test server

@mm-cloud-bot
Copy link
Copy Markdown

Plugin Spinwick PR #594 🎉

Test server created!

Access here: https://agents-pr-594-wuee6.test.mattermost.cloud

Plugin Version Artifact
agents 4a57f2b Download

Installation ID: pcsxu9q5nbyajc8eqsjowff5mr
Logs: Click here

Credentials: Posted securely in this Mattermost channel - Look for PR #594

Merge origin/master into feature branch. Resolved conflicts:
- bifrost/bifrost.go: convertToBifrostResponsesRequest now returns error;
  kept fallback attachment and adapted to new (req, error) return signature
- bifrost/bifrost_test.go: kept both fallback tests and new master tests
  (structured output enum, multi-type array, proxy routing); updated
  fallback test calls to match new (req, error) return signature

Co-authored-by: Christopher Speller <crspeller@users.noreply.github.com>
@mm-cloud-bot
Copy link
Copy Markdown

New commit detected. SpinWick will update the plugin if a new artifact is available.

@mm-cloud-bot
Copy link
Copy Markdown

Plugin test server updated!

Updated with git commit d90aea5eb14c34c1b16aef0f7789fa37d5bb905c

Plugin Version Artifact
agents d90aea5 Download

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants