This section as Markdown: View Download

WebSocket

Receive real-time task updates via a persistent WebSocket connection.

Connection URL

wss://socket.wiro.ai/v1

Connect to this URL after calling the Run endpoint. Use the socketaccesstoken from the run response to register your session.

Connection Flow

  1. Connect: open a WebSocket connection to wss://socket.wiro.ai/v1
  2. Register: send a task_info message with your tasktoken
  3. Receive: listen for messages as the task progresses through its lifecycle
  4. Close: disconnect after the task_postprocess_end event (this is the final event with results)

Registration message format:

{
  "type": "task_info",
  "tasktoken": "your-socket-access-token"
}

Message Types

Message Type Description
task_queue The task is queued and waiting to start.
task_accept The task was accepted and is preparing for execution.
task_preprocess_start Optional input preparation has started.
task_preprocess_end Input preparation completed.
task_assign Execution capacity was assigned and the model is preparing to start.
task_start Model execution started.
task_output The model is producing output. Emitted multiple times; LLM events carry the latest cumulative ordered message.segments snapshot.
task_error An interim diagnostic event. It is not terminal; continue listening for completion.
task_output_full Signals that output collection ended. Treat it as a lifecycle event.
task_error_full Signals that error-output collection ended. Treat it as a lifecycle event.
task_end Model execution ended. This is not the final success signal; wait for task_postprocess_end.
task_postprocess_start Final output preparation started.
task_postprocess_end Post-processing completed. Check success and exitCode (0 = success). The message array contains final outputs. This is the event to listen for.
task_cancel The task was cancelled (if queued) or killed (if running) by the user.

Message Format

Every WebSocket message is a JSON object with this base structure:

{
  "type": "task_accept",
  "id": "534574",
  "message": null,
  "result": true,
  "success": null,
  "terminal": false,
  "exitCode": null
}

The type field indicates the status. The message field varies by type: it's null for lifecycle events, a string or object for output events, and an array for the final result.

Use the top-level id to correlate server events with the submitted task.

Lifecycle Events

These events signal task state changes. The message field is null:

// task_accept, task_preprocess_start, task_preprocess_end,
// task_assign, task_start, task_end, task_postprocess_start
{
  "type": "task_assign",
  "id": "534574",
  "message": null,
  "result": true
}

Output Events

Standard models: message is a progress object or plain string:

// Progress output (image generation, video, etc.)
{
  "type": "task_output",
  "id": "534574",
  "message": {
    "type": "progressGenerate",
    "task": "Generate",
    "percentage": "60",
    "stepCurrent": "6",
    "stepTotal": "10",
    "speed": "1.2",
    "speedType": "it/s",
    "elapsedTime": "5s",
    "remainingTime": "3s"
  },
  "result": true
}

// Simple string output (when no progress format is detected)
{
  "type": "task_output",
  "id": "534574",
  "message": "Processing complete.",
  "result": true
}

LLM models: message.segments is the cumulative ordered output snapshot. Replace it on every event. The final active item's text grows as chunks arrive, so render it before completion; a new item appears when the output phase changes. See LLM & Chat Streaming for full details:

{
  "type": "task_output",
  "id": "534574",
  "message": {
    "type": "progressGenerate",
    "task": "Generate",
    "speed": "12.4",
    "speedType": "words/s",
    "segments": [
      { "type": "thinking", "text": "Let me analyze this..." },
      { "type": "answer", "text": "Quantum computing uses qubits..." }
    ],
    "finishreason": "stop",
    "usage": {
      "input_tokens": 18,
      "input_tokens_details": { "cached_tokens": 6 },
      "output_tokens": 11,
      "output_tokens_details": { "reasoning_tokens": 4 },
      "total_tokens": 29
    },
    "isThinking": false,
    "elapsedTime": "3s"
  },
  "result": true
}

