Implementation:Langfuse Langfuse CompileChatMessages
| Knowledge Sources | |
|---|---|
| Domains | Prompt Management, Template Compilation, LLM Integration |
| Last Updated | 2026-02-14 00:00 GMT |
Overview
Concrete tool for compiling chat prompt templates into LLM-ready message arrays by expanding placeholders and substituting text variables, provided by Langfuse.
Description
The compileChatMessages function transforms a prompt template (an array of PromptMessage objects retrieved from getPrompt) into a finalized ChatMessage array ready for LLM consumption. It performs two sequential transformations:
- Placeholder expansion: Messages with type "placeholder" are replaced by arrays of concrete ChatMessage objects supplied by the caller. The function uses flatMap to expand each placeholder in-place, preserving message ordering. If a placeholder name is missing from the provided values, or if the value is not an array of objects, the function throws an error.
- Text variable substitution: After placeholder expansion, the function iterates over all messages and replaces {{variableName}} patterns in string content fields with corresponding values from the textVariables map. The regex handles optional whitespace around the variable name. Messages with non-string content are passed through unchanged.
The module also exports several supporting functions:
- isPlaceholder: Type guard that checks if a PromptMessage has type "placeholder".
- replaceTextVariables: Pure function performing regex-based variable substitution on a single string.
- expandPlaceholder: Takes a PlaceholderMessage and its replacement values, validates the input, and returns an array of ChatMessage objects.
- extractPlaceholderNames: Filters a message array for placeholder messages and returns their names.
- compileChatMessagesWithIds: Variant of compileChatMessages that preserves or assigns UUID v4 IDs to each message, used by the UI layer.
Usage
Import compileChatMessages when you have a chat prompt template from getPrompt and need to fill it with runtime data before sending to an LLM. This is the final step in the prompt lifecycle: after retrieval and dependency resolution, compilation produces the concrete messages for the API call.
Code Reference
Source Location
- Repository: langfuse
- File: packages/shared/src/server/llm/compileChatMessages.ts
- Lines: 65-91 (compileChatMessages), with supporting functions on lines 15-63 and 93-133
Signature
export function compileChatMessages(
messages: PromptMessage[],
placeholderValues: MessagePlaceholderValues,
textVariables?: Record<string, string>,
): ChatMessage[]
Supporting types:
export type MessagePlaceholderValues = Record<string, unknown[]>;
export type PromptMessage = z.infer<typeof PromptChatMessageSchema>;
// PromptChatMessageSchema is a union of:
// { role: string, content: string }
// | { type: "placeholder", name: string }
Import
import {
compileChatMessages,
type MessagePlaceholderValues,
type PromptMessage,
} from "@langfuse/shared/src/server/llm/compileChatMessages";
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| messages | PromptMessage[] | Yes | The chat prompt template array from getPrompt. Each element is either a standard message object with role and content fields, or a placeholder object with type: "placeholder" and a name field. |
| placeholderValues | MessagePlaceholderValues | Yes | A map from placeholder names to arrays of replacement message objects. Each key corresponds to a placeholder name in the template. Each value must be an array of objects conforming to the ChatMessage shape (e.g., { role: "user", content: "..." }). Pass an empty object {} if there are no placeholders. |
| textVariables | Record<string, string> | No | A map from variable names to their string values. Used to replace {{variableName}} patterns in message content fields. If omitted or empty, no text substitution is performed. |
Outputs
| Name | Type | Description |
|---|---|---|
| ChatMessage[] | Array | The compiled message array ready for LLM consumption. All placeholders have been expanded into concrete messages, and all text variable patterns have been substituted. Message ordering is preserved: placeholders expand in-place, with subsequent messages shifted accordingly. |
Errors
| Condition | Error Message |
|---|---|
| Placeholder name not found in placeholderValues | "Missing value for message placeholder: {name}" |
| Placeholder value is not an array | "Placeholder value for '{name}' must be an array of messages" |
| Individual item in placeholder array is not an object | "Invalid message in placeholder '{name}': expected object but got {type}" |
Usage Examples
Basic Text Variable Substitution
import { compileChatMessages } from "@langfuse/shared/src/server/llm/compileChatMessages";
const messages = [
{ role: "system", content: "You are a helpful assistant for {{company_name}}." },
{ role: "user", content: "Summarize this: {{text}}" },
];
const result = compileChatMessages(
messages,
{}, // no placeholders
{ company_name: "Acme Corp", text: "The quarterly results show..." },
);
// Result:
// [
// { role: "system", content: "You are a helpful assistant for Acme Corp." },
// { role: "user", content: "Summarize this: The quarterly results show..." },
// ]
Placeholder Expansion with Few-Shot Examples
const messages = [
{ role: "system", content: "You classify sentiment as positive or negative." },
{ type: "placeholder", name: "examples" },
{ role: "user", content: "Classify: {{input_text}}" },
];
const result = compileChatMessages(
messages,
{
examples: [
{ role: "user", content: "I love this product!" },
{ role: "assistant", content: "positive" },
{ role: "user", content: "Terrible experience." },
{ role: "assistant", content: "negative" },
],
},
{ input_text: "The service was outstanding!" },
);
// Result:
// [
// { role: "system", content: "You classify sentiment as positive or negative." },
// { role: "user", content: "I love this product!" },
// { role: "assistant", content: "positive" },
// { role: "user", content: "Terrible experience." },
// { role: "assistant", content: "negative" },
// { role: "user", content: "Classify: The service was outstanding!" },
// ]
Combined Placeholders and Variables
const messages = [
{ role: "system", content: "You are {{agent_name}}, a customer support agent." },
{ type: "placeholder", name: "conversation_history" },
{ role: "user", content: "{{current_question}}" },
];
const result = compileChatMessages(
messages,
{
conversation_history: [
{ role: "user", content: "What are your hours?" },
{ role: "assistant", content: "We are open 9am-5pm EST." },
],
},
{
agent_name: "Luna",
current_question: "Can I return an item after 30 days?",
},
);
// Result:
// [
// { role: "system", content: "You are Luna, a customer support agent." },
// { role: "user", content: "What are your hours?" },
// { role: "assistant", content: "We are open 9am-5pm EST." },
// { role: "user", content: "Can I return an item after 30 days?" },
// ]
Using compileChatMessagesWithIds for UI Rendering
import { compileChatMessagesWithIds } from "@langfuse/shared/src/server/llm/compileChatMessages";
// Same as compileChatMessages but each message gets an id field.
// Existing non-placeholder messages retain their original IDs.
// Expanded placeholder messages receive new UUID v4 IDs.
const messagesWithIds = [
{ id: "msg_1", role: "system", content: "Hello {{name}}" },
{ id: "msg_2", type: "placeholder", name: "history" },
];
const result = compileChatMessagesWithIds(
messagesWithIds,
{ history: [{ role: "user", content: "Hi" }] },
{ name: "World" },
);
// result[0].id === "msg_1" (preserved)
// result[0].content === "Hello World"
// result[1].id === "<new-uuid>" (generated)
// result[1].content === "Hi"
Extracting Placeholder Names from a Template
import { extractPlaceholderNames } from "@langfuse/shared/src/server/llm/compileChatMessages";
const messages = [
{ role: "system", content: "System prompt" },
{ type: "placeholder", name: "examples" },
{ role: "user", content: "{{question}}" },
{ type: "placeholder", name: "context" },
];
const names = extractPlaceholderNames(messages);
// ["examples", "context"]