Skip to main content

Overview

Content blocks represent different types of content within messages. They are used in both UserMessage and AssistantMessage content.
ContentBlock = TextBlock | ThinkingBlock | ToolUseBlock | ToolResultBlock

TextBlock

Represents plain text content.
@dataclass
class TextBlock:
    text: str
text
str
required
The text content.

Example

async for message in client:
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if isinstance(block, TextBlock):
                print(f"Claude says: {block.text}")

ThinkingBlock

Represents Claude’s internal reasoning (extended thinking).
@dataclass
class ThinkingBlock:
    thinking: str
    signature: str
thinking
str
required
The thinking content showing Claude’s reasoning process.
signature
str
required
Cryptographic signature verifying the thinking content.

Example

async for message in client:
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if isinstance(block, ThinkingBlock):
                print(f"Claude's reasoning: {block.thinking}")
                print(f"Verified: {block.signature}")
Thinking blocks are only present when extended thinking is enabled via the thinking option in ClaudeAgentOptions.

ToolUseBlock

Represents Claude’s intent to use a tool.
@dataclass
class ToolUseBlock:
    id: str
    name: str
    input: dict[str, Any]
id
str
required
Unique identifier for this tool use (e.g., "toolu_01ABC123").
name
str
required
Name of the tool being invoked (e.g., "Bash", "Read", "Write").
input
dict[str, Any]
required
Tool input parameters as a dictionary.

Example

async for message in client:
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if isinstance(block, ToolUseBlock):
                print(f"Tool: {block.name}")
                print(f"ID: {block.id}")
                print(f"Input: {block.input}")
                
                # Example tool use
                if block.name == "Bash":
                    print(f"Command: {block.input.get('command')}")
                elif block.name == "Write":
                    print(f"File: {block.input.get('filePath')}")

Common Tool Input Schemas

ToolResultBlock

Represents the result of a tool execution.
@dataclass
class ToolResultBlock:
    tool_use_id: str
    content: str | list[dict[str, Any]] | None = None
    is_error: bool | None = None
tool_use_id
str
required
ID of the tool use this result corresponds to (matches ToolUseBlock.id).
content
str | list[dict[str, Any]] | None
Tool output content. Can be:
  • A string for simple text output
  • A list of content blocks for structured output
  • None if the tool had no output
is_error
bool | None
Whether the tool execution resulted in an error.

Example

async for message in client:
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if isinstance(block, ToolResultBlock):
                print(f"Tool result for: {block.tool_use_id}")
                if block.is_error:
                    print(f"Error: {block.content}")
                else:
                    print(f"Output: {block.content}")
Tool result blocks are typically generated internally by the SDK and CLI. You usually don’t need to create them manually unless implementing custom tool execution.

Pattern Matching Example

Python 3.10+ pattern matching makes it easy to handle different content block types:
async for message in client:
    if isinstance(message, AssistantMessage):
        for block in message.content:
            match block:
                case TextBlock(text=text):
                    print(f"Text: {text}")
                
                case ThinkingBlock(thinking=thinking):
                    print(f"Thinking: {thinking}")
                
                case ToolUseBlock(id=tool_id, name=name, input=input):
                    print(f"Tool {name} ({tool_id}): {input}")
                
                case ToolResultBlock(tool_use_id=tool_id, content=content, is_error=is_error):
                    status = "error" if is_error else "success"
                    print(f"Result for {tool_id} ({status}): {content}")

Type Guards

For older Python versions or more explicit type checking:
from claude_agent_sdk.types import (
    TextBlock,
    ThinkingBlock,
    ToolUseBlock,
    ToolResultBlock,
)

async for message in client:
    if isinstance(message, AssistantMessage):
        for block in message.content:
            if isinstance(block, TextBlock):
                print(f"Text: {block.text}")
            elif isinstance(block, ThinkingBlock):
                print(f"Thinking: {block.thinking}")
            elif isinstance(block, ToolUseBlock):
                print(f"Tool: {block.name}")
            elif isinstance(block, ToolResultBlock):
                print(f"Result: {block.content}")

Build docs developers (and LLMs) love