Skip to content

Concepts · ai

Messages

Message struct, roles, provenance, reading text, stop reasons, and the Prompt type

Read this when
  • Building or manipulating conversation history
  • Working with message roles or content blocks
  • Deciding what a reader may see and what only the model reads

This page gives the conversation message model used by the SDK. A Message carries content blocks, role metadata, and role-specific fields. Messages are the primary data structure that flows through the SDK.

Roles

The three roles are user, assistant, and tool_result. Role-specific fields use zero values when they do not apply. Assistant messages carry provider metadata and token usage. Tool result messages carry the call ID and tool name that they answer.

Design: flat struct with role-specific fields

The SDK uses one Message struct instead of separate role types. This keeps slices homogeneous as []Message. It simplifies serialization and matches the wire format of most provider APIs. The tradeoff is that some fields have no meaning for some roles. Go’s zero values handle that cleanly.

Provenance: where a message came from

Injected says who put a message in the history. The zero value, InjectionNone, means the caller or the model, so an ordinary message needs no thought. InjectionMeta and InjectionEphemeral both mean an injector added it. Origin names that injector, and the SDK never interprets it.

Three consumers read the one field and each applies its own rule:

ConsumerInjectionNoneInjectionMetaInjectionEphemeral
The modelreadsreadsreads
A readershowshideshides
A storekeepskeepsskips

So the two injected flavors differ in one thing: durability. Meta survives a restart, and ephemeral does not. Use ephemeral for what is true only right now, such as a reminder built from live state.

Design: the flag is on the message, not on the entry that wraps it. A message reaches a UI as a stream event long before anything persists it. With the flag one layer up, on the session entry, a UI had no structured signal at all and had to guess from the text. See Entries.

Injected context can also ride inside an ordinary message, as an ai.Reminder block. Use that when part of the message is for the reader and part is not.

Reading the text of a message

Text() returns the blocks that carry text — the Text blocks and the Reminder blocks — as []ai.Content, in document order. JoinText(sep) joins those same blocks into one string.

Pick by what you are feeding:

  • A provider, or any format that takes one stringJoinText. The model reads injected context, so the joined result is correct.
  • A reader: a UI, a transcript, a rendered message — neither. Walk Content and keep the ai.Text blocks. Both accessors return what the model reads.

Design: Text returns blocks so the caller keeps the choice. A string throws away which kind each block is, and that kind is exactly the decision above. The rule differs per caller, so it is not the SDK’s to make. See Messages (agent) for the full argument.

Constructors

Helper functions such as UserMessage, AssistantMessage, and ToolResultMessage set the correct role and timestamp. Prefer these helpers over direct Message literals.

Stop reasons

StopReason says why generation stopped. Values include natural completion, stop, token limit, length, tool use, tool_use, error, and context cancellation, aborted. The agent loop uses tool_use to decide whether to continue with another turn.

Prompt

Prompt bundles the inputs for a model call. It contains system prompt text, conversation history, and available tool definitions. It maps 1:1 to a provider API call. The agent builds it internally. Direct callers of StreamText and GenerateText construct it themselves.

JSON serialization

Custom MarshalJSON and UnmarshalJSON produce a clean wire format. Content blocks carry a type discriminator. Zero-valued fields are omitted, so an ordinary message writes no injected or origin key. Timestamps use RFC3339Nano. Server-tool calls round-trip the Server, ServerType, and Output fields on ToolCall. The Output field includes Content, Raw, and IsError. Persisted history replays with the same shape that providers produced.

  • Content — content block types, including Reminder
  • Messages (agent) — how a hook adds a message, and why Text returns blocks
  • Usage — token usage carried on assistant messages
  • Tools — tool calling and results