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 namedanswer, 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 inmessage.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 asusage.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:
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 firstuser 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.