Enable the chat completions feature, configure your indexes, and create a workspace to start using conversational search.
Before building a chat interface or generating summarized answers, you need to enable the feature, configure your indexes, and create a workspace. This setup is shared across all conversational search use cases.
Meilisearch automatically generates a “Default Chat API Key” that combines chatCompletions and search permissions on all indexes. Conversational search requires both actions: chatCompletions authorizes the LLM call, and search authorizes the retrieval step that feeds documents to the model. Any key you use with the /chats routes must carry both actions, so prefer the default chat API key unless you have a specific reason to create a custom one.Check if you have the key using:
curl \ -X GET 'MEILISEARCH_URL/keys' \ -H 'Authorization: Bearer MASTER_KEY'
const client = new MeiliSearch({ host: 'MEILISEARCH_URL', apiKey: 'masterKey' })client.getKeys()
MeilisearchClient client = new MeilisearchClient("MEILISEARCH_URL", "masterKey");var keys = await client.GetKeysAsync();
let client = Client::new("MEILISEARCH_URL", Some("MASTER_KEY")); let keys = client .get_keys() .await .unwrap();
client = try MeiliSearch(host: "MEILISEARCH_URL", apiKey: "masterKey")client.getKeys { result in switch result { case .success(let keys): print(keys) case .failure(let error): print(error) }}
var client = MeiliSearchClient('MEILISEARCH_URL', 'masterKey');await client.getKeys();
Look for the key with the description “Default Chat API Key”.
Chat queries only search the indexes that the API key can access. The default chat API key is scoped to all indexes. To limit which indexes a chat client can reach, you have two options:
Create a new API key with both chatCompletions and search actions, scoped to the exact indexes you want exposed. See manage API keys for the full workflow.
Generate a tenant token from the default chat API key. Tenant tokens inherit both the chatCompletions and search actions from their parent key and let you narrow index access or attach search rules per user.
A tenant token cannot grant access to an index its parent API key does not already cover. Make sure the parent key is scoped to every index the token should be allowed to reach.
Configure the chat settings for each index you want to make available to the conversational search agent:
curl \ -X PATCH 'MEILISEARCH_URL/indexes/INDEX_NAME/settings/chat' \ -H 'Authorization: Bearer MEILISEARCH_KEY' \ -H 'Content-Type: application/json' \ --data-binary '{ "description": "A movie database containing titles, genres, release dates, keywords, and plot overviews to help users find films to watch", "documentTemplate": "A movie titled '\''{{doc.title}}'\'' that released in {{ doc.release_date | date: '\''%Y'\'' }}. The movie genres are: {{doc.genres}}. The key themes include: {{doc.keywords}}. The storyline is about: {{doc.overview|truncatewords: 100}}", "documentTemplateMaxBytes": 400 }'
description tells the LLM what the index contains. A good description helps the agent decide which index to search and improves answer relevance. See optimize chat prompts for tips on writing effective descriptions
documentTemplate is a Liquid template that defines the text representation of each document sent to the LLM. Write it as natural language so the model can extract relevant information easily. Consult the document template best practices article for more guidance
documentTemplateMaxBytes sets a size limit on the text generated from the template. If the rendered text exceeds this limit, it is truncated. The default of 400 bytes balances context quality and speed
You can also configure searchParameters to control how the LLM searches the index (hybrid search, result limits, sorting, etc.). See configure index chat settings for all available options.
You can create as many workspaces as you need. Choose any name for WORKSPACE_NAME — if the workspace does not exist, Meilisearch creates it automatically:
curl \ -X PATCH 'MEILISEARCH_URL/chats/WORKSPACE_NAME/settings' \ -H 'Authorization: Bearer MEILISEARCH_KEY' \ -H 'Content-Type: application/json' \ --data-binary '{ "source": "openAi", "apiKey": "PROVIDER_API_KEY", "prompts": { "system": "You are a helpful assistant. Answer questions based only on the provided context." } }'
curl \ -X PATCH 'MEILISEARCH_URL/chats/WORKSPACE_NAME/settings' \ -H 'Authorization: Bearer MEILISEARCH_KEY' \ -H 'Content-Type: application/json' \ --data-binary '{ "source": "mistral", "apiKey": "PROVIDER_API_KEY", "baseUrl": "PROVIDER_API_URL", "prompts": { "system": "You are a helpful assistant. Answer questions based only on the provided context." } }'
curl \ -X PATCH 'MEILISEARCH_URL/chats/WORKSPACE_NAME/settings' \ -H 'Authorization: Bearer MEILISEARCH_KEY' \ -H 'Content-Type: application/json' \ --data-binary '{ "source": "vLlm", "baseUrl": "PROVIDER_API_URL", "prompts": { "system": "You are a helpful assistant. Answer questions based only on the provided context." } }'
baseUrl is required for all providers except OpenAI. For OpenAI, it is optional and only needed if you are using a custom endpoint. See the workspace settings API reference for all available fields.The prompts.system field gives the agent its baseline instructions. For guidance on writing effective prompts, see configure guardrails and optimize chat prompts.