Skip to content

ImagesΒΆ

An artifact can carry pictures in flock.Image fields. The picture is stored inline, as a base64 data:image/... URL, so it moves through stores, the REST API, the dashboard and agents like any other field.

from pydantic import BaseModel

from flock import Flock, Image, flock_type


@flock_type
class ProductPhoto(BaseModel):
    sku: str
    photo: Image                 # also: Image | None, list[Image], nested models


flock = Flock("openai/gpt-4.1")
await flock.publish(ProductPhoto(sku="A-17", photo=Image.from_file("a17.jpg")))

Creating imagesΒΆ

Image.from_file(), Image.from_bytes() and Image.from_pil() scale a picture down to max_side (default 1024 px) and re-encode it. Pictures without transparency become JPEG, pictures with transparency become PNG. Re-encoding drops metadata such as EXIF and GPS positions. Image(url="data:image/png;base64,...") takes an existing data URL as it is.

LimitsΒΆ

Limit Value Checked
Decoded size 20 MB When an Image is created, and again before any artifact is stored
Pixels 50 million (e.g. 8660 x 5773) From the image header, before decoding
Source Inline data:image/...;base64,... only URLs and file paths are rejected
Uploads per request (REST) 20 files, and at most 20 x 20 MB in total Total size before the body is parsed, file count while it is parsed

The limits hold on every publish path:

  • Models: flock.publish(ProductPhoto(...)) validates the Image field when the model is created.
  • Dicts: flock.publish({"type": ..., "payload": ...}) validates the payload against the registered model.
  • Everything else: before any artifact is stored, its inline image data is checked against the same limits. This covers Artifact objects published directly, component publishes, agent outputs and models changed after they were created.
  • REST: POST /api/v1/artifacts (JSON) and POST /api/v1/artifacts/upload (multipart; see the REST API guide).
  • Dashboard: the publish panel. The server re-encodes those pictures as well.

Smaller pictures are faster and cheaper: every image is sent to the model in full and counts against its context.

Agents and decision modelsΒΆ

  • LLM agents (DSPy engine) receive Image fields as pictures, also in batches and joins. Images in conversation context are described (πŸ–Ό image/jpeg Β· 42 KB), not inlined. See image inputs.
  • Decision models that accept images decide about pictures. See decision models.

Dashboard and API responsesΒΆ

  • Publishing: the publish panel has a picture picker for Image and list[Image] fields.
  • Viewing: graph nodes, the message detail window, the message history and the historical blackboard show 160 px thumbnails. A click loads the full image through GET /api/v1/artifacts/{id}.
  • Transfer: graph snapshots and WebSocket events carry descriptions and thumbnails, never full image data. API clients can request the same form with images=thumbnails (REST API guide).
  • Traces: spans record a description (πŸ–Ό image/png Β· 12 KB), not the pixels.

Security rulesΒΆ

  • No fetching. Flock never loads an image from a URL or a file path named in an artifact. Only inline data is accepted, so artifacts cannot make the server or a model provider fetch remote content.
  • Checked uploads. Uploaded files must be JPEG, PNG, GIF, WebP or BMP. Formats that run external tools, such as EPS, are refused. Size and pixel limits are checked before decoding, and every upload and dashboard picture is re-encoded, which drops metadata.
  • Visibility. Image data is part of the payload and follows the artifact's visibility: the REST endpoints return neither the image nor its thumbnail to callers who may not see the artifact. Two gaps are known and tracked for 1.0:

    • WebSocket events, including thumbnails, currently go to every dashboard client (#431).
    • Graph, message history and trace reads are not yet authorized per caller (#432).

    Until both are closed, run the dashboard only where every viewer may see every artifact. - Storage. Inline images make artifacts large, about 4/3 of the file size, and every copy (stores, exports) carries the full data. Keep max_side modest. Dapr state stores can have size limits per item.

ExamplesΒΆ

Example Shows
examples/01-getting-started/19_image_agent.py An LLM agent checking captions against pictures
examples/15-decisions/03_color_sorter.py A decision model sorting pictures by color