How to Configure Custom OpenAI-Compatible Endpoints in Meetily
Meetily supports custom OpenAI-compatible endpoints through a dedicated "Custom Open AI" provider that enables connection to any server implementing the OpenAI chat-completions API, including self-hosted LLMs and third-party inference services.
Meetily, the open-source meeting assistant from Zackriya-Solutions, provides native support for custom OpenAI-compatible endpoints to power its AI summarization engine. This feature allows you to route meeting transcriptions to private infrastructure, local models via Ollama, or alternative API providers without modifying the core Rust codebase.
Understanding the Configuration Architecture
The CustomOpenAIConfig Struct
At the core of this feature is the CustomOpenAIConfig struct defined in src-tauri/src/summary/mod.rs (lines 12-31). This serializable structure stores all necessary connection parameters:
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CustomOpenAIConfig {
/// Base URL of the OpenAI‑compatible API endpoint (e.g. "http://localhost:8000/v1")
pub endpoint: String,
/// API key for authentication (optional)
#[serde(rename = "apiKey")]
pub api_key: Option<String>,
/// Model identifier to use (e.g. "gpt‑4", "llama‑3‑70b")
pub model: String,
/// Maximum tokens for completion (optional)
#[serde(rename = "maxTokens")]
pub max_tokens: Option<i32>,
/// Temperature (0.0‑2.0, optional)
pub temperature: Option<f32>,
/// Top‑P (0.0‑1.0, optional)
#[serde(rename = "topP")]
pub top_p: Option<f32>,
}
The struct uses Serde attributes for JSON compatibility, ensuring seamless serialization between the Rust backend and TypeScript frontend.
Configuration Management Commands
Meetily exposes three Tauri commands in src-tauri/src/api/api.rs to manage the complete lifecycle of custom endpoint configurations.
Saving and Retrieving Settings
To persist a configuration, the api_save_custom_openai_config command (lines 1172-1220) validates input fields and upserts the JSON representation into the SQLite settings table:
#[tauri::command]
pub async fn api_save_custom_openai_config<R: Runtime>(
pool: State<'_, SqlitePool>,
endpoint: String,
api_key: Option<String>,
model: String,
max_tokens: Option<i32>,
temperature: Option<f32>,
top_p: Option<f32>,
) -> Result<serde_json::Value, String> {
let config = CustomOpenAIConfig {
endpoint,
api_key,
model,
max_tokens,
temperature,
top_p,
};
SettingsRepository::save_custom_openai_config(pool, &config).await?;
Ok(json!({ "status": "success", "message": "Custom OpenAI configuration saved successfully" }))
}
Retrieval is handled by api_get_custom_openai_config (lines 1244-1265), which returns the stored configuration or None if unset:
#[tauri::command]
pub async fn api_get_custom_openai_config<R: Runtime>(
pool: State<'_, SqlitePool>,
) -> Result<Option<CustomOpenAIConfig>, String> {
SettingsRepository::get_custom_openai_config(pool).await.map_err(|e| e.to_string())
}
Testing Endpoint Connectivity
Before activating a custom endpoint, you can verify network reachability and API compatibility using api_test_custom_openai_connection (lines 1270-1350). This command sends a minimal chat request ("Hi" with max_tokens: 5) to the specified endpoint and validates the response structure:
#[tauri::command]
pub async fn api_test_custom_openai_connection<R: Runtime>(
endpoint: String,
api_key: Option<String>,
model: String,
) -> Result<serde_json::Value, String> {
let url = format!("{}/chat/completions", endpoint.trim_end_matches('/'));
// Builds test request, sends HTTP POST, validates status code 200,
// and checks for valid choices[0].message.content in JSON response
}
Runtime Integration in the LLM Client
When generating meeting summaries, the system dynamically routes requests to your custom endpoint based on the stored configuration.
URL Construction and Provider Routing
In src-tauri/src/summary/llm_client.rs (lines 66-89), the provider parsing logic identifies the custom-openai variant. During request construction (lines 173-180), the client builds the target URL by appending /chat/completions to the configured base endpoint:
LLMProvider::CustomOpenAI => {
let endpoint = custom_openai_endpoint
.ok_or_else(|| "Custom OpenAI endpoint not configured".to_string())?;
(
format!("{}/chat/completions", endpoint.trim_end_matches('/')),
HeaderMap::new()
)
}
The trim_end_matches('/') call ensures proper URL path joining regardless of whether the user includes a trailing slash.
Dynamic Parameter Injection
The request payload construction (lines 22-27 of llm_client.rs) conditionally includes generation parameters only when using the custom provider. This allows the system to pass max_tokens, temperature, and top_p values directly to compatible endpoints that support these OpenAI-style parameters.
Frontend Integration Examples
Configuring a Custom Endpoint
From the TypeScript frontend, invoke the save command to register a local Ollama server or compatible proxy:
import { invoke } from '@tauri-apps/api/tauri';
await invoke('api_save_custom_openai_config', {
endpoint: 'http://localhost:11434/v1',
api_key: null, // Optional for local servers
model: 'llama3.1:8b',
max_tokens: 1024,
temperature: 0.7,
top_p: 0.9
});
Validating and Using the Connection
Test connectivity before trusting the endpoint for production summaries:
const testResult = await invoke('api_test_custom_openai_connection', {
endpoint: 'http://localhost:11434/v1',
api_key: null,
model: 'llama3.1:8b'
});
console.log(testResult);
// → { status: 'success', message: 'Connection successful …' }
Trigger summary generation by specifying the custom provider:
const summary = await invoke('api_get_summary', {
provider: 'custom-openai',
meeting_id: 'uuid-here',
transcript: 'Meeting transcript text...'
});
Summary
- Meetily implements custom OpenAI-compatible endpoint support through the
CustomOpenAIConfigstruct insrc-tauri/src/summary/mod.rs, enabling connections to any server following the OpenAI chat-completions API specification. - Three Tauri commands—
api_save_custom_openai_config,api_get_custom_openai_config, andapi_test_custom_openai_connection—manage configuration persistence and validation. - Dynamic URL construction in
src-tauri/src/summary/llm_client.rs(lines 173-180) routes requests to{endpoint}/chat/completionswith automatic trailing slash handling. - Optional parameters including
max_tokens,temperature, andtop_pare conditionally injected into requests only for the custom provider case. - No core code modifications are required to use self-hosted models, LocalAI instances, Azure OpenAI, or other compatible endpoints.
Frequently Asked Questions
Which self-hosted LLM servers work with Meetily's custom endpoint feature?
Any server implementing the OpenAI chat-completions API specification works with Meetily's custom OpenAI-compatible endpoint support. This includes Ollama with its OpenAI compatibility layer, LocalAI, LiteLLM Proxy, vLLM, and cloud alternatives like Azure OpenAI Service. The system expects standard /chat/completions endpoints returning JSON with a choices array containing message.content fields.
Is an API key required when configuring a custom OpenAI-compatible endpoint?
No, the API key is optional. The CustomOpenAIConfig struct defines api_key as Option<String>, making authentication unnecessary for local networks or unsecured development servers. However, production deployments using cloud-based compatible endpoints should provide valid authentication tokens through this field.
How does Meetily validate that a custom endpoint is working correctly?
The api_test_custom_openai_connection command performs live validation by sending a minimal POST request to {endpoint}/chat/completions with a test prompt and max_tokens: 5. It verifies HTTP 200 status, valid JSON parsing, and the presence of a non-empty choices[0].message.content field in the response, ensuring the endpoint conforms to expected OpenAI API behavior patterns.
Can I use different generation parameters like temperature for custom endpoints?
Yes, Meetily supports passing dynamic generation parameters including max_tokens, temperature (0.0-2.0), and top_p (0.0-1.0) to custom OpenAI-compatible endpoints. These values are stored in CustomOpenAIConfig and conditionally injected into the request payload only when using the custom provider, allowing fine-grained control over output generation without affecting other LLM providers.
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 →