Skip to contents

Some providers (Anthropic, Gemini) reject a message array whose first non-system turn is not user, or that contains two consecutive turns of the same role. ensure_alternating_messages() repairs an assembled array so it satisfies both constraints: it merges all leading system messages into one system block, merges any run of adjacent same-role messages into one (joining their content), and guarantees the first non-system message has role "user".

Usage

ensure_alternating_messages(messages)

Arguments

messages

A list of message objects, each list(role=, content=). Any number of leading system messages is allowed; they are merged into one system block (most providers take system as a single top-level field).

Value

A list of message objects that strictly alternates roles after the merged leading system block, beginning with user.

Details

This is the normalizer that makes hand-built multi-turn arrays (for example from transcript_as_messages()) safe to send to any supported provider. It is a pure transformation: no network or file I/O.

Merging assumes scalar character content: if two adjacent same-role messages carry non-scalar content (for example multimodal/list content), they cannot be concatenated and the function errors rather than corrupt them. Supply an array that is already alternating in that case.

Examples

msgs <- list(
  list(role = "system", content = "be terse"),
  list(role = "user",   content = "Ana: hello"),
  list(role = "user",   content = "Ben: hi"),     # adjacent user -> merged
  list(role = "assistant", content = "my prior reply"),
  list(role = "user",   content = "your turn")
)
ensure_alternating_messages(msgs)