Skip to main content

Messages Package - Deep Reference

Core Architecture

MessageStore System

The MessageStore system provides multi-section message management for complex conversational scenarios:

Message System Contracts

Message Role System

Content Type Enumeration

Message Type Enumeration

Identity Types

MessageId

MessageSessionId

Tool Types

ToolCallId

ToolCall

ToolCalls

ToolResult

Message Class Structure

Core Message Class

Message Construction Patterns

Message Input Resolution

Content System Architecture

Content Class Structure

ContentParts Collection

The collection is directly iterable, so foreach ($parts as $part) works and foreach ($parts->all() as $part) is no longer required.

Content Construction

A parts collection is always a LIST. That is what separates the two array arms: ['type' => 'image_url', 'image_url' => [...]] is a single part, while [['type' => 'text', ...], ['type' => 'text', ...]] is a collection of parts. Messages/MessageInput apply the same list-vs-keyed rule one level up: a keyed array is a message (recognised by its role / content / _metadata keys), and only a list of strings is treated as a sequence of text parts.

Content State Management

Content Complexity Logic

ContentPart System

ContentPart Structure

ContentPart Factory Methods

ContentPart API

ContentPart Export Filtering

Media Utilities

Image Utility Class

File Utility Class

Audio Utility Class

Metadata Utility Class

OpenAI API Content Part Compliance

Canonical output uses nested payload keys for non-text parts (e.g. image_url, file, input_audio). Flat legacy inputs like ['type' => 'image_url', 'url' => '...'] are accepted, but outputs are normalized to the nested shape.

Supported Content Part Types

Multimodal Message Examples

MessageStore System Architecture

MessageStore Structure

toStorage() calls CanStoreMessages::save(), which REPLACES the session with exactly this store - it is not a merge. Messages absent from $store are gone from the session afterwards, including any sibling branch that was not on the loaded path, so a load-mutate-save round trip through one branch discards the others. Use append() (with navigateTo() to choose the branch) for additive writes. Both InMemoryStorage and JsonlStorage implement this same contract.

Section Operator API

Parameter Operator API

Section Class Structure

Sections Collection

Messages Collection System

Messages Class Structure

MessageList Collection

Messages Construction Patterns

Messages Access API

Messages Mutation API

Messages Transformation API

Messages Serialization

Advanced Message Operations

Message State Management

Message Mutation (Immutable)

withMergedFrom() is the full fold, where addContentFrom() only moves content: content parts are appended, tool calls concatenated, and $source’s metadata keys win on conflict, while identity (id, parentId, createdAt), role and name stay with the receiver - so a merged message keeps its place in a stored parentId chain. It throws InvalidArgumentException if either message carries a tool result: a tool result is bound to a single tool call id, and folding two together would silently drop that binding. This is what toMergedPerRole() uses.

Message Serialization

Message Validation and Detection

Format Detection

Conversion and Integration Patterns

Role-Based Merging

A run of same-role messages is folded with Message::withMergedFrom(), so the merged message keeps the FIRST message of the run’s id, parentId and createdAt, and carries the tool calls and metadata of every message in the run. Runs break at a role change and at any tool-result message: a message carrying a ToolResult is never merged with a neighbour, in either direction, because that binding belongs to one tool call id.

Provider Pattern Integration

TextRepresentation Integration

Performance and Memory Considerations

Immutable Design Patterns

Lazy Evaluation Patterns

Memory-Efficient Operations