# How to Add Support for a New LLM Provider in Meetily: Ollama, Claude, Groq, and OpenRouter

> Learn to add new LLM providers like Ollama Claude Groq and OpenRouter to Meetily. Extend the LLMProvider enum implement parsers and update settings for seamless integration.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: how-to-guide
- Published: 2026-07-09

---

**To add a new LLM provider in Meetily, extend the `LLMProvider` enum in [`frontend/src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/llm_client.rs), implement the `from_str` parser, add the endpoint and headers in the `generate_summary` match statement, and expose the new option in the settings UI.**

Meetily abstracts LLM communication behind a unified Rust backend that handles multiple providers through a single interface. To add support for services like **Ollama**, **Claude**, **Groq**, or **OpenRouter**, you modify the provider enumeration and request-building logic in the Tauri backend. This guide walks through the exact implementation steps using the actual source code from the `Zackriya-Solutions/meetily` repository.

## Extend the LLMProvider Enum

First, add your new provider to the enumeration that defines supported services. In [`frontend/src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/llm_client.rs), locate the `LLMProvider` enum around lines 66-74 and add a new variant:

```rust
// frontend/src-tauri/src/summary/llm_client.rs
pub enum LLMProvider {
    OpenAI,
    Claude,
    Groq,
    Ollama,
    OpenRouter,
    BuiltInAI,
    CustomOpenAI,
    MyNewProvider,  // ← Add your new provider here
}

```

This enum acts as the source of truth for all supported LLM integrations throughout the application.

## Implement String Parsing with from_str

Meetily converts user-selected strings from the UI into enum variants using the `from_str` method. Update the implementation around lines 78-90 to handle your new provider:

```rust
impl LLMProvider {
    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),
            "mynewprovider" => Ok(Self::MyNewProvider),  // ↔ new mapping
            _ => Err(format!("Unsupported LLM provider: {}", s)),
        }
    }
}

```

The string literal you match here (e.g., `"mynewprovider"`) must match the value stored in the settings database and passed from the UI.

## Configure API Endpoints in generate_summary

The `generate_summary` function uses a match statement to select the correct API endpoint and construct the request payload. Around lines 51-73, add a new arm for your provider:

```rust
match provider {
    LLMProvider::OpenAI => {
        let endpoint = "https://api.openai.com/v1/chat/completions".to_string();
        (endpoint, header::HeaderMap::new())
    }
    LLMProvider::MyNewProvider => {
        // Example: OpenAI-compatible endpoint
        let endpoint = "https://api.mynewprovider.com/v1/chat/completions".to_string();
        (endpoint, header::HeaderMap::new())
    }
    // ... other providers
}

```

If your provider uses a custom request schema (like Claude's distinct message format), create a provider-specific struct similar to `ClaudeRequest` and build the payload in the conditional block that handles non-OpenAI formats.

## Handle Provider-Specific Headers

For services requiring unique authentication headers, insert the header logic within the same match section. For example, Claude uses `x-api-key` instead of the standard `Authorization` header around lines 81-90:

```rust
let mut header_map = header::HeaderMap::new();
header_map.insert("x-api-key", api_key.parse()?);

```

Apply this pattern to your provider if it requires custom headers like `X-API-Key`, `api-key`, or specialized content-type specifications.

## Update the provider_name Helper for Logging

Meetily uses a helper function to generate human-readable names for debug output and logging. Around lines 35-45, add a match arm for your new variant:

```rust
match provider {
    LLMProvider::OpenAI => "OpenAI",
    LLMProvider::Claude => "Claude",
    LLMProvider::Groq => "Groq",
    LLMProvider::Ollama => "Ollama",
    LLMProvider::OpenRouter => "OpenRouter",
    LLMProvider::MyNewProvider => "MyNewProvider",
    _ => "Unknown",
}

```

This ensures that logs and error messages clearly identify which provider is handling the request.

## Expose the Provider in the Settings UI

The frontend settings screen must allow users to select your new provider. In the React/TypeScript components (typically [`frontend/src/app/Settings.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/app/Settings.tsx) or similar), add your provider string to the dropdown or selection list:

```typescript
const providers = [
  { value: "openai", label: "OpenAI" },
  { value: "claude", label: "Claude" },
  { value: "mynewprovider", label: "MyNewProvider" },
  // ... other providers
];

```

Ensure the `value` matches exactly the string handled by `LLMProvider::from_str` in the Rust backend.

## Persist the Selection in the Database

User preferences are stored via the settings repository in [`frontend/src-tauri/src/database/repositories/setting.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/repositories/setting.rs) (lines 1-20). The system stores key-value pairs as strings, so no schema migration is required. When the user selects your new provider, the string value is saved automatically and retrieved by the summary service ([`frontend/src-tauri/src/summary/service.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/service.rs)) when generating summaries.

## Test the Integration End-to-End

Verify your implementation by running the Tauri development server and executing a full workflow:

1. **Start the dev server**: `pnpm run tauri:dev`
2. **Select the provider**: Navigate to *Settings → LLM Provider* and choose your new option
3. **Trigger a summary**: Start a recording, let Meetily transcribe the audio, and click *Generate Summary*
4. **Verify the request**: Run with debug logging (`RUST_LOG=debug`) and confirm the request URL matches your configured endpoint and that the response parses correctly

If your provider uses a custom response format, add a deserialization struct similar to `ClaudeChatResponse` and adjust the final parsing block around lines 300-330 to extract the generated text.

## Summary

- **Extend the enum**: Add your provider to `LLMProvider` in [`frontend/src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/llm_client.rs)
- **Parse the string**: Update `from_str` to recognize the new provider identifier
- **Configure the endpoint**: Add the API URL and headers in the `generate_summary` match statement
- **Handle custom headers**: Insert special authentication headers if the provider requires them
- **Update logging**: Add the display name to the `provider_name` helper
- **Wire the UI**: Add the provider to the settings dropdown in the frontend React components
- **Persist settings**: The database automatically stores the selection via [`setting.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/setting.rs)
- **Test**: Run the full transcription-to-summary workflow with debug logging enabled

## Frequently Asked Questions

### Which file contains the main LLM provider logic in Meetily?

The core integration logic resides in [`frontend/src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/llm_client.rs). This file contains the `LLMProvider` enum definition, the `from_str` parser, the `generate_summary` function that handles HTTP requests, and the `provider_name` helper for logging.

### Do I need to modify the database schema to add a new LLM provider?

No, the settings repository in [`frontend/src-tauri/src/database/repositories/setting.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/database/repositories/setting.rs) stores the provider as a generic key-value string pair. As long as your new provider name is handled by `LLMProvider::from_str`, the system will persist and retrieve it without any schema changes.

### How does Meetily handle different API request formats between providers?

The `generate_summary` function uses a Rust match statement to select endpoints and construct appropriate payloads. For OpenAI-compatible providers, it uses standard chat completion formats. For unique schemas like Claude, it constructs provider-specific request structs (e.g., `ClaudeRequest`) and handles response parsing with dedicated deserialization structs such as `ClaudeChatResponse` around lines 300-330.

### Can I add a provider that requires a custom authentication header?

Yes, you can insert custom headers within the provider's match arm in `generate_summary`. For example, Claude uses `x-api-key` instead of `Authorization`, which is implemented by creating a new `HeaderMap` and inserting the required key before returning the endpoint tuple.