class RubyLLM::Message
A Message is a single entry in a chat conversation: a user prompt, an assistant reply, a system instruction, or a tool result. Chat#ask returns the model’s reply as a Message, and Chat#messages holds the transcript as an array of them.
response = chat.ask "What is the capital of France?" response.role # => :assistant response.content # => "The capital of France is Paris." response.finish_reason # => "stop"
A Message also carries everything else the provider returned: token usage (tokens), reasoning output (thinking), source citations (citations), and requested tool calls (tool_calls).
Constants
- ROLES
-
The valid message roles:
:system,:user,:assistant, and:tool.
Attributes
The files sent or returned with the message, as an array of Attachment objects.
The source citations as an array of Citation objects, normalized across providers.
The message text as a String. Empty for assistant messages that only request tool calls.
The provider-reported reason the model stopped, preserved as-is, such as "stop", "max_tokens", or "MAX_TOKENS".
The ID of the model that produced the message, nil on user messages.
The raw provider response: a Faraday::Response, or the result body Hash for messages retrieved from a Batch.
The role of the message: :system, :user, :assistant, or :tool.
The model’s reasoning output as a Thinking object, or nil when the provider returned none.
The token usage as a Tokens object, or nil when the provider reported none.
The ID of the tool call this message answers. Set only on tool result messages.
The tool calls the assistant requested, as a Hash of ToolCall objects keyed by call ID, or nil.
Public Instance Methods
Source
# File lib/ruby_llm/message.rb, line 175 def cache_read_tokens tokens&.cache_read end
Returns the prompt cache read token count, same as tokens.cache_read.
Source
# File lib/ruby_llm/message.rb, line 205 def cache_until_here! @cache_until_here = true self end
Marks this message as an explicit prompt cache boundary. Providers that support prompt caching cache the conversation up to and including this message. Returns self.
chat.add_message(role: :user, content: long_context).cache_until_here!
Source
# File lib/ruby_llm/message.rb, line 212 def cache_until_here? @cache_until_here end
Returns true if the message carries an explicit prompt cache boundary, false otherwise.
Source
# File lib/ruby_llm/message.rb, line 181 def cache_write_tokens tokens&.cache_write end
Returns the prompt cache write token count, same as tokens.cache_write.
Source
# File lib/ruby_llm/message.rb, line 158 def content_filtered? finish_reason_in?(CONTENT_FILTERED_FINISH_REASONS) end
Returns true if a provider safety filter stopped the response, false otherwise.
Source
# File lib/ruby_llm/message.rb, line 195 def cost(model: nil) Cost.new(tokens:, model: model || model_info) end
Returns a Cost pricing this message’s token usage in US dollars. Pricing comes from model_info, or from model: when given.
response.cost.total
Source
# File lib/ruby_llm/message.rb, line 163 def input_tokens tokens&.input end
Returns the standard input token count, same as tokens.input.
Source
# File lib/ruby_llm/message.rb, line 146 def max_tokens? finish_reason_in?(MAX_TOKENS_FINISH_REASONS) end
Returns true if the response was cut off by a token limit, false otherwise.
Source
# File lib/ruby_llm/message.rb, line 241 def model_info return unless model @model_info ||= RubyLLM.models.find(model) rescue ModelNotFoundError nil end
Source
# File lib/ruby_llm/message.rb, line 169 def output_tokens tokens&.output end
Returns the billable output token count, same as tokens.output.
Source
# File lib/ruby_llm/message.rb, line 107 def parsed @parsed ||= JSON.parse(content) if content end
Returns content parsed as JSON, memoized after the first call. Useful for reading structured output responses.
response = chat.with_schema(PersonSchema).ask "Generate a person" response.parsed # => {"name" => "Alice", "age" => 30}
Source
# File lib/ruby_llm/message.rb, line 140 def stopped? finish_reason_in?(STOPPED_FINISH_REASONS) end
Returns true if finish_reason indicates the model finished normally, false otherwise.
Source
# File lib/ruby_llm/message.rb, line 186 def thinking_tokens tokens&.thinking end
Returns the reasoning token count, same as tokens.thinking.
Source
# File lib/ruby_llm/message.rb, line 219 def to_h { role: role, content: content, attachments: list_to_h(attachments), model: model, tool_calls: tool_calls, tool_call_id: tool_call_id, thinking: thinking&.text, thinking_signature: thinking&.signature, citations: list_to_h(citations), finish_reason: finish_reason, cache_until_here: cache_until_here? || nil }.merge(tokens ? tokens.to_h : {}).compact end
Returns a Hash of the message’s attributes, with token counts merged in as :input_tokens, :output_tokens, and related keys. Omits nil values and empty attachment and citation lists.
Source
# File lib/ruby_llm/message.rb, line 117 def tool_call? !tool_calls.nil? && !tool_calls.empty? end
Returns true if the assistant requested one or more tool calls, false otherwise.
Source
# File lib/ruby_llm/message.rb, line 152 def tool_call_stop? finish_reason_in?(TOOL_CALL_FINISH_REASONS) end
Returns true if the model stopped to request tool calls, false otherwise.
Source
# File lib/ruby_llm/message.rb, line 123 def tool_result? !tool_call_id.nil? && !tool_call_id.empty? end
Returns true if the message carries the result of a tool call, false otherwise.
Source
# File lib/ruby_llm/message.rb, line 130 def tool_results return [] unless tool_call? && conversation conversation.messages.select do |message| message.tool_result? && tool_calls.key?(message.tool_call_id) end end
Returns the tool result messages answering this message’s tool calls, or an empty array when it made none. Mirrors the tool_results association on acts_as_message records.