use claude_agent_sdk::{
ClaudeAgentOptions, ContentBlock, Message, PermissionMode, UserContentBlock,
query_stream_with_content, query_with_content,
};
use futures::stream::StreamExt;
const SAMPLE_RED_PNG_BASE64: &str = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==";
const SAMPLE_BLUE_PNG_BASE64: &str = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPj/HwADBwIAMCbHYQAAAABJRU5ErkJggg==";
#[tokio::main]
async fn main() -> anyhow::Result<()> {
println!("=== Example 23: Multimodal Image Input ===\n");
let options = ClaudeAgentOptions::builder()
.permission_mode(PermissionMode::BypassPermissions)
.max_turns(1)
.build();
println!("--- Example 1: Query with Base64 Image ---\n");
example_base64_image(options.clone()).await?;
println!("\n--- Example 2: Query with Multiple Images ---\n");
example_multiple_images(options.clone()).await?;
println!("\n--- Example 3: Streaming with Image Content ---\n");
example_streaming_with_image(options.clone()).await?;
println!("\n--- Example 4: Image URL Reference ---\n");
example_image_url().await?;
println!("\n--- Example 5: Validation Error Handling ---\n");
example_validation_errors();
println!("\n=== All Examples Complete ===");
Ok(())
}
async fn example_base64_image(options: ClaudeAgentOptions) -> anyhow::Result<()> {
println!("Creating content with text and image...");
let content = vec![
UserContentBlock::text(
"What color is this 1x1 pixel image? Reply with just the color name.",
),
UserContentBlock::image_base64("image/png", SAMPLE_RED_PNG_BASE64)?,
];
println!("Sending query with image to Claude...");
let messages = query_with_content(content, Some(options)).await?;
for message in messages {
if let Message::Assistant(msg) = message {
for block in &msg.message.content {
if let ContentBlock::Text(text) = block {
println!("Claude's response: {}", text.text);
}
}
}
}
Ok(())
}
async fn example_multiple_images(options: ClaudeAgentOptions) -> anyhow::Result<()> {
println!("Creating content with multiple images for comparison...");
let content = vec![
UserContentBlock::text(
"I'm showing you two 1x1 pixel images. What colors are they? Reply briefly.",
),
UserContentBlock::image_base64("image/png", SAMPLE_RED_PNG_BASE64)?,
UserContentBlock::image_base64("image/png", SAMPLE_BLUE_PNG_BASE64)?,
];
println!("Sending query with multiple images...");
let messages = query_with_content(content, Some(options)).await?;
for message in messages {
if let Message::Assistant(msg) = message {
for block in &msg.message.content {
if let ContentBlock::Text(text) = block {
println!("Claude's response: {}", text.text);
}
}
}
}
Ok(())
}
async fn example_streaming_with_image(options: ClaudeAgentOptions) -> anyhow::Result<()> {
println!("Creating streaming query with image...");
let content = vec![
UserContentBlock::image_base64("image/png", SAMPLE_RED_PNG_BASE64)?,
UserContentBlock::text("Describe what you see in this image. Keep it brief."),
];
let mut stream = query_stream_with_content(content, Some(options)).await?;
print!("Claude's response: ");
while let Some(result) = stream.next().await {
let message = result?;
if let Message::Assistant(msg) = message {
for block in &msg.message.content {
if let ContentBlock::Text(text) = block {
print!("{}", text.text);
}
}
}
}
println!();
Ok(())
}
async fn example_image_url() -> anyhow::Result<()> {
println!("Creating content with image URL...");
let content = [
UserContentBlock::text("Describe this diagram"),
UserContentBlock::image_url("https://example.com/architecture-diagram.png"),
];
println!("Content blocks created:");
for (i, block) in content.iter().enumerate() {
let json = serde_json::to_string_pretty(block)?;
println!(" Block {}: {}", i + 1, json);
}
println!("\nNote: URL images require publicly accessible URLs.");
println!("The URL is passed to Claude who fetches the image directly.");
Ok(())
}
fn example_validation_errors() {
println!("Testing validation for unsupported MIME types...\n");
let result = UserContentBlock::image_base64("image/bmp", "somedata");
match result {
Err(e) => println!("Expected error for image/bmp: {}", e),
Ok(_) => println!("Unexpected: image/bmp should have failed"),
}
let result = UserContentBlock::image_base64("image/tiff", "somedata");
match result {
Err(e) => println!("Expected error for image/tiff: {}", e),
Ok(_) => println!("Unexpected: image/tiff should have failed"),
}
println!("\nSupported MIME types:");
for mime in &["image/jpeg", "image/png", "image/gif", "image/webp"] {
let result = UserContentBlock::image_base64(*mime, "data");
match result {
Ok(_) => println!(" {} - OK", mime),
Err(_) => println!(" {} - FAILED (unexpected)", mime),
}
}
}