pub struct Message {
pub id: MessageId,
pub role: MessageRole,
pub content: Vec<ContentPart>,
pub phase: Option<ExecutionPhase>,
pub phase_source: Option<PhaseSource>,
pub controls: Option<Controls>,
pub metadata: Option<HashMap<String, Value>>,
pub external_actor: Option<ExternalActor>,
pub created_at: DateTime<Utc>,
}Expand description
A message in the conversation
Fields§
§id: MessageIdUnique message ID (format: message_{32-hex})
role: MessageRoleMessage role
content: Vec<ContentPart>Message content as array of content parts (text, images, tool calls, tool results)
phase: Option<ExecutionPhase>Execution phase for this message.
Helps LLMs distinguish between intermediate working commentary and completed answers in multi-step tool-calling flows. Only set on agent (assistant) messages. Providers with native phase support (OpenAI GPT-5.x) send this value in the API request; others derive it from state but don’t send it to the provider.
phase_source: Option<PhaseSource>Whether Self::phase was reported by the provider or inferred from
tool-call presence. A derived phase carries no information beyond
“this message called tools”, so consumers that need a real
classification must be able to tell the two apart.
controls: Option<Controls>Runtime controls (model, reasoning, etc.)
metadata: Option<HashMap<String, Value>>Message-level metadata
external_actor: Option<ExternalActor>External actor identity (for messages from external channels like Slack)
created_at: DateTime<Utc>Timestamp when the message was created
Implementations§
Source§impl Message
impl Message
Sourcepub fn reasoning_parts(&self) -> impl Iterator<Item = &ReasoningContentPart>
pub fn reasoning_parts(&self) -> impl Iterator<Item = &ReasoningContentPart>
Reasoning artifacts carried by this message, in emission order.
Sourcepub fn has_reasoning(&self) -> bool
pub fn has_reasoning(&self) -> bool
Whether this message carries any provider reasoning artifact.
Sourcepub fn reasoning_display_text(&self) -> Option<String>
pub fn reasoning_display_text(&self) -> Option<String>
Readable reasoning across every artifact, joined for display.
Display only. Replay must walk Message::reasoning_parts so each
artifact keeps its own signature and position.
Sourcepub fn into_public(self) -> Self
pub fn into_public(self) -> Self
Replace every reasoning part with its publishable projection, dropping opaque provider replay state. Used at API boundaries.
Sourcepub fn with_id(self, id: MessageId) -> Self
pub fn with_id(self, id: MessageId) -> Self
Override the generated message id.
Streaming producers use this to allocate a public id before emitting
output.message.started, then reuse it on the completed message.
Sourcepub fn assistant_with_tools(
content: impl Into<String>,
tool_calls: Vec<ToolCall>,
) -> Self
pub fn assistant_with_tools( content: impl Into<String>, tool_calls: Vec<ToolCall>, ) -> Self
Create a new assistant message with tool calls
Tool calls are stored as ContentPart::ToolCall in the content array alongside the text content. Empty text content is omitted to avoid LLM API errors (e.g., Anthropic requires non-empty text blocks).
Sourcepub fn tool_result(
tool_call_id: impl Into<String>,
result: Option<Value>,
error: Option<String>,
) -> Self
pub fn tool_result( tool_call_id: impl Into<String>, result: Option<Value>, error: Option<String>, ) -> Self
Create a tool result message
Sourcepub fn tool_result_with_images(
tool_call_id: impl Into<String>,
result: Option<Value>,
images: Vec<ToolResultImage>,
) -> Self
pub fn tool_result_with_images( tool_call_id: impl Into<String>, result: Option<Value>, images: Vec<ToolResultImage>, ) -> Self
Create a tool result message with images.
Images are included as ContentPart::Image alongside the ToolResult part.
When converted to LlmMessage, images become native image content blocks
that the LLM can see visually (not just stringified base64).
Sourcepub fn with_phase(self, phase: ExecutionPhase) -> Self
pub fn with_phase(self, phase: ExecutionPhase) -> Self
Set the execution phase on this message and return self.
Sourcepub fn with_phase_from(self, phase: ExecutionPhase, source: PhaseSource) -> Self
pub fn with_phase_from(self, phase: ExecutionPhase, source: PhaseSource) -> Self
Set the phase together with where it came from.
Sourcepub fn tool_call_id(&self) -> Option<&str>
pub fn tool_call_id(&self) -> Option<&str>
Get the tool_call_id from a tool result message
Returns the tool_call_id from the first ToolResult content part, if any.
Sourcepub fn tool_calls(&self) -> Vec<&ToolCallContentPart>
pub fn tool_calls(&self) -> Vec<&ToolCallContentPart>
Get all tool calls from the message content
Sourcepub fn has_tool_calls(&self) -> bool
pub fn has_tool_calls(&self) -> bool
Check if this message has tool calls
Sourcepub fn tool_result_content(&self) -> Option<&ToolResultContentPart>
pub fn tool_result_content(&self) -> Option<&ToolResultContentPart>
Get the first tool result from the message content
Sourcepub fn content_to_llm_string(&self) -> String
pub fn content_to_llm_string(&self) -> String
Convert content to LLM-compatible string representation
Sourcepub fn to_openai_format(&self) -> Value
pub fn to_openai_format(&self) -> Value
Convert message to OpenAI-compatible format
Transforms internal message format to OpenAI API format:
agentrole →assistanttool_resultrole →tool(with tool_call_id at message level)- Tool calls formatted as
{id, type: "function", function: {name, arguments}}
Used by observability backends (e.g., Braintrust) that expect OpenAI format.