Skip to content

Support images in tool results (for fetch_screenshot) #47

Description

@tcdent

Summary

Add support for returning images (and other binary content) from tool results, enabling a fetch_screenshot tool that returns page screenshots for Claude to interpret visually.

Background

While implementing Chrome profile support for fetch_html, we discovered that:

  1. The readability algorithm strips content from feed-style pages (Twitter/X, etc.)
  2. Screenshots would be ideal for visual content Claude can interpret directly
  3. chromiumoxide supports full-page screenshots via page.screenshot()

Current Limitation

The genai library's ToolResponse only supports string content:

// lib/genai/src/chat/tool/tool_response.rspubstructToolResponse{pubcall_id:String,pubcontent:String,// <-- String only}

And the Anthropic adapter serializes it as a simple string:

// lib/genai/src/adapter/adapters/anthropic/adapter_impl.rs:570-574
values.push(json!({"type":"tool_result","content": tool_response.content,// <-- Just a string"tool_use_id": tool_response.call_id,}));

What Anthropic API Actually Supports

Anthropic's API accepts rich content in tool_result, including images:

{
"type": "tool_result",
"tool_use_id": "toolu_...",
"content": [
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": "iVBORw0KGgo..."
}
},
{
"type": "text",
"text": "Screenshot of the page"
}
]
}

Proposed Changes

1. Modify genai's ToolResponse

Change content from String to support rich content:

pubstructToolResponse{pubcall_id:String,pubcontent:ToolResponseContent,}pubenumToolResponseContent{Text(String),Parts(Vec<ContentPart>),}

Or simply use MessageContent:

pubstructToolResponse{pubcall_id:String,pubcontent:MessageContent,}

2. Update Anthropic Adapter

Serialize images properly when present in tool results.

3. Update Codey's Agent

Change submit_tool_result signature:

// Currentpubfnsubmit_tool_result(&mutself,call_id:&str,content:String)// Newpubfnsubmit_tool_result(&mutself,call_id:&str,content:implInto<MessageContent>)

4. Add fetch_screenshot Tool

pubasyncfnfetch_screenshot(url:&str) -> Result<Vec<u8>,String>{// Uses same browser infrastructure as fetch_html// Returns PNG bytes}

Use Cases

  • Twitter/X feeds - Readability strips most content; screenshots preserve full context
  • Dashboards - Visual layouts don't convert well to markdown
  • Charts/graphs - Better interpreted visually
  • Any SPA - Complex rendered content

Related

References

  • Anthropic Tool Use Docs
  • genai ContentPart already supports Binary: ContentPart::from_binary_base64("image/png", data, None)
  • chromiumoxide screenshot: page.screenshot(ScreenshotParams::builder().full_page(true).build())

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions