# How Meetily's Summary Engine Integrates with Multiple AI Providers (Ollama, Claude, Groq)

> Discover how Meetily's summary engine seamlessly integrates with Ollama, Claude, and Groq. Learn about its provider-agnostic design for flexible AI backend routing and a unified chat interface.

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

---

**TLDR:** Meetily employs a provider-agnostic abstraction layer centered on the `LLMProvider` enum and `SummaryService` to route meeting transcripts to diverse AI backends—including Ollama, Claude, and Groq—through a unified `chat` interface that handles provider-specific request formatting, authentication, and local versus cloud endpoint differences.

Meetily's open-source meeting assistant supports heterogeneous large language model (LLM) backends to generate intelligent summaries from audio transcripts. The **Meetily summary engine integrates with multiple AI providers** through a modular Rust architecture that abstracts HTTP client differences behind a single orchestration service, allowing seamless switching between local models and cloud APIs without changing application logic.

## The Pluggable Provider Architecture

At the core of Meetily's multi-provider capability is the `LLMProvider` enum defined in [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs). This enumeration declares all supported backends: **OpenAI**, **Anthropic**, **Ollama**, **Groq**, **OpenRouter** (for Claude), and **CustomOpenAI**.

The engine treats these providers as interchangeable modules. When `SummaryService::generate_summary` in [`src-tauri/src/summary/service.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/service.rs) initiates a summarization request, it matches the selected provider variant to dispatch the call to the appropriate client implementation. This design eliminates provider-specific logic from the core summarization pipeline, ensuring that transcript chunking, token budgeting, and result aggregation remain agnostic to whether the underlying model runs locally or in the cloud.

## Provider-Specific Implementation Patterns

Each AI backend requires distinct authentication headers, endpoint URLs, and payload schemas. Meetily encapsulates these differences in dedicated modules while exposing a consistent `chat` method signature.

### Ollama (Local Execution)

The Ollama integration in [`src-tauri/src/ollama/ollama.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/ollama/ollama.rs) targets local inference servers. It requires no API key and defaults to `http://127.0.0.1:11434/api/chat`. The client accepts an optional custom endpoint parameter, enabling users to route requests to alternative local ports or networked Ollama instances.

```rust
pub async fn chat(
    request: &ChatRequest,
    endpoint: Option<String>,
) -> Result<ChatResponse, String> {
    let url = endpoint.unwrap_or_else(|| "http://127.0.0.1:11434/api/chat".to_string());
    let client = reqwest::Client::new();
    client.post(&url)
        .json(request)
        .send()
        .await
        .map_err(|e| e.to_string())?
        .json::<ChatResponse>()
        .await
        .map_err(|e| e.to_string())
}

```

### Claude via OpenRouter

To support Claude, Meetily leverages the OpenRouter gateway implemented in [`src-tauri/src/openrouter/openrouter.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/openrouter/openrouter.rs). This approach normalizes Anthropic's native API to an OpenAI-compatible chat schema, allowing the summary engine to use identical request structures across providers while OpenRouter handles protocol translation.

### Groq and Anthropic (Direct Cloud APIs)

For Groq, the client in [`src-tauri/src/groq/groq.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/groq/groq.rs) sends POST requests to Groq's OpenAI-compatible `/v1/chat/completions` endpoint. Similarly, [`src-tauri/src/anthropic/anthropic.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/anthropic/anthropic.rs) implements Anthropic's direct Claude API for users who prefer native integration over the OpenRouter bridge. Both modules handle API key authentication and model caching.

## The Summarization Orchestration Flow

