ConnectOnionConnectOnion
DocsUseful Pluginsimage_result_formatter

image_result_formatter

Enable vision models to see images from tool results

What it does

When a tool returns a base64-encoded image (screenshot, generated image, etc.), this plugin:

Detects base64 images

Recognizes data URLs (data:image/png;base64,...) and plain base64 strings.

Converts to vision format

Transforms the tool result into OpenAI vision API format so the LLM can see the image visually.

Quick Start

main.py
1from connectonion import Agent 2from connectonion.useful_plugins import image_result_formatter 3 4def take_screenshot(url: str) -> str: 5 """Take a screenshot of a webpage.""" 6 # Returns base64-encoded PNG 7 return capture_screenshot(url) 8 9agent = Agent( 10 "vision_assistant", 11 tools=[take_screenshot], 12 plugins=[image_result_formatter], 13 model="gpt-4o" # Use a vision model 14) 15 16agent.input("Take a screenshot of example.com and describe what you see")
Python REPL
Interactive
[Tool: take_screenshot("example.com")]
🖼️ Formatted 'take_screenshot' result as image
The screenshot shows a simple webpage with the heading "Example Domain"...

Without vs With Plugin

Without Plugin

The LLM receives raw base64 text:

Tool result: "iVBORw0KGgoAAAANSUhEUgAAA..."

LLM cannot interpret this as an image!

With Plugin

The LLM receives proper image format:

{type: "image_url", url: "data:image/png;..."}

LLM can see and analyze the image!

How it works

main.py
1@after_tools 2def _format_image_result(agent): 3 trace = agent.current_session['trace'][-1] 4 5 if trace['type'] != 'tool_execution' or trace['status'] != 'success': 6 return 7 8 result = trace['result'] 9 is_image, mime_type, base64_data = _is_base64_image(result) 10 11 if not is_image: 12 return 13 14 # Find and modify the tool result message 15 messages = agent.current_session['messages'] 16 for i, msg in enumerate(reversed(messages)): 17 if msg['role'] == 'tool' and msg.get('tool_call_id') == trace['call_id']: 18 # Shorten tool message (save tokens) 19 msg['content'] = "Screenshot captured (image provided below)" 20 21 # Insert user message with actual image 22 messages.insert(len(messages) - i, { 23 "role": "user", 24 "content": [ 25 {"type": "text", "text": "Tool returned an image. See below."}, 26 {"type": "image_url", "image_url": {"url": f"data:{mime_type};base64,{base64_data}"}} 27 ] 28 }) 29 break

Supported Formats

FormatExample
PNGdata:image/png;base64,...
JPEGdata:image/jpeg;base64,...
WebPdata:image/webp;base64,...
GIFdata:image/gif;base64,...
Plain base64Long base64 strings (defaults to PNG)

Use Cases

  • Screenshots: Browser automation tools that capture pages
  • Image generation: Tools that create images (charts, diagrams)
  • Visual analysis: Any tool returning visual data for LLM interpretation

Events Used

EventHandlerPurpose
after_tools_format_image_resultConvert base64 to vision format

Uses after_tools (not after_each_tool) because message modification must happen after all tools complete.

Source

connectonion/useful_plugins/image_result_formatter.py

main.py
1# The plugin is just a list with one event handler 2image_result_formatter = [after_tools(_format_image_result)]