0
# Message Types and Content
1
2
Rich message system with structured content blocks supporting text, tool usage, tool results, thinking blocks, and streaming events. Includes complete type definitions for all message and content types used in Claude Code SDK communications.
3
4
## Capabilities
5
6
### Message Union Type
7
8
All possible message types that can be received from Claude Code.
9
10
```python { .api }
11
Message = UserMessage | AssistantMessage | SystemMessage | ResultMessage | StreamEvent
12
```
13
14
### User Messages
15
16
Messages representing user input and prompts.
17
18
```python { .api }
19
@dataclass
20
class UserMessage:
21
"""User message."""
22
23
content: str | list[ContentBlock]
24
parent_tool_use_id: str | None = None
25
```
26
27
**Fields:**
28
- `content`: User input as string or structured content blocks
29
- `parent_tool_use_id`: Optional reference to parent tool use operation
30
31
### Assistant Messages
32
33
Messages from Claude containing responses with rich content blocks.
34
35
```python { .api }
36
@dataclass
37
class AssistantMessage:
38
"""Assistant message with content blocks."""
39
40
content: list[ContentBlock]
41
model: str
42
parent_tool_use_id: str | None = None
43
```
44
45
**Fields:**
46
- `content`: List of content blocks (text, tool use, etc.)
47
- `model`: Claude model identifier used for the response
48
- `parent_tool_use_id`: Optional reference to parent tool use operation
49
50
### System Messages
51
52
Internal system messages with metadata and notifications.
53
54
```python { .api }
55
@dataclass
56
class SystemMessage:
57
"""System message with metadata."""
58
59
subtype: str
60
data: dict[str, Any]
61
```
62
63
**Fields:**
64
- `subtype`: Type of system message (status, notification, etc.)
65
- `data`: Structured data payload for the system message
66
67
### Result Messages
68
69
Final result messages containing cost, usage, and completion information.
70
71
```python { .api }
72
@dataclass
73
class ResultMessage:
74
"""Result message with cost and usage information."""
75
76
subtype: str
77
duration_ms: int
78
duration_api_ms: int
79
is_error: bool
80
num_turns: int
81
session_id: str
82
total_cost_usd: float | None = None
83
usage: dict[str, Any] | None = None
84
result: str | None = None
85
```
86
87
**Fields:**
88
- `subtype`: Result type identifier
89
- `duration_ms`: Total duration in milliseconds
90
- `duration_api_ms`: API call duration in milliseconds
91
- `is_error`: Whether the interaction resulted in an error
92
- `num_turns`: Number of conversation turns
93
- `session_id`: Session identifier
94
- `total_cost_usd`: Total cost in USD (if available)
95
- `usage`: Token usage and other metrics
96
- `result`: Final result summary
97
98
### Stream Events
99
100
Streaming updates during partial message processing.
101
102
```python { .api }
103
@dataclass
104
class StreamEvent:
105
"""Stream event for partial message updates during streaming."""
106
107
uuid: str
108
session_id: str
109
event: dict[str, Any] # The raw Anthropic API stream event
110
parent_tool_use_id: str | None = None
111
```
112
113
**Fields:**
114
- `uuid`: Unique identifier for the stream event
115
- `session_id`: Session identifier
116
- `event`: Raw Anthropic API stream event data
117
- `parent_tool_use_id`: Optional reference to parent tool use operation
118
119
## Content Block Types
120
121
### Content Block Union
122
123
All possible content block types within messages.
124
125
```python { .api }
126
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock
127
```
128
129
### Text Blocks
130
131
Plain text content blocks containing textual responses.
132
133
```python { .api }
134
@dataclass
135
class TextBlock:
136
"""Text content block."""
137
138
text: str
139
```
140
141
**Fields:**
142
- `text`: The text content
143
144
### Thinking Blocks
145
146
Claude's internal reasoning and thought process.
147
148
```python { .api }
149
@dataclass
150
class ThinkingBlock:
151
"""Thinking content block."""
152
153
thinking: str
154
signature: str
155
```
156
157
**Fields:**
158
- `thinking`: Claude's internal reasoning text
159
- `signature`: Cryptographic signature for thinking content
160
161
### Tool Use Blocks
162
163
Blocks representing Claude's intention to use a tool.
164
165
```python { .api }
166
@dataclass
167
class ToolUseBlock:
168
"""Tool use content block."""
169
170
id: str
171
name: str
172
input: dict[str, Any]
173
```
174
175
**Fields:**
176
- `id`: Unique identifier for the tool use
177
- `name`: Name of the tool to be used
178
- `input`: Input parameters for the tool
179
180
### Tool Result Blocks
181
182
Blocks containing the results of tool execution.
183
184
```python { .api }
185
@dataclass
186
class ToolResultBlock:
187
"""Tool result content block."""
188
189
tool_use_id: str
190
content: str | list[dict[str, Any]] | None = None
191
is_error: bool | None = None
192
```
193
194
**Fields:**
195
- `tool_use_id`: Reference to the tool use that generated this result
196
- `content`: Tool execution result content
197
- `is_error`: Whether the tool execution resulted in an error
198
199
## Usage Examples
200
201
### Processing Assistant Messages
202
203
```python
204
from claude_code_sdk import query, AssistantMessage, TextBlock, ToolUseBlock, ToolResultBlock
205
206
async def main():
207
async for message in query(prompt="Create a Python file and run it"):
208
if isinstance(message, AssistantMessage):
209
print(f"Response from {message.model}:")
210
211
for block in message.content:
212
if isinstance(block, TextBlock):
213
print(f"Text: {block.text}")
214
215
elif isinstance(block, ToolUseBlock):
216
print(f"Tool use: {block.name} (ID: {block.id})")
217
print(f"Input: {block.input}")
218
219
elif isinstance(block, ToolResultBlock):
220
print(f"Tool result for {block.tool_use_id}:")
221
if block.is_error:
222
print(f"Error: {block.content}")
223
else:
224
print(f"Result: {block.content}")
225
226
elif isinstance(block, ThinkingBlock):
227
print(f"Claude's thinking: {block.thinking[:100]}...")
228
```
229
230
### Handling Different Message Types
231
232
```python
233
from claude_code_sdk import (
234
query, UserMessage, AssistantMessage, SystemMessage,
235
ResultMessage, StreamEvent
236
)
237
238
async def main():
239
async for message in query(prompt="What is the capital of France?"):
240
if isinstance(message, UserMessage):
241
print(f"User: {message.content}")
242
243
elif isinstance(message, AssistantMessage):
244
print(f"Assistant ({message.model}): Processing {len(message.content)} content blocks")
245
246
elif isinstance(message, SystemMessage):
247
print(f"System ({message.subtype}): {message.data}")
248
249
elif isinstance(message, ResultMessage):
250
print(f"Result: {message.num_turns} turns, {message.duration_ms}ms")
251
if message.total_cost_usd:
252
print(f"Cost: ${message.total_cost_usd:.4f}")
253
254
elif isinstance(message, StreamEvent):
255
print(f"Stream event: {message.uuid}")
256
```
257
258
### Collecting Complete Responses
259
260
```python
261
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, ResultMessage, TextBlock
262
263
async def main():
264
async with ClaudeSDKClient() as client:
265
await client.query("Explain quantum computing")
266
267
complete_response = []
268
async for msg in client.receive_response():
269
complete_response.append(msg)
270
271
if isinstance(msg, ResultMessage):
272
# Response is complete
273
break
274
275
# Process collected messages
276
for msg in complete_response:
277
if isinstance(msg, AssistantMessage):
278
for block in msg.content:
279
if isinstance(block, TextBlock):
280
print(block.text)
281
```
282
283
### Working with Tool Interactions
284
285
```python
286
from claude_code_sdk import (
287
query, ClaudeCodeOptions, AssistantMessage,
288
ToolUseBlock, ToolResultBlock
289
)
290
291
async def main():
292
options = ClaudeCodeOptions(
293
allowed_tools=["Read", "Write", "Bash"],
294
permission_mode="acceptEdits"
295
)
296
297
tool_uses = []
298
tool_results = []
299
300
async for message in query(
301
prompt="Create a hello.py file and run it",
302
options=options
303
):
304
if isinstance(message, AssistantMessage):
305
for block in message.content:
306
if isinstance(block, ToolUseBlock):
307
tool_uses.append(block)
308
print(f"Claude wants to use {block.name}:")
309
print(f" ID: {block.id}")
310
print(f" Input: {block.input}")
311
312
elif isinstance(block, ToolResultBlock):
313
tool_results.append(block)
314
print(f"Tool result for {block.tool_use_id}:")
315
if block.is_error:
316
print(f" Error: {block.content}")
317
else:
318
print(f" Success: {block.content}")
319
320
print(f"Total tool uses: {len(tool_uses)}")
321
print(f"Total tool results: {len(tool_results)}")
322
```
323
324
### Stream Event Processing
325
326
```python
327
from claude_code_sdk import ClaudeCodeOptions, query, StreamEvent
328
329
async def main():
330
options = ClaudeCodeOptions(
331
include_partial_messages=True # Enable streaming events
332
)
333
334
async for message in query(
335
prompt="Write a long story about space exploration",
336
options=options
337
):
338
if isinstance(message, StreamEvent):
339
event_type = message.event.get("type", "unknown")
340
print(f"Stream event ({event_type}): {message.uuid}")
341
342
# Handle different stream event types
343
if event_type == "content_block_start":
344
print(" Starting content block")
345
elif event_type == "content_block_delta":
346
delta = message.event.get("delta", {})
347
if "text" in delta:
348
print(f" Text delta: {delta['text']}")
349
elif event_type == "content_block_stop":
350
print(" Finished content block")
351
```
352
353
### Error Handling in Messages
354
355
```python
356
from claude_code_sdk import query, ResultMessage, ToolResultBlock
357
358
async def main():
359
async for message in query(prompt="Run an invalid command"):
360
if isinstance(message, ResultMessage):
361
if message.is_error:
362
print(f"Conversation ended with error: {message.result}")
363
else:
364
print(f"Conversation completed successfully")
365
366
# Check for tool errors in content blocks
367
if hasattr(message, 'content'):
368
for block in getattr(message, 'content', []):
369
if isinstance(block, ToolResultBlock) and block.is_error:
370
print(f"Tool error in {block.tool_use_id}: {block.content}")
371
```
372
373
### Message Filtering and Analysis
374
375
```python
376
from claude_code_sdk import query, AssistantMessage, TextBlock
377
from collections import Counter
378
379
async def main():
380
message_types = Counter()
381
content_types = Counter()
382
total_text_length = 0
383
384
async for message in query(prompt="Analyze this codebase and suggest improvements"):
385
message_types[type(message).__name__] += 1
386
387
if isinstance(message, AssistantMessage):
388
for block in message.content:
389
content_types[type(block).__name__] += 1
390
391
if isinstance(block, TextBlock):
392
total_text_length += len(block.text)
393
394
print("Message type distribution:")
395
for msg_type, count in message_types.items():
396
print(f" {msg_type}: {count}")
397
398
print("Content block distribution:")
399
for content_type, count in content_types.items():
400
print(f" {content_type}: {count}")
401
402
print(f"Total text content length: {total_text_length} characters")
403
```
404
405
## Message Flow Patterns
406
407
### Typical Conversation Flow
408
409
1. `UserMessage`: Initial user prompt
410
2. `AssistantMessage`: Claude's response with content blocks
411
3. `ToolUseBlock`: Claude decides to use a tool
412
4. `ToolResultBlock`: Tool execution result
413
5. `AssistantMessage`: Claude's response to tool result
414
6. `ResultMessage`: Final result with costs and usage
415
416
### Streaming Flow with Partial Messages
417
418
When `include_partial_messages=True`:
419
420
1. `UserMessage`: User prompt
421
2. `StreamEvent`: Content block start
422
3. `StreamEvent`: Multiple text deltas
423
4. `StreamEvent`: Content block stop
424
5. `AssistantMessage`: Complete assembled message
425
6. `ResultMessage`: Final result
426
427
### Error Flow
428
429
1. `UserMessage`: User prompt
430
2. `AssistantMessage`: Partial response
431
3. `ToolUseBlock`: Tool attempt
432
4. `ToolResultBlock`: Tool error (`is_error=True`)
433
5. `AssistantMessage`: Error handling response
434
6. `ResultMessage`: Error result (`is_error=True`)
435
436
## Type Safety and Validation
437
438
All message types are dataclasses with type hints, enabling:
439
- Static type checking with mypy
440
- IDE autocomplete and validation
441
- Runtime type checking with isinstance()
442
- Structured access to message fields
443
444
For configuration options related to message handling, see [Configuration and Options](./configuration-options.md).