API

Introducing Backboard’s Image Tool: Streaming-native Image Generation for Your Agents

Today we are launching Image Tool, a built‑in image generation capability for Backboard threads. It lets your agents create and edit images inside normal conversations, with streaming support and first‑class document IDs for follow‑ups.

If you are already using Backboard for text agents, you do not need a new API. You just turn image generation on per message, choose an image model, and let the thread LLM decide when to call the built‑in generate_image tool.

How it works

Image Tool is enabled per message through three new fields:

  • image_generation="auto"

  • image_model_provider

  • image_model_name

You send a normal conversation message. The thread LLM chooses when to call the tool and Backboard handles the image generation and media events for you.

This gives you:

  • Text‑to‑image inside any agent conversation

  • Image‑to‑image edits within the same thread

  • Streaming image URLs and document_ids via media_generated events

  • A simple upgrade path from text‑only agents to multimodal experiences

Python SDK: text‑to‑image in one call

The Python SDK exposes the image fields directly on send_message().


Python
import asyncio
from backboard import BackboardClient
async def main():
client = BackboardClient(api_key="YOUR_API_KEY")
response = await client.send_message(
"Generate a square image of a tiny red robot watering a sunflower in a sunny garden.",
llm_provider="openai",
model_name="gpt-4.1",
image_generation="auto",
image_model_provider="openrouter",
image_model_name="google/gemini-3.1-flash-image-preview",
)
print(response.content)
print(response.thread_id)
print(response.assistant_id)
asyncio.run(main())

You keep your usual text workflow. By adding the image fields, you unlock image generation without managing a separate media pipeline.

Streaming: capture images as they are generated

Most image experiences feel better when they stream. Backboard surfaces images through media_generated events on the same stream you already use for content.


Python
import asyncio
from backboard import BackboardClient
async def main():
client = BackboardClient(api_key="YOUR_API_KEY")
stream = await client.send_message(
"Generate a square image of a tiny red robot watering a sunflower in a sunny garden.",
llm_provider="openai",
model_name="gpt-4.1",
image_generation="auto",
image_model_provider="openrouter",
image_model_name="google/gemini-3.1-flash-image-preview",
stream=True,
)
generated_document_id = None
async for chunk in stream:
event_type = chunk.get("type")
if event_type == "media_generated":
media = chunk.get("media", {})
generated_document_id = media.get("document_id")
print("image url:", media.get("url"))
print("document_id:", generated_document_id)
if event_type == "content_streaming":
print(chunk.get("content", ""), end="", flush=True)
print()
print("final document_id:", generated_document_id)
asyncio.run(main())

Key behavior:

  • content_streaming delivers partial text as usual

  • media_generated gives you the image URL and a stable document_id you can store for later edits or display in your app

Image‑to‑image: edit by document_id

Because images are treated as first‑class documents, you can perform follow‑up edits by referencing the prior document_id inside the same thread.


Python
async def main():
client = BackboardClient(api_key="YOUR_API_KEY")
first = await client.send_message(
"Generate a square image of a tiny red robot watering a sunflower in a sunny garden.",
llm_provider="openai",
model_name="gpt-4.1",
image_generation="auto",
image_model_provider="openrouter",
image_model_name="google/gemini-3.1-flash-image-preview",
stream=True,
)
document_id = None
thread_id = None
async for chunk in first:
if chunk.get("thread_id"):
thread_id = chunk.get("thread_id")
if chunk.get("type") == "media_generated":
document_id = (chunk.get("media") or {}).get("document_id")
if not thread_id or not document_id:
raise RuntimeError("Missing thread_id or document_id from first image generation")
second = await client.send_message(
(
f"Edit the generated image with document_id {document_id}. "
"Pass this exact id as input_image_document_id to the generate_image tool. "
"Make the robot blue and add a small crescent moon in the sky."
),
thread_id=thread_id,
llm_provider="openai",
model_name="gpt-4.1",
image_generation="auto",
image_model_provider="openrouter",
image_model_name="google/gemini-3.1-flash-image-preview",
stream=True,
)
async for chunk in second:
if chunk.get("type") == "media_generated":
media = chunk.get("media", {})
print("edited image url:", media.get("url"))
print("edited document_id:", media.get("document_id"))
asyncio.run(main())

This pattern lets you build iterative design flows. Your users can ask an agent to refine an existing image, and your app only needs to keep track of thread_id and document_id.

JavaScript and TypeScript

The current JavaScript SDK helper does not yet expose image fields, so you call the HTTP API directly with the standard /threads/messages request.


Typescript
const response = await fetch("https://app.backboard.io/api/threads/messages", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "Generate a square image of a tiny red robot watering a sunflower in a sunny garden.",
llm_provider: "openai",
model_name: "gpt-4.1",
image_generation: "auto",
image_model_provider: "openrouter",
image_model_name: "google/gemini-3.1-flash-image-preview",
stream: false,
}),
});
const result = await response.json();
console.log(result.content);


This uses the same fields and behavior as the Python SDK. When streaming is enabled, you receive media_generated events in the response stream.

Parameters at a glance

Field

Description

image_generation

Set to "auto" to enable the built‑in image tool

image_model_provider

Provider for the image model, such as openrouter or google

image_model_name

Image‑capable model name

thread_id

Reuse the same thread for follow‑up edits

stream

Enables media_generated events for streaming images

Recommended setup

To get the best experience:

  1. Use a normal thread LLM such as gpt-4.1 for conversation

  2. Configure an image model with image_model_provider and image_model_name

  3. Turn on streaming so you can react to media_generated events

  4. Store document_id values for any images you want to edit or redisplay later

What you can build with Image Tool

Some examples that work out of the box:

  • UI and marketing agents that generate hero images and iterate on them with user feedback

  • Product customization flows that let users start from a base template and refine by prompt

  • Design review bots that annotate or modify existing images based on natural language instructions

Any place you already rely on Backboard threads, you can now add images without standing up a separate media service.

ON THIS PAGE

No headings found on page

CATEGORY

API

PUBLISHED

SHARE