Messages
Build and store conversation history as a parts-based message model that mirrors the AI SDK without depending on it.
The message model
AgentMessage is a parts-based, discriminated union representing one conversation turn. It structurally mirrors the Vercel AI SDK's ModelMessage, but core has no dependency on ai. You build messages, store them in machine context, and pass them to a text request or decision through the messages field.
type AgentMessage = SystemMessage | UserMessage | AssistantMessage | ToolMessage;content is a string or an array of typed parts, depending on role:
system: a string.user: a string, orTextPart/ImagePart/FilePartparts.assistant: a string, orTextPart/FilePart/ToolCallPart/ToolResultPartparts.tool: an array ofToolResultPart.
Build messages
Build each role with its helper:
import { assistantMessage, systemMessage, userMessage } from '@statelyai/agent';
const messages = [
systemMessage('You draft concise emails.'),
userMessage('Draft a launch email.'),
assistantMessage('Here is a first draft: ...'),
];userMessage and assistantMessage also accept a parts array for multimodal content:
userMessage([
{ type: 'text', text: 'What is in this image?' },
{ type: 'image', image: 'https://example.com/photo.png' },
]);Store messages in context
Messages are plain context state. Declare a messages field validated by messagesSchema, and grow it over transitions:
import { messagesSchema, setupAgent } from '@statelyai/agent';
const agentSetup = setupAgent({
context: z.object({
prompt: z.string(),
messages: messagesSchema,
}),
});Append with appendMessages, which returns a transition result adding one or more messages. Pass a message, an array, or a function of { context, event }:
import { appendMessages, userMessage } from '@statelyai/agent';
on: {
USER_REPLIED: appendMessages(({ event }) => userMessage(event.text)),
}A request that needs history sends it through messages instead of a bare prompt. examples/email-drafter/index.ts keeps a running messages array in context and feeds it to a createTextLogic request.
Persisting messages
Warning:
ImagePartandFilePartcan carry binary data (Uint8ArrayorArrayBuffer) or aURLinstance, none of which are JSON-serializable. If you persist machine context containing messages, store binary content as base64 strings and URLs as strings. The library does not convert this for you.
Everything else in a message is plain JSON, so a history built from strings, base64, and URL strings survives a snapshot round-trip cleanly. See Human in the loop for the persistence flow this applies to.