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 { thinking: String },
112}
113
114/// Assistant response message.
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct AssistantMessage {
117    pub uuid: Uuid,
118    pub session_id: String,
119    pub content: Vec<ContentBlock>,
120    pub model: String,
121    #[serde(skip_serializing_if = "Option::is_none")]
122    pub stop_reason: Option<String>,
123    #[serde(skip_serializing_if = "Option::is_none")]
124    pub parent_tool_use_id: Option<String>,
125    #[serde(skip_serializing_if = "Option::is_none")]
126    pub usage: Option<Usage>,
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub error: Option<AssistantMessageError>,
129}
130
131#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
132#[serde(rename_all = "snake_case")]
133pub enum AssistantMessageError {
134    AuthenticationFailed,
135    BillingError,
136    RateLimit,
137    InvalidRequest,
138    ServerError,
139    Unknown,
140}
141
142/// User input or tool result message.
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub struct UserMessage {
145    pub uuid: Option<Uuid>,
146    pub session_id: String,
147    pub content: Vec<ContentBlock>,
148    #[serde(skip_serializing_if = "Option::is_none")]
149    pub parent_tool_use_id: Option<String>,
150    #[serde(default)]
151    pub is_synthetic: bool,
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub tool_use_result: Option<serde_json::Value>,
154}
155
156/// Final result message.
157#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct ResultMessage {
159    pub subtype: ResultSubtype,
160    pub uuid: Uuid,
161    pub session_id: String,
162    pub duration_ms: u64,
163    pub duration_api_ms: u64,
164    pub is_error: bool,
165    pub num_turns: u32,
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub result: Option<String>,
168    #[serde(skip_serializing_if = "Option::is_none")]
169    pub stop_reason: Option<String>,
170    pub total_cost_usd: f64,
171    #[serde(skip_serializing_if = "Option::is_none")]
172    pub usage: Option<Usage>,
173    #[serde(default)]
174    pub model_usage: HashMap<String, ModelUsage>,
175    #[serde(default)]
176    pub permission_denials: Vec<PermissionDenial>,
177    #[serde(skip_serializing_if = "Option::is_none")]
178    pub structured_output: Option<serde_json::Value>,
179    #[serde(default)]
180    pub errors: Vec<String>,
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
184#[serde(rename_all = "snake_case")]
185pub enum ResultSubtype {
186    Success,
187    ErrorMaxTurns,
188    ErrorDuringExecution,
189    ErrorMaxBudgetUsd,
190    ErrorMaxStructuredOutputRetries,
191}
192
193/// Token usage information.
194#[derive(Debug, Clone, Default, Serialize, Deserialize)]
195pub struct Usage {
196    pub input_tokens: u64,
197    pub output_tokens: u64,
198    #[serde(default)]
199    pub cache_creation_input_tokens: u64,
200    #[serde(default)]
201    pub cache_read_input_tokens: u64,
202}
203
204/// Per-model usage breakdown.
205#[derive(Debug, Clone, Default, Serialize, Deserialize)]
206pub struct ModelUsage {
207    pub input_tokens: u64,
208    pub output_tokens: u64,
209    #[serde(default)]
210    pub cache_creation_input_tokens: u64,
211    #[serde(default)]
212    pub cache_read_input_tokens: u64,
213    pub cost_usd: f64,
214}
215
216/// Information about a denied tool use.
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct PermissionDenial {
219    pub tool_name: String,
220    pub tool_use_id: String,
221    pub tool_input: serde_json::Value,
222}
223
224/// Streaming partial message.
225#[derive(Debug, Clone, Serialize, Deserialize)]
226pub struct StreamEventMessage {
227    pub event: serde_json::Value,
228    pub parent_tool_use_id: Option<String>,
229    pub uuid: Uuid,
230    pub session_id: String,
231}