Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Overview

Build ordered conversation turns from sealed message and content types.

developer

Messages are typed conversation turns from github.com/looprig/core/content. Each turn embeds a Message value containing a role and ordered content blocks. AgenticMessages then preserves the turn order passed to an inference request.

Message family

TypeRole constantExtra state
SystemMessageRoleSystemnone
UserMessageRoleUsernone
AIMessageRoleAssistantoptional *Usage
ToolResultMessageRoleToolToolUseID, IsError
type Message struct {
	Role   Role
	Blocks []Block
}

type UserMessage struct{ Message }
type SystemMessage struct{ Message }
type AIMessage struct {
	Message
	Usage *Usage
}
type ToolResultMessage struct {
	Message
	ToolUseID string
	IsError   bool
}

Use pointers to the concrete types in a Conversation slice. The interface is sealed, so a type switch is exhaustive over these four variants.

Build a thread

package main

import "github.com/looprig/core/content"

func main() {
	thread := content.AgenticMessages{
		&content.SystemMessage{Message: content.Message{Role: content.RoleSystem, Blocks: []content.Block{
			&content.TextBlock{Text: "Be concise."},
		}}},
		&content.UserMessage{Message: content.Message{Role: content.RoleUser, Blocks: []content.Block{
			&content.TextBlock{Text: "Summarize the report."},
		}}},
	}
	_ = thread
}

The zero value of AgenticMessages is a valid empty thread. A nil Blocks slice means no blocks; an explicitly empty slice remains distinguishable in memory even though the message JSON codec omits empty blocks.

Proof

Related: Conversation, AgenticMessages, Request messages.

← back to documentation