holo3-1-35b-a3b) and Holo3 (holo3-122b-a10b).
Read Core concepts first: reasoning, coordinates, observations, and the trim_to_last_n_images helper used below.
Output JSON
Each step, the model emits one object with three fields:string | null
The model’s durable memory: anything from the current screen that future steps will need (URLs, IDs, intermediate answers).
null when nothing new is worth recording.string
required
A one-line plan for the next action.
object
required
One variant of your tool union. Flat:
tool_name is a sibling of the arguments, not nested in an args object.Constrain output to a tool union
Define each tool as a Pydantic model with aLiteral[tool_name] field, then use their union as the response schema. The server’s constrained decoder ensures the model emits exactly one variant, and tool_name is the tag you dispatch on at execution time. The example ships three tools (click, write, answer) for illustration. Real agents register a wider toolbox following the same pattern.
<output_format> block (shown in the loop below). The model was trained with the schema visible in both the prompt and structured_outputs, and dropping either copy noticeably hurts reliability.
Chat layout
Tool results come back asuser messages wrapped in <tool_output tool="...">, not as OpenAI tool-role messages:
A complete loop
Pass the schema tostructured_outputs and parse content back into your models. Because tool_name is a discriminator, the parsed tool_call narrows to exactly one variant, which is what you dispatch on. Highlighted lines are the ones specific to structured outputs; everything else is the shared loop from Core concepts. Plug in your own screenshot() (browser, OS, emulator) and execute(...) dispatcher.
Format-specific pitfalls
Next steps
Element localization
Get click coordinates from a screenshot.
API reference
Endpoint, models, parameters, and limits.