How Meetily Supports Multiple AI Providers: Ollama, Claude, Groq, and OpenRouter Integration Explained
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. This single type enumerates every supported backend:
OpenAI– default cloud providerClaude– Anthropic's Claude modelsGroq– Groq's OpenAI-compatible APIOllama– local Ollama server (no API key required)OpenRouter– the OpenRouter model marketplaceBuiltInAIandCustomOpenAI– 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) orchestrates provider selection. When the UI invokes the summarize command, the service:
- Parses the
model_providerstring into anLLMProvidervariant - Conditionally retrieves API keys (omitted for local providers)
- Reads custom endpoints for Ollama or CustomOpenAI configurations
- Delegates to the LLM client for HTTP request construction
Key routing logic:
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)
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)
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)
The Groq module leverages Groq's OpenAI-compatible API:
- Queries
/v1/modelsfor available model inventory - Caches model listings to reduce API calls
- Uses standard OpenAI request schemas (Groq maintains compatibility)
OpenRouter Integration (openrouter/openrouter.rs)
The OpenRouter module connects to the model aggregation service:
- Retrieves the complete OpenRouter model catalog
- Sets the
Authorizationheader 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)
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 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
Authorizationheaders; Ollama receives none - Response normalization – All results parse into a unified
LLMResponsetype
Example request construction:
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:
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) adapts chunking strategy accordingly:
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 |
Defines LLMProvider, request routing, HTTP execution |
| Summarization service | frontend/src-tauri/src/summary/service.rs |
Parses UI requests, manages credentials |
| Token-aware processor | frontend/src-tauri/src/summary/processor.rs |
Applies provider-specific chunking logic |
| Ollama driver | frontend/src-tauri/src/ollama/ollama.rs |
Local model discovery and execution |
| Claude driver | frontend/src-tauri/src/anthropic/anthropic.rs |
Anthropic API integration |
| Groq driver | frontend/src-tauri/src/groq/groq.rs |
Groq cloud integration |
| OpenRouter driver | frontend/src-tauri/src/openrouter/openrouter.rs |
OpenRouter marketplace access |
Summary
- Provider abstraction via
LLMProviderenum centralizes backend selection inllm_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 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 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →