docs
0
# Content Blocks
1
2
Content blocks are the building blocks of messages in conversations with Claude. They represent different types of content including text, thinking, tool uses, and tool results.
3
4
## Capabilities
5
6
### ContentBlock Union Type
7
8
Union of all possible content block types.
9
10
```python { .api }
11
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock
12
"""
13
Union of all content block types.
14
15
Content blocks appear in AssistantMessage and UserMessage objects to
16
represent different types of content:
17
18
- TextBlock: Normal text output from Claude
19
- ThinkingBlock: Extended thinking content (when enabled)
20
- ToolUseBlock: Request to execute a tool
21
- ToolResultBlock: Result from tool execution
22
23
Use isinstance() to determine the specific block type and access
24
type-specific fields.
25
"""
26
```
27
28
### TextBlock
29
30
Plain text content from Claude or user.
31
32
```python { .api }
33
@dataclass
34
class TextBlock:
35
"""
36
Text content block.
37
38
Represents plain text in a message. This is the most common content
39
block type for normal conversation text.
40
41
Attributes:
42
text: The text content
43
"""
44
45
text: str
46
"""Text content.
47
48
The plain text content of this block. Can be a single word, sentence,
49
paragraph, or longer text.
50
51
Examples:
52
"Hello, how can I help you?"
53
"To solve this problem, we need to..."
54
"The result is 42."
55
"""
56
```
57
58
### ThinkingBlock
59
60
Extended thinking content from Claude.
61
62
```python { .api }
63
@dataclass
64
class ThinkingBlock:
65
"""
66
Thinking content block.
67
68
Represents extended thinking from Claude when using models with
69
thinking capabilities (like Claude Opus with extended thinking enabled).
70
This shows Claude's internal reasoning process.
71
72
Attributes:
73
thinking: The thinking content
74
signature: Digital signature for the thinking block
75
"""
76
77
thinking: str
78
"""Thinking content.
79
80
Claude's internal reasoning and thought process. This text shows how
81
Claude is analyzing the problem, considering options, and planning
82
its response.
83
84
Example:
85
"Let me think through this step by step. First, I need to
86
understand what the user is asking. They want to know about...
87
I should consider... The best approach would be..."
88
"""
89
90
signature: str
91
"""Digital signature.
92
93
Cryptographic signature that verifies the authenticity of the thinking
94
content. Ensures the thinking wasn't modified after generation.
95
"""
96
```
97
98
### ToolUseBlock
99
100
Request from Claude to execute a tool.
101
102
```python { .api }
103
@dataclass
104
class ToolUseBlock:
105
"""
106
Tool use content block.
107
108
Represents a request from Claude to execute a tool. When Claude needs
109
to perform an action like reading a file or running a command, it
110
generates a ToolUseBlock with the tool name and input parameters.
111
112
The SDK or CLI handles executing the tool and providing results back
113
to Claude via ToolResultBlock.
114
115
Attributes:
116
id: Unique identifier for this tool use
117
name: Name of the tool to execute
118
input: Input parameters for the tool
119
"""
120
121
id: str
122
"""Unique tool use identifier.
123
124
A unique ID for this specific tool execution. Used to match tool
125
uses with their results (ToolResultBlock.tool_use_id).
126
127
Example: "toolu_01A2B3C4D5E6F7G8H9I0J1K2"
128
"""
129
130
name: str
131
"""Tool name.
132
133
The name of the tool Claude wants to execute. This matches tool
134
names from the allowed_tools configuration or MCP server tools.
135
136
Examples:
137
"Read" - Read a file
138
"Write" - Write a file
139
"Bash" - Execute a bash command
140
"Grep" - Search files
141
"custom_tool" - Your custom MCP tool
142
"""
143
144
input: dict[str, Any]
145
"""Tool input parameters.
146
147
Dictionary of parameters to pass to the tool. Structure varies by
148
tool type.
149
150
Examples:
151
{"file_path": "/home/user/file.txt"} # Read tool
152
{"command": "ls -la"} # Bash tool
153
{"pattern": "TODO", "path": "./src"} # Grep tool
154
"""
155
```
156
157
### ToolResultBlock
158
159
Result from executing a tool.
160
161
```python { .api }
162
@dataclass
163
class ToolResultBlock:
164
"""
165
Tool result content block.
166
167
Contains the result of a tool execution. After Claude requests a tool
168
use via ToolUseBlock, the SDK executes the tool and provides results
169
back to Claude in a ToolResultBlock.
170
171
Attributes:
172
tool_use_id: ID of the tool use this is a result for
173
content: The result content
174
is_error: Whether the tool execution resulted in an error
175
"""
176
177
tool_use_id: str
178
"""Tool use identifier.
179
180
The ID of the ToolUseBlock this result corresponds to. Used to match
181
results with their requests.
182
183
Example: "toolu_01A2B3C4D5E6F7G8H9I0J1K2"
184
"""
185
186
content: str | list[dict[str, Any]] | None = None
187
"""Result content.
188
189
The output from the tool execution. Can be:
190
- A string for simple text results
191
- A list of content dictionaries for rich content
192
- None if the tool produced no output
193
194
Examples:
195
"File contents: Hello World"
196
[{"type": "text", "text": "Success"}]
197
None
198
"""
199
200
is_error: bool | None = None
201
"""Error flag.
202
203
Indicates whether the tool execution resulted in an error:
204
- True: Tool execution failed
205
- False: Tool execution succeeded
206
- None: Error status not specified (usually means success)
207
208
When True, the content typically contains error details.
209
"""
210
```
211
212
## Usage Examples
213
214
### Extracting Text from Messages
215
216
```python
217
from claude_agent_sdk import query, AssistantMessage, TextBlock
218
219
async for msg in query(prompt="Explain Python"):
220
if isinstance(msg, AssistantMessage):
221
for block in msg.content:
222
if isinstance(block, TextBlock):
223
print(block.text)
224
```
225
226
### Handling All Block Types
227
228
```python
229
from claude_agent_sdk import (
230
query, AssistantMessage, TextBlock, ThinkingBlock,
231
ToolUseBlock, ToolResultBlock, ClaudeAgentOptions
232
)
233
234
options = ClaudeAgentOptions(allowed_tools=["Read", "Bash"])
235
236
async for msg in query(prompt="Analyze this project", options=options):
237
if isinstance(msg, AssistantMessage):
238
for block in msg.content:
239
if isinstance(block, TextBlock):
240
print(f"[Text] {block.text}")
241
242
elif isinstance(block, ThinkingBlock):
243
print(f"[Thinking] {block.thinking}")
244
245
elif isinstance(block, ToolUseBlock):
246
print(f"[Tool Use] {block.name}: {block.input}")
247
248
elif isinstance(block, ToolResultBlock):
249
error_status = " (ERROR)" if block.is_error else ""
250
print(f"[Tool Result{error_status}] {block.content}")
251
```
252
253
### Collecting Text Content
254
255
```python
256
from claude_agent_sdk import query, AssistantMessage, TextBlock
257
258
all_text = []
259
260
async for msg in query(prompt="Write a story"):
261
if isinstance(msg, AssistantMessage):
262
for block in msg.content:
263
if isinstance(block, TextBlock):
264
all_text.append(block.text)
265
266
full_response = "\n".join(all_text)
267
print(full_response)
268
```
269
270
### Monitoring Tool Usage
271
272
```python
273
from claude_agent_sdk import (
274
query, AssistantMessage, ToolUseBlock, ClaudeAgentOptions
275
)
276
277
options = ClaudeAgentOptions(allowed_tools=["Read", "Write", "Bash"])
278
279
tools_used = []
280
281
async for msg in query(prompt="Build a web server", options=options):
282
if isinstance(msg, AssistantMessage):
283
for block in msg.content:
284
if isinstance(block, ToolUseBlock):
285
tools_used.append({
286
"id": block.id,
287
"name": block.name,
288
"input": block.input
289
})
290
291
print(f"Claude used {len(tools_used)} tools:")
292
for tool in tools_used:
293
print(f" - {tool['name']}: {tool['input']}")
294
```
295
296
### Detecting Tool Errors
297
298
```python
299
from claude_agent_sdk import (
300
query, AssistantMessage, ToolResultBlock, ClaudeAgentOptions
301
)
302
303
options = ClaudeAgentOptions(allowed_tools=["Bash"])
304
305
async for msg in query(prompt="Run an invalid command", options=options):
306
if isinstance(msg, AssistantMessage):
307
for block in msg.content:
308
if isinstance(block, ToolResultBlock):
309
if block.is_error:
310
print(f"Error in tool {block.tool_use_id}:")
311
print(f" {block.content}")
312
```
313
314
### Building a Conversation Log
315
316
```python
317
from claude_agent_sdk import (
318
query, AssistantMessage, TextBlock, ToolUseBlock,
319
ToolResultBlock, ClaudeAgentOptions
320
)
321
322
options = ClaudeAgentOptions(allowed_tools=["Read"])
323
324
log = []
325
326
async for msg in query(prompt="Read config.json", options=options):
327
if isinstance(msg, AssistantMessage):
328
for block in msg.content:
329
if isinstance(block, TextBlock):
330
log.append({"type": "text", "content": block.text})
331
332
elif isinstance(block, ToolUseBlock):
333
log.append({
334
"type": "tool_use",
335
"tool": block.name,
336
"input": block.input
337
})
338
339
elif isinstance(block, ToolResultBlock):
340
log.append({
341
"type": "tool_result",
342
"content": block.content,
343
"error": block.is_error
344
})
345
346
# Display log
347
for entry in log:
348
print(f"{entry['type']}: {entry.get('content', entry.get('tool', ''))}")
349
```
350
351
### Filtering by Block Type
352
353
```python
354
from claude_agent_sdk import (
355
query, AssistantMessage, TextBlock, ToolUseBlock
356
)
357
358
text_blocks = []
359
tool_blocks = []
360
361
async for msg in query(prompt="Analyze files"):
362
if isinstance(msg, AssistantMessage):
363
text_blocks.extend([b for b in msg.content if isinstance(b, TextBlock)])
364
tool_blocks.extend([b for b in msg.content if isinstance(b, ToolUseBlock)])
365
366
print(f"Text blocks: {len(text_blocks)}")
367
print(f"Tool blocks: {len(tool_blocks)}")
368
```
369
370
### Extracting Thinking Content
371
372
```python
373
from claude_agent_sdk import (
374
query, AssistantMessage, ThinkingBlock, ClaudeAgentOptions
375
)
376
377
# Note: Thinking blocks require extended thinking enabled
378
options = ClaudeAgentOptions(
379
model="claude-opus-4-20250514" # Model with extended thinking
380
)
381
382
async for msg in query(prompt="Solve this complex problem", options=options):
383
if isinstance(msg, AssistantMessage):
384
for block in msg.content:
385
if isinstance(block, ThinkingBlock):
386
print("=== Claude's Thinking Process ===")
387
print(block.thinking)
388
print(f"Signature: {block.signature[:50]}...")
389
```
390
391
### Tool Use Chain Analysis
392
393
```python
394
from claude_agent_sdk import (
395
query, AssistantMessage, ToolUseBlock, ToolResultBlock,
396
ClaudeAgentOptions
397
)
398
399
options = ClaudeAgentOptions(allowed_tools=["Read", "Write", "Bash"])
400
401
tool_chain = []
402
403
async for msg in query(prompt="Create and test a script", options=options):
404
if isinstance(msg, AssistantMessage):
405
for block in msg.content:
406
if isinstance(block, ToolUseBlock):
407
tool_chain.append({
408
"id": block.id,
409
"type": "use",
410
"name": block.name,
411
"input": block.input
412
})
413
414
elif isinstance(block, ToolResultBlock):
415
# Find the matching tool use
416
for entry in tool_chain:
417
if entry["id"] == block.tool_use_id and entry["type"] == "use":
418
entry["result"] = block.content
419
entry["error"] = block.is_error
420
break
421
422
# Display tool chain
423
print("Tool Execution Chain:")
424
for i, entry in enumerate(tool_chain, 1):
425
if entry["type"] == "use":
426
status = "ERROR" if entry.get("error") else "SUCCESS"
427
print(f"{i}. {entry['name']} [{status}]")
428
print(f" Input: {entry['input']}")
429
if "result" in entry:
430
result_preview = str(entry["result"])[:100]
431
print(f" Result: {result_preview}...")
432
```
433
434
### Content Block Statistics
435
436
```python
437
from claude_agent_sdk import (
438
query, AssistantMessage, TextBlock, ThinkingBlock,
439
ToolUseBlock, ToolResultBlock
440
)
441
442
stats = {
443
"text": 0,
444
"thinking": 0,
445
"tool_use": 0,
446
"tool_result": 0
447
}
448
449
async for msg in query(prompt="Complex task"):
450
if isinstance(msg, AssistantMessage):
451
for block in msg.content:
452
if isinstance(block, TextBlock):
453
stats["text"] += 1
454
elif isinstance(block, ThinkingBlock):
455
stats["thinking"] += 1
456
elif isinstance(block, ToolUseBlock):
457
stats["tool_use"] += 1
458
elif isinstance(block, ToolResultBlock):
459
stats["tool_result"] += 1
460
461
print("Content Block Statistics:")
462
for block_type, count in stats.items():
463
print(f" {block_type}: {count}")
464
```
465
466
### Rich Content Handling
467
468
```python
469
from claude_agent_sdk import query, AssistantMessage, ToolResultBlock
470
471
async for msg in query(prompt="Task with rich output"):
472
if isinstance(msg, AssistantMessage):
473
for block in msg.content:
474
if isinstance(block, ToolResultBlock):
475
content = block.content
476
477
# Handle different content types
478
if isinstance(content, str):
479
print(f"Text result: {content}")
480
481
elif isinstance(content, list):
482
print("Rich content result:")
483
for item in content:
484
if isinstance(item, dict):
485
item_type = item.get("type", "unknown")
486
print(f" - Type: {item_type}")
487
if item_type == "text":
488
print(f" Text: {item.get('text', '')}")
489
490
elif content is None:
491
print("No output from tool")
492
```
493
494
### Tool Input Analysis
495
496
```python
497
from claude_agent_sdk import (
498
query, AssistantMessage, ToolUseBlock, ClaudeAgentOptions
499
)
500
501
options = ClaudeAgentOptions(allowed_tools=["Bash", "Read", "Write"])
502
503
tool_inputs = {}
504
505
async for msg in query(prompt="Work on this project", options=options):
506
if isinstance(msg, AssistantMessage):
507
for block in msg.content:
508
if isinstance(block, ToolUseBlock):
509
if block.name not in tool_inputs:
510
tool_inputs[block.name] = []
511
512
tool_inputs[block.name].append(block.input)
513
514
print("Tool Input Analysis:")
515
for tool_name, inputs in tool_inputs.items():
516
print(f"\n{tool_name} ({len(inputs)} uses):")
517
for i, input_data in enumerate(inputs, 1):
518
print(f" {i}. {input_data}")
519
```
520
521
### Separating Text and Actions
522
523
```python
524
from claude_agent_sdk import (
525
query, AssistantMessage, TextBlock, ToolUseBlock,
526
ClaudeAgentOptions
527
)
528
529
options = ClaudeAgentOptions(allowed_tools=["Read", "Write"])
530
531
explanations = []
532
actions = []
533
534
async for msg in query(prompt="Fix this bug", options=options):
535
if isinstance(msg, AssistantMessage):
536
for block in msg.content:
537
if isinstance(block, TextBlock):
538
explanations.append(block.text)
539
540
elif isinstance(block, ToolUseBlock):
541
actions.append(f"{block.name}: {block.input}")
542
543
print("=== What Claude Said ===")
544
print("\n".join(explanations))
545
546
print("\n=== What Claude Did ===")
547
print("\n".join(actions))
548
```
549
550
### Error Recovery Pattern
551
552
```python
553
from claude_agent_sdk import (
554
query, AssistantMessage, ToolUseBlock, ToolResultBlock,
555
ClaudeAgentOptions
556
)
557
558
options = ClaudeAgentOptions(allowed_tools=["Bash"])
559
560
current_tool_use = None
561
562
async for msg in query(prompt="Try a command", options=options):
563
if isinstance(msg, AssistantMessage):
564
for block in msg.content:
565
if isinstance(block, ToolUseBlock):
566
current_tool_use = block
567
print(f"Attempting: {block.name} with {block.input}")
568
569
elif isinstance(block, ToolResultBlock):
570
if block.is_error and current_tool_use:
571
print(f"Failed: {current_tool_use.name}")
572
print(f"Error: {block.content}")
573
print("Claude will likely try an alternative...")
574
elif current_tool_use:
575
print(f"Success: {current_tool_use.name}")
576
577
current_tool_use = None
578
```
579
580
### Block Type Distribution
581
582
```python
583
from claude_agent_sdk import (
584
query, AssistantMessage, TextBlock, ThinkingBlock,
585
ToolUseBlock, ToolResultBlock
586
)
587
588
def get_block_type_name(block):
589
if isinstance(block, TextBlock):
590
return "text"
591
elif isinstance(block, ThinkingBlock):
592
return "thinking"
593
elif isinstance(block, ToolUseBlock):
594
return "tool_use"
595
elif isinstance(block, ToolResultBlock):
596
return "tool_result"
597
else:
598
return "unknown"
599
600
block_sequence = []
601
602
async for msg in query(prompt="Multi-step task"):
603
if isinstance(msg, AssistantMessage):
604
for block in msg.content:
605
block_sequence.append(get_block_type_name(block))
606
607
print("Block sequence:")
608
print(" -> ".join(block_sequence))
609
```
610