Skip to main content

agent_sdk/types/
messages.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use uuid::Uuid;
4
5/// Union type of all possible messages returned by a query.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7#[serde(tag = "type")]
8pub enum Message {
9    /// System lifecycle events (init, compact_boundary).
10    #[serde(rename = "system")]
11    System(SystemMessage),
12
13    /// Assistant response containing text and/or tool calls.
14    #[serde(rename = "assistant")]
15    Assistant(AssistantMessage),
16
17    /// User input or tool result message.
18    #[serde(rename = "user")]
19    User(UserMessage),
20
21    /// Final result message with cost, usage, and session ID.
22    #[serde(rename = "result")]
23    Result(ResultMessage),
24
25    /// Streaming partial message (when partial messages are enabled).
26    #[serde(rename = "stream_event")]
27    StreamEvent(StreamEventMessage),
28}
29
30/// System initialization or compaction boundary message.
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct SystemMessage {
33    pub subtype: SystemSubtype,
34    pub uuid: Uuid,
35    pub session_id: String,
36
37    // Init-specific fields
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub agents: Option<Vec<String>>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub claude_code_version: Option<String>,
42    #[serde(skip_serializing_if = "Option::is_none")]
43    pub cwd: Option<String>,
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub tools: Option<Vec<String>>,
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub mcp_servers: Option<Vec<McpServerStatus>>,
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub model: Option<String>,
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub permission_mode: Option<String>,
52
53    // Compact-specific fields
54    #[serde(skip_serializing_if = "Option::is_none")]
55    pub compact_metadata: Option<CompactMetadata>,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
59#[serde(rename_all = "snake_case")]
60pub enum SystemSubtype {
61    Init,
62    CompactBoundary,
63}
64
65#[derive(Debug, Clone, Serialize, Deserialize)]
66pub struct McpServerStatus {
67    pub name: String,
68    pub status: String,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct CompactMetadata {
73    pub trigger: CompactTrigger,
74    pub pre_tokens: u64,
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
78#[serde(rename_all = "snake_case")]
79pub enum CompactTrigger {
80    Manual,
81    Auto,
82}
83
84/// Content block within an assistant or user message.
85#[derive(Debug, Clone, Serialize, Deserialize)]
86#[serde(tag = "type")]
87pub enum ContentBlock {
88    /// Text content.
89    #[serde(rename = "text")]
90    Text { text: String },
91
92    /// Tool use request from the assistant.
93    #[serde(rename = "tool_use")]
94    ToolUse {
95        id: String,
96        name: String,
97        input: serde_json::Value,
98    },
99
100    /// Tool result from execution.
101    #[serde(rename = "tool_result")]
102    ToolResult {
103        tool_use_id: String,
104        content: serde_json::Value,
105        #[serde(skip_serializing_if = "Option::is_none")]
106        is_error: Option<bool>,
107    },
108
109    /// Thinking block (extended thinking).
110    #[serde(rename = "thinking")]
111    Thinking {
112        thinking: String,
113    },
114}
115
116/// Assistant response message.
117#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct AssistantMessage {
119    pub uuid: Uuid,
120    pub session_id: String,
121    pub content: Vec<ContentBlock>,
122    pub model: String,
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub stop_reason: Option<String>,
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub parent_tool_use_id: Option<String>,
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub usage: Option<Usage>,
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub error: Option<AssistantMessageError>,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
134#[serde(rename_all = "snake_case")]
135pub enum AssistantMessageError {
136    AuthenticationFailed,
137    BillingError,
138    RateLimit,
139    InvalidRequest,
140    ServerError,
141    Unknown,
142}
143
144/// User input or tool result message.
145#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct UserMessage {
147    pub uuid: Option<Uuid>,
148    pub session_id: String,
149    pub content: Vec<ContentBlock>,
150    #[serde(skip_serializing_if = "Option::is_none")]
151    pub parent_tool_use_id: Option<String>,
152    #[serde(default)]
153    pub is_synthetic: bool,
154    #[serde(skip_serializing_if = "Option::is_none")]
155    pub tool_use_result: Option<serde_json::Value>,
156}
157
158/// Final result message.
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct ResultMessage {
161    pub subtype: ResultSubtype,
162    pub uuid: Uuid,
163    pub session_id: String,
164    pub duration_ms: u64,
165    pub duration_api_ms: u64,
166    pub is_error: bool,
167    pub num_turns: u32,
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub result: Option<String>,
170    #[serde(skip_serializing_if = "Option::is_none")]
171    pub stop_reason: Option<String>,
172    pub total_cost_usd: f64,
173    #[serde(skip_serializing_if = "Option::is_none")]
174    pub usage: Option<Usage>,
175    #[serde(default)]
176    pub model_usage: HashMap<String, ModelUsage>,
177    #[serde(default)]
178    pub permission_denials: Vec<PermissionDenial>,
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub structured_output: Option<serde_json::Value>,
181    #[serde(default)]
182    pub errors: Vec<String>,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
186#[serde(rename_all = "snake_case")]
187pub enum ResultSubtype {
188    Success,
189    ErrorMaxTurns,
190    ErrorDuringExecution,
191    ErrorMaxBudgetUsd,
192    ErrorMaxStructuredOutputRetries,
193}
194
195/// Token usage information.
196#[derive(Debug, Clone, Default, Serialize, Deserialize)]
197pub struct Usage {
198    pub input_tokens: u64,
199    pub output_tokens: u64,
200    #[serde(default)]
201    pub cache_creation_input_tokens: u64,
202    #[serde(default)]
203    pub cache_read_input_tokens: u64,
204}
205
206/// Per-model usage breakdown.
207#[derive(Debug, Clone, Default, Serialize, Deserialize)]
208pub struct ModelUsage {
209    pub input_tokens: u64,
210    pub output_tokens: u64,
211    #[serde(default)]
212    pub cache_creation_input_tokens: u64,
213    #[serde(default)]
214    pub cache_read_input_tokens: u64,
215    pub cost_usd: f64,
216}
217
218/// Information about a denied tool use.
219#[derive(Debug, Clone, Serialize, Deserialize)]
220pub struct PermissionDenial {
221    pub tool_name: String,
222    pub tool_use_id: String,
223    pub tool_input: serde_json::Value,
224}
225
226/// Streaming partial message.
227#[derive(Debug, Clone, Serialize, Deserialize)]
228pub struct StreamEventMessage {
229    pub event: serde_json::Value,
230    pub parent_tool_use_id: Option<String>,
231    pub uuid: Uuid,
232    pub session_id: String,
233}