n2 in the model field of your chat.completions requests.
n2 follows the OpenAI chat.completions interface. It exposes five tools — computer_batch for the GUI, edit / read / write for files, and bash for the shell — and returns its actions as tool_calls for your client to execute against the desktop.
Model Versions
Supported Actions
The default tool set iscomputer_use_tools-20260830. It contains five tools.
computer_batch
The one tool that drives the GUI. It runs a sequence of primitive actions in a single call and returns a screenshot after the last one, so it is both how the model acts and how it sees.
Each item in
actions is shaped {"name": <action>, "arguments": {...}}:
- Actions run sequentially, in order.
- Execution stops at the first error. Remaining actions are skipped — do not continue past a failure, and report which action failed in the tool result.
- All coordinates in a batch refer to the screenshot taken before the batch started, not to the state after any earlier action in the same batch.
Batch Actions
The current vocabulary has 15 primitive action types insidecomputer_batch. Coordinate-taking actions use the normalized 1000×1000 space. The Python SDK’s N2ComputerAgent accepts 1–20 actions in one batch.
Parameter notes:
coordinatesandstart_coordinatesare[x, y]integers in the normalized0–1000space, origin top-left.directionforscrollisupordown. Horizontal scrolling is not available.amountforscrollis an integer from1to50, measured in wheel notches.modifieris a single modifier key held for the duration of the action:ctrl,shift,alt,meta,command, orsuper. Execute it as one gesture — press, act, release. A modified click that degrades to a plain click is worse than an error, because actrl-click meant to extend a selection instead activates the target.durationforwaitandhold_keyis in seconds.mouse_downandmouse_upbracket a manual drag:mouse_move→mouse_down→mouse_move→mouse_up. The button stays held across the members between them, so execute them against real press/release primitives rather than synthesizing a click. Release anything still held when the batch ends.screenshottakes no arguments and acts on nothing. A batch already answers with a screenshot taken after its last action, so ascreenshotmember is a no-op you can skip; it exists because it is the only way the model can ask to look without acting.
bash
Runs a shell command on the desktop and returns combined stdout/stderr.
Each call is a separate process. The working directory persists across calls; environment variables and shell functions do not — chain dependent steps in one command with
&& or ;.
read
Reads a text file and returns it in cat -n format, with the encoding detected from the byte-order mark.
Relative paths resolve against the shell’s working directory. To look at an image, take a screenshot instead — the tool result channel is text.
write
Writes a file, creating it or replacing its contents.
Prefer this over a
bash heredoc for anything non-trivial: content rides as a JSON string, so it is never shell-escaped and a backtick or $ in the payload cannot corrupt the file.
edit
Replaces an exact string in an existing file.
The file has to be read (or written) earlier in the same session first — the model is expected to know the current bytes before changing them, and your executor should enforce that rather than editing blind.
Key Space
n2 uses lowercase key names. Combinations are joined with+, and sequential presses are separated by spaces.
Examples:
ctrl+c, ctrl+shift+t, alt+tab, down down down enter
Punctuation keys use their word forms — key_press with slash, not /. To enter punctuation as text, use type instead.
Coordinate System
n2 outputs normalized coordinates in a 1000×1000 space, origin top-left. Scale them to your desktop’s real pixel resolution before executing. The model is never told the resolution.yutori.navigator.coordinates for the inverse normalize_coordinates function.
Screenshots
Capture the whole screen, including window borders, title bars, the taskbar, and any system UI. n2 clicks on all of it, so cropping any of it away removes targets the model needs to see. n2 reports normalized coordinates. 1920×1080, 1280×720, and 1280×800 are all in regular use. Grounding may degrade at extreme aspect ratios. Requests are capped at 10 MB, returning HTTP413 (request_too_large) above that. Full-screen captures are large and a trajectory carries several, so compress them: WebP at ~80% quality, not PNG. A handful of uncompressed full-screen PNGs will exceed the cap on their own.
The Python SDK handles encoding:
yutori.navigator.images for resolution and quality options.
Request Fields
Supported alongsidemodel and messages:
Sampling
Applied whenever you send nothing for a field. An explicitnull counts as sending nothing:
temperature: 0 is not recommended for a reasoning model.
Rejected. n2 returns an error for these rather than silently ignoring them:
Each returns HTTP
400 with an OpenAI-shaped error body:
max_tokens is also rejected, but as a schema violation (HTTP 422) rather than a 400.
A rejected field sent as an empty value is dropped instead of rejected —
"tools": [] and
"response_format": {} are accepted as no-ops. Only a non-empty value returns a 400, so an
empty value is not a reliable way to probe whether a field is supported.prompt_cache_key is accepted and then dropped before the request reaches the model. Any field
outside the ones documented here is stripped rather than rejected — an unrecognized parameter will
not error, and will not take effect.
parallel_tool_calls is pinned to true server-side, so a value you send for it is ignored. In practice n2 answers with a single computer_batch call, which is how it chains actions against one screenshot — but it may return more than one call in a turn, and a loop has to handle that. The SDK’s N2ComputerAgent executes the first call and answers the rest with an error result, because they were planned against a screenshot that the first call has already changed. Whatever the policy, every call needs its own tool result.
Prompting
A system message you supply adds to n2’s defaults rather than replacing them, so a custom system prompt cannot override them — and extra behavioral instructions generally degrade results. Put task-specific instructions in the first user message, after the task description.Message History
Send the full conversation. Do not drop messages — the model needs its own action history to avoid repeating work. n2 retains screenshots at the message level: the last 2 image-bearing messages keep their images, capped at 6 images within each. Older images are dropped server-side with no marker; a short placeholder is inserted only when dropping them would leave a message with no content. In practice it means n2 sees the current screen and the previous one, which is why the previous screenshot should be a real observation rather than a stale duplicate. Send the full history regardless — the text of every earlier turn is kept, and it is what the model uses to know what it has already tried. A turn looks like this — assistant message with the batch call, then onetool result carrying the post-batch screenshot:
edit, read, write, and bash, return the tool’s result text or the command output the same way.
When n2 is done with the task it returns content text and no tool_calls — the signal to end the loop. You can append a new user message to continue from the same history.
Context and Compaction
The served context window is 128,000 tokens. Nothing on this endpoint compacts a conversation for you: the server drops older images (see Message History) but keeps the text of every turn, so a long trajectory grows until a request no longer fits. n2 is trained for long-horizon work with a compaction step, and reproducing it is what keeps a long run in distribution:
Once a response reports more than 53,760 prompt tokens, ask the model to write a checkpoint of the conversation so far, then replace the compacted turns with it and continue. A run that instead grows toward the full 128,000-token window is operating past the context the model was trained at.
The Python SDK does this by default —
N2ComputerAgent attaches an N2InlineCompactor unless you pass compactor=None. The compaction prompt and the reference implementation live in yutori/navigator/n2_compaction.py.
Reasoning
Reasoning is on by default, at medium effort. Setreasoning_effort to change it:
high and minimal are accepted as aliases for xhigh and low. Any other value falls back to medium. chat_template_kwargs is not accepted — reasoning_effort is the supported way to set this.
The trace comes back on the assistant message as reasoning_content, alongside content and tool_calls. Echo it back on the next call — append the assistant message unchanged, reasoning_content included — so the model keeps its own reasoning across turns:
max_completion_tokens.
Tool Sets
Published dated tool sets are immutable: an id always denotes the same tool definitions, and a new surface gets a new date.
The default is the current latest set (
computer_use_tools-20260830), and you can select a set explicitly with the tool_set field:
Changing the tool set
The set is a fixed, immutable list, but you can drop tools from it and add your own. The two compose:disable_tools is applied first, then your definitions in tools are appended
after the set’s.
Disabling a tool
Drop tools you cannot support. A host with no shell or no filesystem should say so rather than let the model call a tool that will always fail:bash, read, write, and edit can be disabled. computer_batch cannot — it is the GUI
surface, and without it there is no computer agent.
Unknown names are rejected rather than ignored, so a typo ("shell", "bash ") fails the call
instead of quietly serving the full set.
Adding custom tools
tools serves your own definitions alongside the set, in the standard OpenAI tool shape. Use it
to expose capabilities the predefined tool sets do not cover:
tool_set can also be redefined by first disabling the tool name and then
providing your own definition in tools. Adding a definition in tools with a conflicting
name to an existing tool in the tool_set will return a 400 if the original tool is not
first disabled:
computer_batch cannot be redefined at all, for the same reason it cannot be disabled. Duplicate
names within tools are rejected too.
Agent Loop
One turn: send the task and the newest screenshot, receive a tool call (usually one; see Request Fields for the case of several), execute it against the desktop, and send back one tool result per call — a screenshot forcomputer_batch, text for bash, read, write, and edit. Repeat until the model returns text with no tool_calls.
A few tips:
- Unpack the batch. Read
actionsand turn each{"name", "arguments"}item into one call against your input driver. - Denormalize coordinates against the screen resolution, per action, before executing it.
- Stop at the first error and report which action failed. Do not run the rest of the batch.
- Return one tool result per tool call, not one per action, with exactly one screenshot taken after the last executed action.
- Keep the payload under 10 MB by compressing screenshots.
- Compact long runs rather than growing to the full window — see Context and Compaction.
- End a capped run with a summary. If you cap the number of turns, spend the last one on a user message asking the model to stop and summarize its progress; a run cut off mid-trajectory otherwise returns no final answer.
The SDK exports
TOOL_SET_COMPUTER_USE_LATEST so you can pin the tool set without hardcoding a date string. It tracks the SDK release rather than the server default, so check the constant’s value in the version you install. See Tool Sets.