Skip to main content

The loop

Pick an output format

Single calls such as element localization take structured outputs on every model, and function calling on every model except Holo3. Pick one loop format and stay in it. The formats differ only in how you declare tools and read the output. The rest of this page applies to both.

Answer tool

Holo ends a task by calling a tool named answer, with its report in the content argument. Register it with your action tools, in both formats, and stop the loop when it is called. A step with no tool call is not a stop: append the message and keep looping.

Reasoning and request settings

Each call returns a thinking trace in message.reasoning and the action in content (or tool_calls). Holo is trained to plan before each step, so keep thinking on in agent loops:
Past reasoning is dropped between turns, so anything the model must remember goes in content. When you append the assistant message, push only the parsed output, never the reasoning.

Prompt caching

When a prompt starts with the same tokens as a recent request to the same model, such as a fixed system prompt or the growing history of an agent loop, the server reuses its work on that part. There is nothing to enable. The reused part is reported as usage.prompt_tokens_details.cached_tokens and billed at the cached input price. The rest of the prompt and all output are billed at the listed rates. Each model’s cached input price is in Models and in GET /v1/models as pricing.input_cache_read. Caching is best effort. Keep the stable part of the prompt at the start, and expect the count to vary between requests.

Coordinates in [0, 1000]

Send a screenshot at any size. Holo returns integer coordinates in [0, 1000], normalized to that image, origin top-left. (932, 880) is 93.2% across and 88% down: pixel (1342, 792) on a 1440 × 900 screenshot. Scale back with its dimensions:
Send and scale against the same image bytes: any resize, crop, or DPI mismatch misclicks. Pick one pixel unit (CSS or device) and keep it end to end.

Observations

An observation is what the agent sees after it acts. Agents without a screen (a code runner, or MCP tools) need nothing extra: the task is the first user message and each tool result goes back as a tool result. The rest of this section is for screen agents. Each step, send the current screenshot as a user message wrapped in <observation> tags:

Image budget

Keep at most the last 3 screenshots in context: more degrades accuracy. Replace older ones with a text placeholder and keep their <observation> wrapper. Call this helper after appending each observation. The function-calling and structured-output loops use it.

Common pitfalls