async for message in client: if isinstance(message, AssistantMessage): for block in message.content: if isinstance(block, TextBlock): print(f"Claude says: {block.text}")
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.
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')}")
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.
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}")