Message Helpers
Message helpers are utility functions for working with BaseMessage
content in VoltAgent. Message content can be either a string or an array of content parts (text, image, or file), and these helpers provide type-safe operations for both formats.
Import
import { messageHelpers } from "@voltagent/core";
// Or import individual functions
import { isTextContent, extractText, MessageContentBuilder } from "@voltagent/core/utils";
Type Guards
Type guards determine the format of message content and enable type-safe operations.
isTextContent()
Checks if content is a string.
import { isTextContent } from "@voltagent/core/utils";
const stringContent = "Hello world";
const arrayContent = [{ type: "text", text: "Hello" }];
console.log(isTextContent(stringContent)); // true
console.log(isTextContent(arrayContent)); // false
isStructuredContent()
Checks if content is an array of content parts.
import { isStructuredContent } from "@voltagent/core/utils";
const stringContent = "Hello world";
const arrayContent = [
{ type: "text", text: "Hello" },
{ type: "image", image: "data:image/png;base64..." },
];
console.log(isStructuredContent(stringContent)); // false
console.log(isStructuredContent(arrayContent)); // true
hasTextPart()
Checks if content contains any text, regardless of format.
import { hasTextPart } from "@voltagent/core/utils";
const stringContent = "Hello";
const mixedContent = [
{ type: "text", text: "Description" },
{ type: "image", image: "data..." },
];
const imageOnlyContent = [{ type: "image", image: "data..." }];
console.log(hasTextPart(stringContent)); // true
console.log(hasTextPart(mixedContent)); // true
console.log(hasTextPart(imageOnlyContent)); // false
hasImagePart()
and hasFilePart()
Check for specific content part types.
import { hasImagePart, hasFilePart } from "@voltagent/core/utils";
const content = [
{ type: "text", text: "Check this image:" },
{ type: "image", image: "data:image/png;base64..." },
{ type: "file", data: "file content", mimeType: "text/plain" },
];
console.log(hasImagePart(content)); // true
console.log(hasFilePart(content)); // true
console.log(hasImagePart("text")); // false
Extractors
Extractors retrieve specific content types from messages.
extractText()
Extracts all text from content, concatenating multiple text parts.
import { extractText } from "@voltagent/core/utils";
// From string content
const text1 = extractText("Hello world");
console.log(text1); // "Hello world"
// From structured content
const content = [
{ type: "text", text: "Hello " },
{ type: "image", image: "data..." },
{ type: "text", text: "world" },
];
const text2 = extractText(content);
console.log(text2); // "Hello world"
// From non-text content
const imageOnly = [{ type: "image", image: "data..." }];
const text3 = extractText(imageOnly);
console.log(text3); // ""
extractTextParts()
Returns all text parts as an array, preserving structure.
import { extractTextParts } from "@voltagent/core/utils";
const content = [
{ type: "text", text: "First paragraph" },
{ type: "image", image: "data..." },
{ type: "text", text: "Second paragraph" },
];
const textParts = extractTextParts(content);
console.log(textParts);
// [
// { type: "text", text: "First paragraph" },
// { type: "text", text: "Second paragraph" }
// ]
// String content returns array format
const stringParts = extractTextParts("Hello");
console.log(stringParts);
// [{ type: "text", text: "Hello" }]
extractImageParts()
and extractFileParts()
Extract specific content part types.
import { extractImageParts, extractFileParts } from "@voltagent/core/utils";
const content = [
{ type: "text", text: "Files:" },
{ type: "image", image: "image1.png" },
{ type: "file", data: "doc.pdf", mimeType: "application/pdf" },
{ type: "image", image: "image2.jpg" },
];
const images = extractImageParts(content);
console.log(images.length); // 2
console.log(images[0]); // { type: "image", image: "image1.png" }
const files = extractFileParts(content);
console.log(files.length); // 1
console.log(files[0]); // { type: "file", data: "doc.pdf", mimeType: "application/pdf" }
Transformers
Transformers modify message content while preserving structure.
transformTextContent()
Applies a transformation function to all text parts.
import { transformTextContent } from "@voltagent/core/utils";
// Transform string content
const upper1 = transformTextContent("hello", (text) => text.toUpperCase());
console.log(upper1); // "HELLO"
// Transform structured content
const content = [
{ type: "text", text: "hello" },
{ type: "image", image: "data..." },
{ type: "text", text: "world" },
];
const upper2 = transformTextContent(content, (text) => text.toUpperCase());
console.log(upper2);
// [
// { type: "text", text: "HELLO" },
// { type: "image", image: "data..." },
// { type: "text", text: "WORLD" }
// ]
mapMessageContent()
Transforms text content within a complete message object.
import { mapMessageContent } from "@voltagent/core/utils";
import type { BaseMessage } from "@voltagent/core";
const message: BaseMessage = {
role: "user",
content: "hello world",
};
const loudMessage = mapMessageContent(message, (text) => text.toUpperCase());
console.log(loudMessage);
// { role: "user", content: "HELLO WORLD" }
// Works with structured content too
const complexMessage: BaseMessage = {
role: "assistant",
content: [
{ type: "text", text: "The answer is" },
{ type: "text", text: "42" },
],
};
const emphasized = mapMessageContent(complexMessage, (text) => `**${text}**`);
console.log(emphasized.content);
// [
// { type: "text", text: "**The answer is**" },
// { type: "text", text: "**42**" }
// ]
filterContentParts()
Filters content parts based on a predicate function.
import { filterContentParts } from "@voltagent/core/utils";
const content = [
{ type: "text", text: "Keep this" },
{ type: "image", image: "remove.png" },
{ type: "text", text: "Keep this too" },
{ type: "file", data: "remove.pdf" },
];
// Keep only text parts
const textOnly = filterContentParts(content, (part) => part.type === "text");
console.log(textOnly);
// [
// { type: "text", text: "Keep this" },
// { type: "text", text: "Keep this too" }
// ]
// If only one text part remains, returns string
const singleContent = [
{ type: "text", text: "Only text" },
{ type: "image", image: "img.png" },
];
const filtered = filterContentParts(singleContent, (part) => part.type === "text");
console.log(filtered); // "Only text"
Normalizers
Normalizers convert between content formats.
normalizeToArray()
Converts any content format to array format.
import { normalizeToArray } from "@voltagent/core/utils";
// String to array
const array1 = normalizeToArray("Hello");
console.log(array1);
// [{ type: "text", text: "Hello" }]
// Array remains array
const content = [
{ type: "text", text: "Hello" },
{ type: "image", image: "data..." },
];
const array2 = normalizeToArray(content);
console.log(array2 === content); // true (same reference)
normalizeContent()
Converts content to the most compact representation.
import { normalizeContent } from "@voltagent/core/utils";
// Single text part becomes string
const content1 = [{ type: "text", text: "Hello" }];
const normalized1 = normalizeContent(content1);
console.log(normalized1); // "Hello"
// Empty array becomes empty string
const content2 = [];
const normalized2 = normalizeContent(content2);
console.log(normalized2); // ""
// Multiple parts remain as array
const content3 = [
{ type: "text", text: "Hello" },
{ type: "image", image: "data..." },
];
const normalized3 = normalizeContent(content3);
console.log(Array.isArray(normalized3)); // true
MessageContentBuilder
A builder class for constructing complex message content.
Basic Usage
import { MessageContentBuilder } from "@voltagent/core/utils";
const builder = new MessageContentBuilder();
// Build simple text
const simple = builder.addText("Hello world").build();
console.log(simple); // "Hello world"
// Build complex content
builder.clear(); // Reset the builder
const complex = builder
.addText("Here's an image:")
.addImage("data:image/png;base64,...")
.addText("And here's a file:")
.addFile("document.pdf", "application/pdf")
.build();
console.log(Array.isArray(complex)); // true
console.log(complex.length); // 4
Builder Methods
const builder = new MessageContentBuilder();
// Add various content types
builder
.addText("Step 1")
.addImage("screenshot.png")
.addFile("data.csv", "text/csv")
.addPart({ type: "custom", data: "..." }); // Custom parts
// Builder state
console.log(builder.length); // 4
// Build as array (always returns array)
const asArray = builder.buildAsArray();
console.log(Array.isArray(asArray)); // true
// Clear and reuse
builder.clear();
console.log(builder.length); // 0
Convenience Functions
Pre-built functions for common operations.
addTimestampToMessage()
Adds timestamps to user messages.
import { addTimestampToMessage } from "@voltagent/core/utils";
import type { BaseMessage } from "@voltagent/core";
const userMessage: BaseMessage = {
role: "user",
content: "What's the weather?",
};
// With custom timestamp
const stamped1 = addTimestampToMessage(userMessage, "10:30:00");
console.log(stamped1.content); // "[10:30:00] What's the weather?"
// With automatic timestamp
const stamped2 = addTimestampToMessage(userMessage);
console.log(stamped2.content); // "[14:23:45] What's the weather?" (current time)
// Non-user messages are unchanged
const assistantMessage: BaseMessage = {
role: "assistant",
content: "The weather is sunny",
};
const unchanged = addTimestampToMessage(assistantMessage);
console.log(unchanged.content); // "The weather is sunny"
prependToMessage()
and appendToMessage()
Add text to the beginning or end of message content.
import { prependToMessage, appendToMessage } from "@voltagent/core/utils";
import type { BaseMessage } from "@voltagent/core";
const message: BaseMessage = {
role: "user",
content: "Execute this",
};
const withPrefix = prependToMessage(message, "URGENT: ");
console.log(withPrefix.content); // "URGENT: Execute this"
const withSuffix = appendToMessage(message, " immediately!");
console.log(withSuffix.content); // "Execute this immediately!"
// Works with structured content
const structured: BaseMessage = {
role: "assistant",
content: [
{ type: "text", text: "Result" },
{ type: "image", image: "graph.png" },
],
};
const prefixed = prependToMessage(structured, "Final ");
console.log(prefixed.content[0]); // { type: "text", text: "Final Result" }
hasContent()
and getContentLength()
Utility functions for content inspection.
import { hasContent, getContentLength } from "@voltagent/core/utils";
import type { BaseMessage } from "@voltagent/core";
// Check if message has content
const empty: BaseMessage = { role: "user", content: "" };
const withText: BaseMessage = { role: "user", content: "Hello" };
const emptyArray: BaseMessage = { role: "user", content: [] };
console.log(hasContent(empty)); // false
console.log(hasContent(withText)); // true
console.log(hasContent(emptyArray)); // false
// Get content length
console.log(getContentLength("Hello")); // 5 (string length)
console.log(getContentLength([])); // 0 (array length)
console.log(
getContentLength([
{ type: "text", text: "Hi" },
{ type: "image", image: "..." },
])
); // 2 (array length)
Using with Hooks
Message helpers integrate with agent hooks for message transformation.
import { Agent, messageHelpers } from "@voltagent/core";
import { VercelAIProvider } from "@voltagent/vercel-ai";
import { openai } from "@ai-sdk/openai";
const agent = new Agent({
name: "Assistant",
description: "A helpful assistant",
llm: new VercelAIProvider(),
model: openai("gpt-4o-mini"),
hooks: {
onPrepareMessages: async ({ messages }) => {
const timestamp = new Date().toLocaleTimeString();
// Transform all user messages
const enhanced = messages.map((msg) => messageHelpers.addTimestampToMessage(msg, timestamp));
return { messages: enhanced };
},
},
});
API Reference
Type Guards
function isTextContent(content: MessageContent): content is string;
function isStructuredContent(content: MessageContent): content is Array<any>;
function hasTextPart(content: MessageContent): boolean;
function hasImagePart(content: MessageContent): boolean;
function hasFilePart(content: MessageContent): boolean;
Extractors
function extractText(content: MessageContent): string;
function extractTextParts(content: MessageContent): Array<{ type: "text"; text: string }>;
function extractImageParts(content: MessageContent): Array<any>;
function extractFileParts(content: MessageContent): Array<any>;
Transformers
function transformTextContent(
content: MessageContent,
transformer: (text: string) => string
): MessageContent;
function mapMessageContent<T extends BaseMessage>(
message: T,
transformer: (text: string) => string
): T;
function filterContentParts(
content: MessageContent,
predicate: (part: any) => boolean
): MessageContent;
Normalizers
function normalizeToArray(content: MessageContent): Array<any>;
function normalizeContent(content: MessageContent): MessageContent;
Builder
class MessageContentBuilder {
addText(text: string): this;
addImage(image: string | Uint8Array): this;
addFile(file: string | Uint8Array, mimeType?: string): this;
addPart(part: any): this;
build(): MessageContent;
buildAsArray(): Array<any>;
clear(): this;
get length(): number;
}
Convenience Functions
function addTimestampToMessage(message: BaseMessage, timestamp?: string): BaseMessage;
function prependToMessage(message: BaseMessage, prefix: string): BaseMessage;
function appendToMessage(message: BaseMessage, suffix: string): BaseMessage;
function hasContent(message: BaseMessage): boolean;
function getContentLength(content: MessageContent): number;
Combined Export
All functions are available through the messageHelpers
object:
import { messageHelpers } from "@voltagent/core";
// Access all functions
messageHelpers.isTextContent(content);
messageHelpers.extractText(content);
messageHelpers.MessageContentBuilder;
// ... etc