Skip to main content

Module 05: Message Types

Understanding the message and content block type hierarchy.

What You’ll Learn

  • The four message types: User, Assistant, System, Result
  • Content block types inside Assistant messages
  • Pattern matching with sealed interfaces
  • Extracting text and tool use information

Message Type Hierarchy

ParsedMessage (sealed)
├── RegularMessage → contains Message
│   ├── UserMessage      - Your input
│   ├── AssistantMessage - Claude's response (has content blocks)
│   ├── SystemMessage    - System context
│   └── ResultMessage    - Session completion metadata
├── Control              - Hook requests
├── ControlResponseMessage
└── EndOfStream          - Internal marker

Content Block Types

Inside AssistantMessage.content():
Block TypeDescriptionKey Methods
TextBlockRegular texttext()
ToolUseBlockTool invocationid(), name(), input()
ToolResultBlockTool resulttoolUseId(), content()
ThinkingBlockReasoning (when enabled)thinking()

Pattern Matching with Switch

Message message = parsed.asMessage();

switch (message) {
    case AssistantMessage assistant -> {
        for (ContentBlock block : assistant.content()) {
            switch (block) {
                case TextBlock text ->
                    System.out.println(text.text());
                case ToolUseBlock tool ->
                    System.out.println("Tool: " + tool.name());
                case ToolResultBlock result ->
                    System.out.println("Result: " + result.toolUseId());
                case ThinkingBlock thinking ->
                    System.out.println("Thinking: " + thinking.thinking());
                default -> { }
            }
        }
    }
    case ResultMessage result -> {
        System.out.printf("Cost: $%.6f%n", result.totalCostUsd());
        System.out.printf("Duration: %d ms%n", result.durationMs());
    }
    case UserMessage user ->
        System.out.println("User: " + user.content());
    case SystemMessage system ->
        System.out.println("System: " + system.subtype());
    default -> { }
}

ResultMessage Fields

FieldDescription
durationMs()Total time
durationApiMs()API time only
numTurns()Conversation turns
sessionId()Session identifier
totalCostUsd()Total cost
usage()Token usage
isError()Error flag
result()Error message if isError

AssistantMessage Convenience Methods

AssistantMessage assistant = ...;

// Get all text concatenated (empty string if none)
String text = assistant.text();

// Print directly - toString() returns the text
System.out.println(assistant);  // Same as assistant.text()

// Get first text block content (Optional)
Optional<String> firstText = assistant.getTextContent();

// Get all text blocks
List<TextBlock> textBlocks = assistant.getTextBlocks();

// Get all tool use blocks
List<ToolUseBlock> tools = assistant.getToolUses();

// Check if message has tool use
boolean hasTool = assistant.hasToolUse();

Message toString() Methods

All message types have useful toString() implementations:
for (Message msg : client.connectAndReceive("List files")) {
    System.out.println(msg);  // Works for all message types
}

// AssistantMessage: prints the text content
// ResultMessage: "[Result: cost=$0.001234, turns=3, session=abc123]"
// UserMessage: prints the user input
// SystemMessage: prints system info

Source Code

View on GitHub

Running the Example

mvn compile exec:java -pl module-05-message-types

Next Module

Module 06: CLI Options - Learn about fine-grained configuration of Claude’s behavior.