or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration-options.mdcustom-tools.mderror-handling.mdhook-system.mdindex.mdinteractive-client.mdmessage-types.mdsimple-queries.mdtransport-system.md

message-types.mddocs/

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).