Skip to main content
Every Claude model on Gloo AI can read images, and so can every Gemini and Grok chat model and every OpenAI GPT model except the open-weight GPT OSS models. This tutorial builds two small features with Claude on Direct Responses, POST /ai/v2/direct/responses: a photo of a fridge becomes a dinner recipe, and a screenshot of an email or text message becomes three suggested replies. Want the concepts first? Images In and Out in the AI Learning Center explains image input (vision) and image generation. For production advice, such as keeping images small and switching models mid-conversation, see Images in Conversations.
Direct or guarded? Both take the same request body. This tutorial uses Direct Responses, which bills the model’s published rate and suits apps that handle their own safety. To have Gloo’s guardrails and values alignment built in, send the same request to the guarded Responses endpoint; see Use the guarded endpoint.

Prerequisites

Before starting, make sure you have:
  • A Gloo AI Studio account
  • Your API key from the API Keys page, exported as GLOO_API_KEY
  • Authentication setup: complete the Authentication Tutorial first
  • Python 3.9+ with requests (pip install requests), or Node.js 18+ (for built-in fetch)
  • The TypeScript samples use top-level await, so run them as ES modules (for example, save them as .mts files or set "type": "module" in package.json)
  • Two images to try: a photo of the inside of a fridge saved as fridge.jpg, and a screenshot of an email or text message saved as message.png

What You’ll Build

  1. Pick a model that reads images: find vision models in the live catalog
  2. Turn an image into a request part: encode a file or an upload as base64
  3. Fridge photo to recipe: list what’s in the photo and suggest a dinner
  4. Screenshot to suggested replies: read a message and draft answers
  5. Keep talking about the image: ask follow-up questions in the same conversation

Step 1: Pick a Model That Reads Images

A model that can read images has supports_vision: true in the catalog, and its input_modalities include "image". The catalog is at GET /platform/v2/models and needs no API key. List the current models that read images:
This tutorial uses Claude Sonnet 5.5 (gloo-anthropic-claude-sonnet-5.5), which reads photos and screenshots well. Any model on that list works: change the MODEL constant to try another. To compare models by price and capability, see Supported Models.

Step 2: Turn an Image into a Request Part

An image goes into a user message as an input_image part, next to an input_text part with your question. Its image_url is either a public https:// link or the image itself as a base64 data: URI (base64 writes a file’s bytes as plain text so they fit in JSON). Use base64 for photos your users take or upload. It works with every model that reads images, and the model never has to fetch anything from the internet.
Phone photos. Many phones save photos as HEIC, which not every model reads. Convert to JPEG before sending, and scale large photos down to about 1,500 pixels on the long side: the model reads a fridge shelf or a screenshot just as well, and the request is smaller and cheaper. See Keep images small.
Keep your API key on your server. A browser or mobile app sends the photo to your backend, and your backend calls Gloo AI. See API Key Security.

Step 3: Turn a Fridge Photo into a Recipe

Send the photo with a question, and use instructions (the system prompt) to set the rules: cook only with what’s visible, and say so when something is unclear.
Claude Sonnet 5.5 reasons before it answers, and max_output_tokens holds that reasoning as well as the answer. The examples set 16,384 to leave room for both. See Set your output limit for reasoning models.
The answer is an ordinary text response in output[], the same shape as any other Responses request:
The image counts toward input_tokens and is billed at the model’s input rate, like the text you send. A larger image uses more tokens.

Step 4: Turn a Screenshot into Suggested Replies

A screenshot works the same way. Here the instructions do one more job: the text inside the image is the message to answer, never instructions for the model. An image can carry text that tries to redirect the model, just as typed text can (see prompt injection).
If your app needs the replies as separate fields, for example to show three buttons, ask for structured output with a forced tool call; the suggested replies example shows the pattern.

Step 5: Keep Talking About the Image

Your app holds the conversation and sends all of it on every request (Conversations That Remember explains why). Append the Step 3 answer and the next question to the same list, and the photo goes along with it, so the model can look again. With cURL, do the same by hand: add the answer as an assistant item and the new question as a user item after the first user item, which still carries the image.
Two things follow from resending the history:
  • The image is billed again on every turn, as input tokens. For a long conversation, have the model describe the image once and keep that description in place of the image.
  • Every model in the conversation must read images. Keep the conversation on a model with supports_vision, such as any Claude, Gemini or Grok chat model, or any OpenAI GPT model other than GPT OSS. A model that can’t read images can’t take a conversation that holds one, and the request fails.
Images in Conversations shows both patterns in code.

Use the Guarded Endpoint

To have Gloo’s guardrails, output moderation and values alignment run around the same request, change the URL and keep the body:
With the Python or TypeScript code above, set API_URL to https://platform.ai.gloo.com/ai/v2/guarded/responses. Guarded requests are priced at the model’s rate plus 6.5% for guardrails, moderation and values alignment. For images that people you don’t control upload, see Images and moderation.

Troubleshooting

413, or a request refused as too large : The request body is over 10 MB, and base64 makes an image about a third larger than the file. Scale the photo down or send fewer images per request. See Request size. 400 about the image’s format : Send JPEG, PNG, GIF or WebP, and check that the data: URI’s type matches the file, for example data:image/png;base64, for a PNG. The request fails on a model you switched to : That model may not read images. Check supports_vision in the catalog (Step 1), or replace the image with a text description before switching. 400 with provider_content_policy_violation : The model’s maker declined the image or the request under its own content policy. Don’t send it again unchanged; see Content Policy Refusals. A link in image_url fails : A link is fetched over the internet when the request runs, so it must be public and must not expire first. Send base64 instead for private images. The answer stops early, or status is "incomplete" : The response reached max_output_tokens, which also holds the model’s reasoning. Raise it; see Set your output limit for reasoning models.

Next Steps

Images in Conversations

Choosing a model, switching models, image size, cost and reviewing uploads

Images In and Out

The concepts, which models read images, and image generation

Direct Responses: Multimodal

Image input, PDF input and image generation in the guide

Build with Direct Responses

Streaming, multi-turn, tool calls and error handling