# How Meetily Supports Multiple AI Providers: Ollama, Claude, Groq, and OpenRouter Integration Explained

> Discover how Meetily seamlessly integrates Ollama, Claude, Groq, and OpenRouter. Learn about its unified LLM client abstraction layer and provider-specific modules for efficient AI model management.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: deep-dive
- Published: 2026-08-01

---

**Meetily supports multiple AI providers through a unified LLM client abstraction layer in its Tauri backend, routing requests to Ollama, Claude, Groq, and OpenRouter via provider-specific modules while exposing a single API to the frontend.**

Meetily's open-source meeting assistant enables users to choose from diverse AI backends—from local **Ollama** instances to cloud providers like **Claude**, **Groq**, and **OpenRouter**—without changing application code. This flexibility is implemented in the Rust-based Tauri backend under `frontend/src-tauri/src/summary/`, where a provider-agnostic architecture handles authentication, request formatting, and token management automatically.

---

## Provider Enumeration and Abstraction

The foundation of Meetily's multi-provider support is the **`LLMProvider`** enum defined 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 single type enumerates every supported backend:

- **`OpenAI`** – default cloud provider
- **`Claude`** – Anthropic's Claude models
- **`Groq`** – Groq's OpenAI-compatible API
- **`Ollama`** – local Ollama server (no API key required)
- **`OpenRouter`** – the OpenRouter model marketplace
- **`BuiltInAI`** and **`CustomOpenAI`** – internal or user-supplied endpoints

The enum implements `from_str` for parsing user selections and `provider_name` for display labels. This abstraction ensures the rest of the codebase remains provider-agnostic.

---

## Request Routing in the Summary Service

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)) orchestrates provider selection. When the UI invokes the `summarize` command, the service:

1. Parses the `model_provider` string into an `LLMProvider` variant
2. Conditionally retrieves API keys (omitted for local providers)
3. Reads custom endpoints for Ollama or CustomOpenAI configurations
4. Delegates to the LLM client for HTTP request construction

Key routing logic:

```rust
let provider = LLMProvider::from_str(&model_provider)?;
let api_key = if provider == LLMProvider::Ollama
              || provider == LLMProvider::BuiltInAI
              || provider == LLMProvider::CustomOpenAI {
    None
} else {
    Some(user_provided_key)
};

```

This conditional key handling eliminates configuration friction for local deployments while maintaining security for cloud credentials.

---

## Provider-Specific Integration Modules

Each AI backend has a dedicated module implementing discovery, request formatting, and authentication:

### Ollama Integration ([`ollama/ollama.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/ollama/ollama.rs))

The **Ollama module** manages local LLM execution:

- Validates the endpoint URL (default: `http://127.0.0.1:11434`)
- Discovers available models via `GET /api/tags`
- Automatically downloads missing models
- Constructs Ollama-native request bodies without API keys

### Claude Integration ([`anthropic/anthropic.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/anthropic/anthropic.rs))

The **Anthropic module** handles cloud-based Claude models:

- Maintains Claude model listings with version and capability metadata
- Builds Anthropic-specific JSON schemas distinct from OpenAI format
- Injects required headers including `anthropic-version`

### Groq Integration ([`groq/groq.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/groq/groq.rs))

The **Groq module** leverages Groq's OpenAI-compatible API:

- Queries `/v1/models` for available model inventory
- Caches model listings to reduce API calls
- Uses standard OpenAI request schemas (Groq maintains compatibility)

### OpenRouter Integration ([`openrouter/openrouter.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/openrouter/openrouter.rs))

The **OpenRouter module** connects to the model aggregation service:

- Retrieves the complete OpenRouter model catalog
- Sets the `Authorization` header with user-provided OpenRouter credentials
- Enables access to hundreds of models through a single integration point

### Built-in and Custom Endpoints ([`summary/summary_engine/client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/summary/summary_engine/client.rs))

For **self-hosted or internal models**, this module supports arbitrary OpenAI-compatible endpoints, allowing enterprises to point Meetily at private inference servers.

All modules expose a consistent interface: `fn get_<provider>_models(...) -> Result<Vec<Model>, String>`, enabling a unified model picker in the UI.

---

## Unified Request Handling and Response Parsing

