Images
A memory can carry an image. The engine indexes the image, so a text query in any language matches it even when the record has no caption, title or alt text.
Storing one
Pass an image object to the ordinary add call. content may be empty; the image is then searchable on its own.
mem.add("at the beach", image={"data": b64}) # caption + image
mem.add("", image={"data": b64}) # the image IS the memorydata is required. A data:image/jpeg;base64, prefix and the line wrapping added by base64 and openssl are both stripped for you.
| Field | What it does |
|---|---|
| data | Base64 of the image. Required. The size ceiling is a server setting, not an SDK constant - /health reports it as memory.images.max_bytes. |
| reference | Where your own copy of the original lives. Stored as a string and never fetched by us - and the place for it, since what we keep is downscaled. |
| taken_at | RFC3339, usually from EXIF. Fills event_date when that is empty, so the memory sorts by when the image was taken rather than when it was uploaded. |
Finding one
There is no separate image search. search and recall return images alongside text, ranked together.
Working with the ones you have
data, mime = mem.get_image(memory_id=mid)
page = mem.list_images(limit=50) # page["count"] = store total
mem.forget_image(memory_id=mid, preview=True)| Call | What it does |
|---|---|
| get_image | The picture we hold, as (bytes, content_type) - not necessarily your upload. An image whose long edge was over 1,568 px was stored downscaled, and re-encoded to WebP unless it was a JPEG, so a PNG comes back as image/webp. The type is sniffed from the bytes, not from whatever the upload was named, so name the file from content_type. A memory with no image raises rather than returning something empty. |
| list_images | One page, newest first, plus count - the store's total, not the page size. Paging is by cursor: hand next_before and next_skip_ids back. Both are needed because images can share a timestamp. |
| forget_image | Removes the image and keeps the text. An image stored with no caption is the memory, so there it deletes the memory too. |
Pass preview=True to forget_image to get memory_kept without changing anything. iter_images pages for you.
What an image costs
Images are billed in tokens, like text. Tokens = pixel area / 556.7. Above 1,568 px on the long edge the count is taken at 1,568 px, so a 2,500 px image and a 1,568 px image cost the same.
| Image | Counted at | Tokens |
|---|---|---|
| 700 × 700 | as sent | 881 |
| 1000 × 1000 | as sent | 1,797 |
| 1568 × 1568 | as sent | 4,417 |
| 1920 × 1080 | 1568 × 882 | 2,485 |
| 2500 × 1875 | 1568 × 1176 | 3,313 |
| 2500 × 2500 | 1568 × 1568 | 4,417 |
Ceiling: 4,417 tokens per image. The ceiling is reserved against your balance before the call; the measured value is charged after and is never higher.
image/webp. JPEG stays JPEG, and below 1,568 px the bytes are untouched. (If re-encoding would make the file bigger, we keep your bytes as they were.) Both edges must still be ≥ 700 px and the long edge ≤ 2,500 px or the call is refused with a 400 - under 700 px a flat minimum applies, so a smaller image costs the same to store, and over 2,500 px we will not decode the file at all. Keep your own copy, or put its URL in reference, if you need the full-resolution file.How many come back
Default 1, maximum 5 images per response. Five images is close to 20,000 tokens.
| Field | What it does |
|---|---|
| max_images | 0 to 5. Images a single response may carry. Default 1. 0 returns text only. Out of range is rejected rather than clamped. |