Messages
Messages build the conversation context for agent interactions. Each message has a role (user, assistant, system, or tool) and content (text, images, or documents). ActiveAgent supports both native provider formats and a unified common format that works across all providers.
Message Roles
Understanding roles helps you structure conversations correctly:
- User - Input from the user to the agent (text, images, documents)
- Assistant - Responses from the agent, including tool call requests
- System - Instructions that guide agent behavior (set via
instructionsoption) - Tool - Results from tool executions (handled automatically)
Most of the time you'll send user messages and inspect assistant/tool responses.
Sending Messages
Single Message
The simplest way to send a message:
class SingleMessageAgent < ApplicationAgent
generate_with :openai, model: "gpt-4o-mini"
def chat
prompt("What is the capital of France?")
end
end2
3
4
5
6
7
Use the message: keyword for clarity:
class MessageKeywordAgent < ApplicationAgent
generate_with :anthropic, model: "claude-3-5-haiku-20241022"
def chat
prompt(message: "Explain quantum computing")
end
end2
3
4
5
6
7
Multiple Messages
Send multiple strings as separate user messages in a single prompt:
class MultipleMessagesAgent < ApplicationAgent
generate_with :open_router, model: "openai/gpt-4o-mini"
def chat_inline
prompt(
"Tell me a fun fact about Ruby.",
"Now explain why that's interesting."
)
end
def chat_array
prompt(messages: [
"Tell me a fun fact about Ruby.",
"Now explain why that's interesting."
])
end
end2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MultipleMessagesAgent < ApplicationAgent
generate_with :open_router, model: "openai/gpt-4o-mini"
def chat_inline
prompt(
"Tell me a fun fact about Ruby.",
"Now explain why that's interesting."
)
end
def chat_array
prompt(messages: [
"Tell me a fun fact about Ruby.",
"Now explain why that's interesting."
])
end
end2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Messages with Roles
Set explicit roles using hashes. The default role is :user:
class MessagesWithRolesAgent < ApplicationAgent
generate_with :openai, model: "gpt-4o-mini"
def chat_multiple
prompt(messages: [
{ role: "assistant", text: "I can help with programming questions." },
{ text: "What are the benefits of ActiveRecord?" }
])
end
def chat_single
prompt(message: { role: "assistant", text: "Previous response..." })
end
end2
3
4
5
6
7
8
9
10
11
12
13
14
Note: Use the instructions option for system messages. System role messages are dropped in common format and replaced by instructions. Learn about instructions →
Images and Documents
ActiveAgent provides a unified interface for multimodal inputs. Pass HTTP URLs or Base64 data URIs - the framework converts them to the provider's native format.
ActiveStorage Support: Direct attachment support for ActiveStorage files is coming soon.
Images
class ImageAgent < ApplicationAgent
generate_with :anthropic, model: "claude-3-5-haiku-20241022"
def analyze_url
prompt(
"What's in this image?",
image: "https://framerusercontent.com/images/oEx786EYW2ZVL4Xf9hparOVLjHI.png?scale-down-to=64"
)
end
def analyze_base64
prompt(
"Describe this image",
image: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
)
end
def analyze_message_hash
prompt(message: {
text: "Analyze this",
image: "https://framerusercontent.com/images/oEx786EYW2ZVL4Xf9hparOVLjHI.png?scale-down-to=64"
})
end
def analyze_messages_array
prompt(messages: [
{ text: "What's in this image?" },
{ image: "https://framerusercontent.com/images/oEx786EYW2ZVL4Xf9hparOVLjHI.png?scale-down-to=64" }
])
end
end2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Documents
Same interface for PDFs and other documents:
class DocumentAgent < ApplicationAgent
generate_with :openai, model: "gpt-4o-mini"
def summarize_url
prompt(
"Summarize this document",
document: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
)
end
end2
3
4
5
6
7
8
9
10
Supported formats:
- Images: JPEG, PNG, GIF, WebP
- Documents: PDF (provider-dependent)
Inspecting Responses
After generation, access messages from the response:
response = InspectMessagesAgent.with(message: "Hello").chat.generate_now
response.message
response.messages2
3
4
Grouping by Role
Filter messages to find specific types:
system_messages = response.messages.select { |m| m.role == :system }
user_messages = response.messages.select { |m| m.role == :user }
assistant_messages = response.messages.select { |m| m.role == :assistant }
tool_messages = response.messages.select { |m| m.role == :tool }2
3
4
System Messages
System messages come from the instructions option:
class SystemMessagesAgent < ApplicationAgent
generate_with :anthropic, model: "claude-3-5-haiku-20241022"
def chat
prompt(
instructions: "You are a travel booking assistant.",
message: "Help me book a hotel"
)
end
end2
3
4
5
6
7
8
9
10
system_message = response.messages.find { |m| m.role == :system }Assistant Messages
Assistant messages contain the agent's responses. Provide conversation history by including previous assistant messages:
class AssistantHistoryAgent < ApplicationAgent
generate_with :open_router, model: "openai/gpt-4o-mini"
def continue_conversation
prompt(messages: [
{ role: "assistant", text: "I can help you with that." },
{ text: "Great! I need help with X" }
])
end
end2
3
4
5
6
7
8
9
10
Tool Messages
Tool messages contain results from tool executions. ActiveAgent handles tool calls and their results automatically. Learn about tools →
# Tool messages contain execution results
tool_messages.first.content
# => "https://cataas.com/cat/5e9..."Common vs Native Format
ActiveAgent provides two ways to work with messages:
Common Format (Recommended)
Use the unified prompt() interface. ActiveAgent normalizes messages across providers:
class CommonFormatAgent < ApplicationAgent
generate_with :openai, model: "gpt-4o-mini"
def multimodal
prompt("Hello", image: "https://framerusercontent.com/images/oEx786EYW2ZVL4Xf9hparOVLjHI.png?scale-down-to=64")
end
end2
3
4
5
6
7
Benefits:
- Switch providers without changing code
- Consistent API across all providers
- Automatic format conversion
Native Format
For provider-specific features, use native message structures:
class NativeFormatAgent < ApplicationAgent
generate_with :openai, model: "gpt-4o-mini"
def multimodal_native
# Use common format - the native format is provider-specific
prompt("What's in this image?", image: "https://framerusercontent.com/images/oEx786EYW2ZVL4Xf9hparOVLjHI.png?scale-down-to=64")
end
end2
3
4
5
6
7
8
Both formats work with all providers, but common format is simpler and more portable.
Related Documentation
- Agents → - Understanding the agent lifecycle
- Actions → - Overview of agent capabilities
- Tools → - Defining and using agent tools
- Instructions → - Setting system messages and guiding agent behavior
- Generation → - How messages flow through the generation process
- Structured Output → - Formatting agent responses
- Callbacks → - Hook into message processing
- Streaming → - Real-time message updates
- Testing → - Test message handling patterns