Agents

Drive a computer through an OpenAI-shaped endpoint

The agent loop behind a door an OpenAI client already knows how to open, for callers who would rather point an existing client at a base URL than integrate a new one. Same loop and the same X-Model-Key behavior as the BYOK computer agent. This route always requires your own key; funded AI is unavailable here.

Four things are ours rather than OpenAI’s. computer_id on the body is required, and there is nowhere else to put it: this endpoint has no computer in its path. provider and max_steps are optional and mean what they mean on /computers/{id}/agent. And the response carries an agent block beside the OpenAI fields, saying what the loop did. Everything else reads the way an OpenAI client already writes it — the prompt is the last user message, the user and assistant messages before it are the conversation so far (given to the model as turns it is told are done), and any system messages become the system prompt. thread_id and store keep and continue a conversation as on /computers/{id}/agent; with thread_id the thread’s own turns are the conversation and earlier messages you send are not read, so resending the whole history each call is harmless. A new thread starts with the messages you sent, and its id comes back as agent.thread_id (on the last chunk when streaming). Only the documented top-level fields are accepted; unknown fields are a 400.

BESIDES THE KEY IT NEEDS, ONE BEHAVIOUR DIFFERS FROM THE ROUTE ABOVE, because this door follows OpenAI’s contract rather than ours: this endpoint does not stream unless you ask it to — omit stream and you get one JSON completion, which is the opposite of /computers/{id}/agent. model and provider choose the provider the same way on both routes; use a model that supports computer use, such as gpt-6.1-sol.

On the hosted API a run that does not stream — this endpoint’s default — is cut off at the edge after about 120 seconds (a 524 with no body), and its result, the usage and the steps it took, is lost with it. The run is stopped where it was once the dropped connection reaches the platform, so do not assume it finished. A run at the default max_steps can easily take longer: send stream: true for anything that may.

The computer must already be running — this endpoint will not start one for you, because starting is billable and not a decision to make on your behalf.

Requires the member role or higher.

post/chat/completions

Request

  • Base URL: https://app.mandala.computer/api/v1
  • URL: https://app.mandala.computer/api/v1/chat/completions
  • Auth: HTTP bearer

Headers

X-Model-Keystring required

Your own key for the selected Anthropic or OpenAI provider. Never stored. The provider bills you directly; no Mandala AI credits are spent. A key whose prefix belongs to the other provider (sk-ant- for OpenAI, any other sk- key for Anthropic) is a 400.

Request body

computer_idstring required

Which of your computers to drive. Required.

messagesobject[] required

OpenAI-shaped messages. The last user message is the prompt. Required.

provider'anthropic' | 'openai'

Optional provider. Inferred from claude-, gpt-, o-series and computer-use-preview model ids; defaults to Anthropic when neither is supplied. Required for an unknown model namespace. A recognized model/provider mismatch is refused. OpenAI requires X-Model-Key.

modelstring

A computer-capable Anthropic or OpenAI model id, passed to the selected provider unchanged. Defaults: claude-opus-5-5 for Anthropic, gpt-6.1-sol for OpenAI.

max_stepsinteger

How many actions the loop may take before it stops, as on POST /computers/{id}/agent — defaults to 20, and 100 is the most it accepts. A value past that is a 400. Not an OpenAI field; it is ours, and an OpenAI client that does not send it gets the default, as does null.

streamboolean

Send true for an event stream. This endpoint does not stream by default, so omitting it gives you one JSON body — the opposite of POST /computers/{id}/agent. Only the JSON booleans true and false change the default; any other value, the string "false" included, is read as if it were left out. On the hosted API a run that does not stream — this endpoint’s default — is cut off at the edge after about 120 seconds (a 524 with no body), and its result, the usage and the steps it took, is lost with it. The run is stopped where it was once the dropped connection reaches the platform, so do not assume it finished. A run at the default max_steps can easily take longer: send stream: true for anything that may.

thread_idstring

A thread to continue: thr_ and twenty-four hex characters, from an earlier run’s thread_id. Its earlier turns are given to the model as the conversation so far, and this run’s exchange is added to it. A thread of another computer is a 409, as is a full one (100 turns); one this key cannot see is a 404.

storeboolean

Whether to keep this run’s exchange in a thread. Default true: a run that does something is kept, in the thread you named or a new one, and its thread_id comes back on the result. false keeps nothing, and cannot be sent with thread_id.

Response

One ChatCompletion, or with stream: true an SSE stream of OpenAI-style chunks.

Each chunk is data: {id, object: "chat.completion.chunk", created, model: "computer-use-agent", choices: [{index: 0, delta, finish_reason}]}. The first chunk’s delta carries role: "assistant"; each action the loop takes arrives as a line of delta.content ([n] what it did), then the model’s text; the last chunk has an empty delta and the finish_reason described on ChatCompletionChoice. The stream carries no usage and no agent block, so a streamed run cannot tell a finished run from one that ran out of rate budget — send stream: false when that matters and the run is short enough. A run that fails arrives as data: {error, request_id} with the OpenAIErrorDetail shape under error. The stream ends with data: [DONE], and lines starting : carry nothing: a : run starting line first, then : keepalive lines while the run goes quiet.

idstring required

This run’s completion id, the same one every chunk of a streamed run carries.

object'chat.completion' required
createdinteger required

Unix seconds.

modelstring required

Always computer-use-agent: a fixed label for this loop, NOT the model that ran it — that is the model you sent, or our default.

Changes

No recorded changes to this operation across all 1 revision of this API.