The integration process follows a strict pipeline defined in [`src-tauri/src/summary/service.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/service.rs):

1. **Configuration Retrieval**: `SummaryService::generate_summary` queries the SQLite settings database via [`src-tauri/src/database/repositories/setting.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/database/repositories/setting.rs) to fetch the active `LLMProvider` variant and associated credentials.
2. **Provider Dispatch**: A `match provider { ... }` block selects the concrete implementation, constructing provider-specific headers and URLs.
3. **Chunk-Aware Processing**: If transcripts exceed token limits, [`src-tauri/src/summary/processor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/processor.rs) performs multi-level chunking, sending partial requests to the selected provider and aggregating responses.
4. **Final Polishing**: The engine optionally submits concatenated partial summaries back to the LLM for coherence refinement, producing a unified output regardless of which provider performed the initial processing.

```rust
pub async fn generate_summary(
    db: DbHandle,
    provider: LLMProvider,
    ollama_endpoint: Option<String>,
) -> Result<String, String> {
    // ...prepare transcript, chunking, token budget...
    let llm_response = match provider {
        LLMProvider::OpenAI => openai::chat(&payload, api_key).await?,
        LLMProvider::Anthropic => anthropic::chat(&payload, api_key).await?,
        LLMProvider::Groq => groq::chat(&payload, api_key).await?,
        LLMProvider::Ollama => ollama::chat(&payload, ollama_endpoint).await?,
        LLMProvider::Claude => openrouter::chat(&payload, api_key).await?,
        _ => return Err("Unsupported provider".into()),
    };
    Ok(llm_response.content)
}

```

## Frontend Integration and TypeScript Commands

The frontend invokes the Rust backend through Tauri's command system. The TypeScript interface allows users to trigger summarization while specifying provider context:

```typescript
await invoke('generate_summary', {
  meeting_id: 42,
  provider: 'ollama',
  ollama_endpoint: undefined
});

```

This command passes through to the `generate_summary` function, which handles provider selection and error propagation back to the UI.

## Extensibility and Fallback Behavior

Adding a new provider requires only three steps: creating a new module in `src-tauri/src/<provider>/`, implementing the `chat` method with the standard signature, and adding the variant to the `LLMProvider` enum. The existing `match` statement in [`llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/llm_client.rs) automatically routes requests to the new implementation without modifying `SummaryService` logic.

If a provider becomes unreachable—such as when the Ollama server is offline or an API key expires—the service logs the error and can gracefully degrade to a cached local model or built-in summarizer, ensuring the meeting pipeline remains functional.

## Summary

- **Unified Abstraction**: The `LLMProvider` enum in [`src-tauri/src/summary/llm_client.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/llm_client.rs) and `SummaryService` in [`src-tauri/src/summary/service.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/service.rs) provide a single interface for diverse AI backends.
- **Local and Cloud Support**: Ollama runs via localhost without authentication, while Claude, Groq, and Anthropic integrate through authenticated HTTPS endpoints.
- **OpenRouter Bridge**: Claude support is achieved through OpenRouter normalization, simplifying request schema management.
- **Chunking Resilience**: [`src-tauri/src/summary/processor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/processor.rs) handles token limits through multi-level chunking that adapts to each provider's constraints.
- **Zero-Change Extensibility**: New providers integrate by adding enum variants and match arms without touching core summarization logic.

## Frequently Asked Questions

### How does Meetily handle authentication for different AI providers?

Authentication credentials are stored in the local SQLite database via [`src-tauri/src/database/repositories/setting.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/database/repositories/setting.rs). Cloud providers like Groq and Anthropic retrieve API keys from this store, while Ollama requires no authentication. The `SummaryService` passes these credentials to provider-specific `chat` functions only when constructing HTTP headers.

### Can I use a custom OpenAI-compatible endpoint instead of the official API?

Yes. Meetily includes a `CustomOpenAI` variant in the `LLMProvider` enum that routes requests through user-specified base URLs. This allows integration with private OpenAI API proxies or compatible services by configuring the endpoint in the settings repository alongside the API key.

### What happens if my transcript exceeds the token limit of my chosen provider?

The `SummaryService` automatically delegates to the chunking logic in [`src-tauri/src/summary/processor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/src-tauri/src/summary/processor.rs). This module splits transcripts into token-safe segments, dispatches parallel or sequential requests to the selected provider, and merges partial summaries. For Ollama and other local models, the engine optimizes chunk sizes to minimize latency on consumer hardware.

### Is it possible to switch providers mid-meeting or for different summary types?

Provider selection is persisted per application instance in the settings database. While the current architecture binds a single provider to each summary generation request, the frontend can invoke `generate_summary` with explicit provider overrides (as shown in the TypeScript example) to route specific meetings to different backends without changing global settings.