How to Add Support for a New AI Provider to Meetily: A Step-by-Step Guide

Adding a new AI provider to Meetily requires extending the LLMProvider enum in frontend/src-tauri/src/summary/llm_client.rs, updating the string-to-enum parser, implementing a request-building branch in generate_summary, and exposing the option in the React frontend.

Meetily, the open-source meeting assistant from Zackriya-Solutions, abstracts LLM interactions through a clean Rust layer that supports Ollama, Claude, Groq, OpenRouter, and built-in local models. When you need to add support for a new AI provider to Meetily—whether it's a niche API or a custom OpenAI-compatible endpoint—the architecture lets you integrate without touching the audio pipeline or recording subsystems. This guide details the exact file paths and code modifications required to extend the provider list.

Understanding the Provider Architecture

Meetily's LLM integration relies on a three-part abstraction in the Tauri backend. The LLMProvider enum defines available providers, the from_str method handles configuration parsing, and the generate_summary function dispatches HTTP requests with provider-specific headers and endpoints. This design isolates provider logic to frontend/src-tauri/src/summary/llm_client.rs, ensuring that new integrations only require localized changes.

Step 1: Extend the LLMProvider Enum

Locate the provider definition in frontend/src-tauri/src/summary/llm_client.rs. Add your new provider as a variant to the existing enum:

pub enum LLMProvider {
    OpenAI,
    Claude,
    Groq,
    Ollama,
    OpenRouter,
    BuiltInAI,
    CustomOpenAI,
    MyProvider,  // ← Add your new provider here
}

This enum drives type safety throughout the application, ensuring that the compiler catches unhandled providers at build time.

Step 2: Update the String-to-Enum Parser

In the same file, extend the from_str implementation to recognize your provider's identifier from configuration files and UI selections:

pub fn from_str(s: &str) -> Result<Self, String> {
    match s.to_lowercase().as_str() {
        "openai" => Ok(Self::OpenAI),
        "claude" => Ok(Self::Claude),
        "groq" => Ok(Self::Groq),
        "ollama" => Ok(Self::Ollama),
        "openrouter" => Ok(Self::OpenRouter),
        "myprovider" => Ok(Self::MyProvider),  // ← Add this arm
        _ => Err(format!("Unsupported LLM provider: {}", s)),
    }
}

This parser enables the frontend to pass provider names as strings while the backend operates on type-safe enum variants.

Step 3: Implement Request Building Logic

Inside the generate_summary function, add a match arm that returns the correct API endpoint and headers for your provider:

let (api_url, mut headers) = match provider {
    LLMProvider::OpenAI => ("https://api.openai.com/v1/chat/completions".into(), HeaderMap::new()),
    LLMProvider::Groq => ("https://api.groq.com/openai/v1/chat/completions".into(), HeaderMap::new()),
    LLMProvider::OpenRouter => ("https://openrouter.ai/api/v1/chat/completions".into(), HeaderMap::new()),
    LLMProvider::MyProvider => {
        let mut h = HeaderMap::new();
        h.insert("authorization", format!("Bearer {}", api_key).parse().unwrap());
        ("https://api.myprovider.com/v1/chat/completions".to_string(), h)
    },
    LLMProvider::Ollama => { /* existing Ollama logic */ },
    LLMProvider::BuiltInAI => unreachable!(),
};

This branch ensures Meetily constructs the correct HTTP request format for your provider's chat completions endpoint.

Step 4: Create Provider-Specific Helpers (Optional)

For providers that expose model listing endpoints, create a dedicated module following the OpenRouter pattern. Reference frontend/src-tauri/src/openrouter/openrouter.rs as a template:

// frontend/src-tauri/src/myprovider/myprovider.rs
#[command]
pub fn get_myprovider_models() -> Result<Vec<ModelInfo>, String> {
    let client = Client::new();
    let resp = client
        .get("https://api.myprovider.com/v1/models")
        .bearer_auth(std::env::var("MYPROVIDER_API_KEY").unwrap())
        .send()
        .map_err(|e| e.to_string())?;
    resp.json::<Vec<ModelInfo>>().map_err(|e| e.to_string())
}

Export this module in src-tauri/src/myprovider/mod.rs and register the Tauri command in your main application builder to make model discovery available to the UI.

Step 5: Update the React Frontend

Modify the provider selector component to include your new option. When the user initiates recording, the frontend invokes the Rust backend with the selected provider name:

// In your provider selection component
<select
  value={provider}
  onChange={e => setProvider(e.target.value)}
>
  <option value="openai">OpenAI</option>
  <option value="claude">Claude</option>
  <option value="groq">Groq</option>
  <option value="openrouter">OpenRouter</option>
  <option value="ollama">Ollama</option>
  <option value="myprovider">MyProvider</option>  // ← Add this option
</select>

// Later, when calling the backend
await invoke('generate_summary', {
  provider: 'myprovider',
  apiKey: apiKey,
  // ... other params
});

The string value must match exactly the case you implemented in the Rust from_str parser.

Step 6: Add Unit Tests

Extend the existing test suite in llm_client.rs to cover your new provider. Verify that from_str correctly parses your identifier and that generate_summary constructs the expected request structure:

#[test]
fn test_myprovider_from_str() {
    assert_eq!(LLMProvider::from_str("myprovider").unwrap(), LLMProvider::MyProvider);
    assert_eq!(LLMProvider::from_str("MyProvider").unwrap(), LLMProvider::MyProvider);
}

Testing ensures that refactors to the summary engine do not break your integration.

Key Files Reference

Path Purpose
frontend/src-tauri/src/summary/llm_client.rs Core abstraction containing LLMProvider, from_str, and generate_summary
frontend/src-tauri/src/openrouter/openrouter.rs Template for provider-specific Tauri commands (model fetching)
frontend/src-tauri/src/<provider>/mod.rs Module exports for new provider commands
frontend/src/components/Sidebar/SidebarProvider.tsx React component managing provider selection state

Summary

  • Modify the enum: Add a variant to LLMProvider in llm_client.rs to define the new provider type.
  • Update parsing: Extend from_str to handle the provider's string identifier from configuration.
  • Implement requests: Add a match arm in generate_summary specifying the endpoint URL and authentication headers.
  • Add helpers: Create optional Tauri commands for provider-specific features like model listing.
  • Expose in UI: Update the React frontend to include the new provider in selection dropdowns.
  • Test thoroughly: Verify enum parsing and request construction with unit tests to maintain CI integrity.

Frequently Asked Questions

What file contains the main LLM provider logic?

The primary logic resides in frontend/src-tauri/src/summary/llm_client.rs. This file contains the LLMProvider enum, the from_str parser, and the generate_summary function that dispatches requests to various providers.

Do I need to modify the audio recording system to add a new AI provider?

No. Meetily's architecture cleanly separates the audio pipeline from the LLM integration layer. Adding a provider only requires changes to the summary module (llm_client.rs) and the frontend provider selector, leaving the recording and transcription systems untouched.

Can I integrate a provider that doesn't use OpenAI's API format?

Yes. While Meetily's existing providers largely follow the OpenAI chat completions format, you can customize the request body construction within the generate_summary match arm. Transform the payload structure, headers, and endpoint URL to match your target provider's requirements before the HTTP client sends the request.

How does the frontend communicate the selected provider to the backend?

The React frontend uses Tauri's invoke function to call Rust commands, passing the provider name as a string parameter. The backend then uses LLMProvider::from_str to convert this string into the typed enum variant used by generate_summary to route the request correctly.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →