/v1/responses runs one episode per socket.
It reaches the same models and the same sessions as chat completions.
The API checks your key and payment once, at the handshake.
Connect
The
model in session.open must equal the model query parameter.
The API refuses a handshake with an HTTP status and the usual JSON error body:
Messages
You send text messages as JSON, and frames as binary messages.session.open also takes handoff, as in Handoff.
observation also takes action_horizon and num_inference_steps, as on chat completions.
A text message is at most 65,536 characters.
observation_id is optional: use 1 to 128 characters from A-Z a-z 0-9 . _ : -.
The API generates one if omitted and returns it on that observation’s actions or
error message. Use a fresh id per logical observation, and reuse it with identical
frames and controls when retrying. Supply expected_step, starting at zero, to reject
out-of-order observations. A repeated completed id returns its original answer with no
new execution or charge; different content conflicts. Concurrent duplicates share the
outstanding observation’s answer. Generated ids cannot protect retries after a lost reply.
Replay records have no expiry and survive gateway and engine restarts. Keep the same
public session_id and opening message when retrieving an answer on a new connection.
A stored answer does not restore the model’s lost episode. If an answer was never saved,
observation_outcome_unknown refuses re-execution; do not switch to a new id to bypass it.
Each connection admits at most 1,024 observation ids and buffers at most 16 MiB of frames;
a retained answer must fit 4 MiB. See HTTP retries.
session.opened
The server states the model’s contract. Build every later message from this reply.Frames
A frame message is binary. Its first byte is the camera index: 0 for the first camera incameras, 1 for the second, 2 for the third.
The remaining bytes are one JPEG, at most 262,144 bytes.
- Before the first observation, send
frames_per_camera_firstframes per camera. - Before every later observation, send
frames_per_camera_nextframes per camera. - Within one camera, send frames oldest first.
actions
The answer to an observation carries the same action chunk as a chat completion, plustype, id and usage:
action_horizon rows.
An abstract/dreamzero-astra:yam answer also carries cache and context, as on chat completions.
You can wait for each reply, or pipeline up to eight outstanding observations. Send all
frames for A, then observation A, then all frames for B, then observation B. Give each
observation its own id so you can match replies. The engine executes observations
sequentially in arrival order; pipelining does not run them concurrently. Each observation
has its own credit reservation and usage settlement. Socket ingress holds at most 16 MiB
and 128 messages while earlier messages are processed; exceeding either limit closes
the socket with message_too_large. Acknowledged observation ids remain protected by
durable replay records, so a long episode does not need to restart after 1,024 observations.
For stateful models, a failed observation does not advance the step. Later queued
observations are validated against the step that actually exists, so a failure on the
first observation can also make a queued continuation’s frame count invalid. Waiting for
each reply is simplest when recovering from errors. Your robot controller must decide
which returned actions remain applicable to its current state.
session.closed
{"type":"session.closed","session_id":"...","steps":3}.
steps counts the chunks the session produced.
The server then closes the socket with code 1000.
Errors
An error arrives as a text message:
Frame and session-control errors have no
observation_id and are not terminal answers to
other outstanding observations. Already queued observations can still return results.
On a close, unanswered observations settle at zero; previously completed ones retain their usage.
The close code tells you whose fault it was:
Errors and limits lists every code.
Lifetime
- One socket is one episode. Open a new socket for a new episode.
- After the first observation, a session that sends no observation for 60 seconds expires. The next observation gets
session_expiredwithclosing: true. - Closing the socket mid-chunk cancels the model call and ends the episode.
- Each observation is metered like one chat completion. See Usage and billing units.
Example
socket_episode.py
pip install websockets, then run it with ABSTRACT_API_KEY="$(abstract token)" python socket_episode.py.