message.segments is always the full accumulated snapshot. Text entries use thinking or answer. Tool-capable models can also emit function_call entries with arguments, or custom_tool_call entries with input; both include id, call_id, name, and status.

message.finishreason and message.usage are final-turn metadata and can be absent from earlier task_output snapshots:

  • finishreason is stop, tool_calls, length, content_filter, or error. Execute a tool only when its segment status is completed and the finish reason is tool_calls.
  • usage contains normalized token and server-tool counters. Input totals already include cache reads/writes; output totals already include reasoning. Do not add details to total_tokens, and use Task Detail totalcost for the billed amount.

Inspect finishreason after completion so truncation and content filtering are not mistaken for a normal stop.

Error Events

task_error is an interim diagnostic event, not a failure. It arrives while the task keeps running, usually because the model wrote to stderr. The stderr text is never exposed: message is an empty string, success stays null, and there is no error field. task_error_full has the same shape. Only task_postprocess_end reports the outcome:

{
  "type": "task_error",
  "id": "534574",
  "message": "",
  "result": true,
  "success": null,
  "terminal": false,
  "exitCode": null
}

Full Output Events

task_output_full and task_error_full are lifecycle signals. Continue listening for task_postprocess_end, or use authenticated POST /Task/Detail to retrieve the persisted task.

{
  "type": "task_output_full",
  "id": "534574",
  "message": "",
  "result": true
}

Final Result

task_postprocess_end is the event you should listen for. The message contains the outputs array:

// Standard model — file outputs with CDN URLs
{
  "type": "task_postprocess_end",
  "id": "534574",
  "message": [{
    "name": "0.png",
    "contenttype": "image/png",
    "size": "202472",
    "url": "https://cdn1.wiro.ai/.../0.png"
  }],
  "result": true,
  "success": true,
  "terminal": true,
  "exitCode": 0
}

// LLM model — structured raw content
{
  "type": "task_postprocess_end",
  "id": "534574",
  "message": [{
    "contenttype": "raw",
    "content": {
      "prompt": "Explain quantum computing",
      "segments": [
        { "type": "answer", "text": "Quantum computing uses qubits..." }
      ],
      "finishreason": "stop",
      "usage": {
        "input_tokens": 18,
        "output_tokens": 11,
        "total_tokens": 29
      }
    }
  }],
  "result": true,
  "success": true,
  "terminal": true,
  "exitCode": 0
}

Realtime Events

These events are exclusive to realtime models (voice conversation, text-to-speech, and speech-to-text):

// Session is ready — start sending audio (voice conversation, speech-to-text)
{
  "type": "task_stream_ready",
  "id": "534574",
  "result": true
}

// The model finished producing output for this turn
{
  "type": "task_stream_end",
  "id": "534574",
  "result": true
}

// Cost update per turn
{
  "type": "task_cost",
  "id": "534574",
  "turnCost": 0.002,
  "cumulativeCost": 0.012,
  "usage": { "input_tokens": 150, "output_tokens": 89 },
  "result": true
}

task_cost.usage is the provider-specific realtime usage payload for that turn. It is separate from the normalized structured finite-LLM message.usage contract described above and can omit total_tokens or detail objects.

Binary Frames

For realtime models that return audio (voice conversation and text-to-speech), the WebSocket may send binary frames containing raw audio data. Check if the received message is a Blob (browser) or Buffer (Node.js) before parsing as JSON.

Ending a Session

For realtime models that maintain a persistent session, send a task_session_end message to gracefully terminate:

{
  "type": "task_session_end",
  "tasktoken": "your-socket-access-token"
}

After sending this, wait for the task_postprocess_end event before closing the connection. This is the final event that contains the complete results.

Agent WebSocket Events

The same WebSocket connection also supports AI Agent real-time streaming. Instead of task_info, register with agent_info and an agenttoken to receive agent response events.

For full documentation on agent events (agent_subscribed, agent_output, agent_end, and more), see Agent WebSocket.