Skip to main content

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

Table of Contents