The **[`llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/llm_client.rs)** module centralizes HTTP execution. Despite provider differences, it produces a uniform interface:

- **Request body selection** – Most providers use OpenAI-compatible schemas; Claude requires special handling
- **Header injection** – Cloud providers receive `Authorization` headers; Ollama receives none
- **Response normalization** – All results parse into a unified `LLMResponse` type

Example request construction:

```rust
let request_body = if provider != &LLMProvider::Claude {
    serde_json::json!({
        "model": model_name,
        "messages": messages,
        "max_tokens": max_tokens,
        "temperature": temperature,
    })
} else {
    serde_json::json!(ClaudeRequest { /* Anthropic-specific fields */ })
};

```

The frontend communicates through a single Tauri command regardless of provider:

```javascript
import { invoke } from '@tauri-apps/api/tauri';

async function summarize(meetingId, provider) {
  const result = await invoke('summarize', {
    meetingId,
    modelProvider: provider, // "ollama", "claude", "groq", "openrouter"
  });
  return result;
}

```

---

## Token Limit Adaptation by Provider

Different providers enforce varying **context window limits**. The **summary processor** ([`frontend/src-tauri/src/summary/processor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/processor.rs)) adapts chunking strategy accordingly:

```rust
if (provider != &LLMProvider::Ollama && provider != &LLMProvider::BuiltInAI)
   || total_tokens < token_threshold { 
    // Apply chunking for cloud providers or large transcripts
}

```

**Local providers** (Ollama, BuiltInAI) typically receive complete transcripts—their local operation removes network latency and cost constraints. **Cloud providers** may receive strategically chunked content to respect rate limits and token quotas.

---

## Key Source Files

| Component | File Path | Purpose |
|-----------|-----------|---------|
| Provider enum and helpers | [`frontend/src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/llm_client.rs) | Defines `LLMProvider`, request routing, HTTP execution |
| Summarization service | [`frontend/src-tauri/src/summary/service.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/service.rs) | Parses UI requests, manages credentials |
| Token-aware processor | [`frontend/src-tauri/src/summary/processor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/summary/processor.rs) | Applies provider-specific chunking logic |
| Ollama driver | [`frontend/src-tauri/src/ollama/ollama.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/ollama/ollama.rs) | Local model discovery and execution |
| Claude driver | [`frontend/src-tauri/src/anthropic/anthropic.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/anthropic/anthropic.rs) | Anthropic API integration |
| Groq driver | [`frontend/src-tauri/src/groq/groq.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/groq/groq.rs) | Groq cloud integration |
| OpenRouter driver | [`frontend/src-tauri/src/openrouter/openrouter.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/openrouter/openrouter.rs) | OpenRouter marketplace access |

---

## Summary

- **Provider abstraction** via `LLMProvider` enum centralizes backend selection in [`llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/llm_client.rs)
- **Conditional authentication** automatically omits API keys for local providers (Ollama, BuiltInAI)
- **Modular drivers** in dedicated directories handle provider-specific discovery, headers, and request formats
- **Unified frontend API** exposes a single `invoke('summarize', ...)` command regardless of chosen backend
- **Adaptive token handling** applies aggressive chunking only to cloud providers, preserving full context for local models

---

## Frequently Asked Questions

### How do I switch between AI providers in Meetily?

Provider selection occurs through the `modelProvider` parameter in the `summarize` Tauri command. The UI passes a string like `"ollama"`, `"claude"`, `"groq"`, or `"openrouter"`, which `LLMProvider::from_str` parses into the appropriate enum variant. No frontend code changes are required to switch providers.

### Does Meetily require an API key for every provider?

No. The [`summary/service.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/summary/service.rs) routing logic explicitly excludes `LLMProvider::Ollama`, `LLMProvider::BuiltInAI`, and `LLMProvider::CustomOpenAI` from key requirements. Cloud providers (Claude, Groq, OpenRouter, OpenAI) require valid API keys, which the service retrieves from user settings.

### Why does Claude use a different request format than other providers?

Anthropic's Claude API predates widespread OpenAI compatibility and maintains a distinct JSON schema. The [`llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/llm_client.rs) module detects `LLMProvider::Claude` and branches to a `ClaudeRequest` struct, while Groq, OpenRouter, and most others accept standard OpenAI-compatible payloads.

### Can I use a self-hosted model with Meetily?

Yes. The `CustomOpenAI` variant in `LLMProvider` supports arbitrary OpenAI-compatible endpoints. Configure your custom base URL in settings, and the summary service routes requests to your self-hosted inference server without cloud dependencies.