> ## Documentation Index
> Fetch the complete documentation index at: https://docs.archetypeai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Direct Query

> Run a natural-language query against a model, optionally grounded in uploaded files or inline data events

<Warning>
  This API endpoint is under active development and is subject to change.
</Warning>

## Overview

The `/query` endpoint runs a synchronous query against an Archetype model. The request is enqueued on the GPU Processing Queue (GPQ), routed to a worker node, and the final result is returned in the same HTTP response.

A query can be grounded in:

* **Uploaded files** — reference files by ID via `file_ids` after uploading them through the [Files API](/api-reference/files/upload). Supported file types: `.png`, `.jpg`, `.jpeg`, `.txt`, `.json`, `.csv`, `.mp4`.
* **Inline data events** — pass payloads directly via `events` (text, JSON, base64-encoded image, or numeric arrays) without a separate upload step.
* **Prompt only** — neither files nor events.

The `model` parameter selects what runs against your inputs. Two model families are currently exposed on `/query`:

* **Newton C language models** (`Newton::c2_...`) — text reasoning, structured-output generation, image understanding. Used in `archetypeai-swat-demo-direct-query`, `archetypeai-earthquake-demo`, `archetypeai-grid-demo`, and the operator-suggestion patterns documented in the [newton-query-prompting skill](https://github.com/archetypeai/archetypeai-agent-skills/tree/main/skills/newton-query-prompting). Examples on this page use `Newton::c2_4_7b_251215a172f6d7`; the newer `Newton::c2_5_8b_260413b723a9ab` is also available.
* **Omega encoders** (`OmegaEncoder::omega_embeddings_01`) — numeric-only. Returns embedding vectors instead of text. Used with `data.numeric_array` events to feed channel-first sensor windows; the response carries one 768-dim embedding per channel. Pattern documented in the [newton-machine-state-direct-query skill](https://github.com/archetypeai/archetypeai-agent-skills/tree/main/skills/newton-machine-state-direct-query).

The exact model identifiers available to your organization may differ — invalid values return `400 invalid_model_version`.

## Request

<ParamField body="model" type="string" required>
  Versioned model identifier such as `Newton::c2_4_7b_251215a172f6d7` (text +
  image reasoning) or `OmegaEncoder::omega_embeddings_01` (numeric encoder).
  Validated against the available model registry — invalid values return
  `400 invalid_model_version`. See [Overview](#overview) for the model families
  currently exposed on this endpoint.
</ParamField>

<ParamField body="query" type="string" required>
  The natural-language query to run against the model. For numeric-encoder
  models (Omega) this is typically `""` — pass the sensor window as a
  `data.numeric_array` event in `events` instead.
</ParamField>

<ParamField body="system_prompt" type="string" default="">
  Optional system prompt prepended to the query.
</ParamField>

<ParamField body="instruction_prompt" type="string" default="">
  Optional instruction prompt appended to the system prompt.
</ParamField>

<ParamField body="response_start_prompt" type="string" default="">
  Optional prefix used to seed the model's response.
</ParamField>

<ParamField body="template_name" type="string" default="">
  Optional named prompt template to apply server-side.
</ParamField>

<ParamField body="file_ids" type="string[]">
  File IDs returned by the [Files API](/api-reference/files/upload). Two
  gotchas worth knowing:

  1. **Use the `file_id` (filename) the upload response returned, not the
     `file_uid` (`fil_…`).** `/query` filters file types by extension on
     the `file_id` string — `fil_…` has no extension and is rejected as
     `unsupported_file_type`.
  2. **Newton text models see contents of `.png` / `.jpg` / `.jpeg` /
     `.txt` / `.json` injected into the prompt; `.csv` is the exception.**
     CSV uploads succeed and `/query` accepts the reference, but the file
     contents are not visible to the text-reasoning model (likely routed
     to the numeric ingestion path the LLM doesn't observe). As a
     workaround, rename the file to end with `.txt` before uploading, or
     pass the CSV contents as a `data.text` event instead. `.mp4` is
     accepted but Newton text
     checkpoints currently return polite refusals when asked to describe
     video frames — use the
     [Activity Monitor lens](https://github.com/archetypeai/archetypeai-agent-skills/tree/main/skills/newton-activity-monitor)
     for video analysis.
</ParamField>

<ParamField body="events" type="object[]">
  Inline data events in place of file uploads. See
  [Data Events](/core-concepts/streams/events/data-events) for the supported
  event types: `data.text`, `data.json`, `data.base64_img`,
  `data.base64_img_array`, `data.numeric_array`. For `data.json`, set
  `event_data.contents` to a serialized JSON **string** (passing a parsed
  object returns `400 invalid_parameter_type`).
</ParamField>

<ParamField body="max_new_tokens" type="integer" default="256">
  Maximum tokens to generate in the response.
</ParamField>

<ParamField body="max_frames" type="integer" default="32">
  Maximum video frames to sample when an `.mp4` file is supplied via `file_ids`.
</ParamField>

<ParamField body="temperature" type="number">
  Sampling temperature. Omit to use the model default.
</ParamField>

<ParamField body="do_sample" type="boolean">
  Whether to use sampling instead of greedy decoding.
</ParamField>

<ParamField body="repetition_penalty" type="number">
  Penalty for repeating tokens already produced.
</ParamField>

<ParamField body="top_p" type="number">
  Nucleus sampling cutoff.
</ParamField>

<ParamField body="top_k" type="integer">
  Top-k sampling cutoff.
</ParamField>

<ParamField body="presence_penalty" type="number">
  Penalty for tokens already present in the prompt.
</ParamField>

<ParamField body="normalize_input" type="boolean" default="false">
  Apply server-side input normalization. For numeric-encoder models (Omega),
  this z-scores each `data.numeric_array` event **per window** before
  encoding. That preserves cross-channel comparability but erases
  cross-window amplitude signal — typically the wrong default for
  anomaly-detection workloads. Leave `false` and pre-normalize with a
  global scaler if cross-window magnitudes carry meaning. Has no effect
  on text-reasoning models.
</ParamField>

<ParamField body="multi_image" type="boolean" default="false">
  When true, treat multiple `file_id`s / image events as a single multi-image
  input rather than independent inputs.
</ParamField>

<ParamField body="render" type="boolean" default="false">
  When true, retains rendered intermediate artifacts on the server. The
  retrieval endpoint for these artifacts is not exposed on `/v0.5`; leave
  this `false` unless instructed otherwise.
</ParamField>

<ParamField body="query_metadata" type="object">
  Free-form metadata stored alongside the query for the caller's own bookkeeping.
</ParamField>

<ParamField body="max_query_size_mb" type="number">
  Override the maximum combined prompt size in MB. Defaults to the server's
  `MAX_QUERY_SIZE_MB` setting (typically 0.04 MB).
</ParamField>

<ParamField body="max_wait_time_sec" type="number">
  Override the maximum time to wait for a synchronous result before returning
  a `504`.
</ParamField>

<ParamField body="sanitize_response" type="boolean" default="true">
  When true, strips internal fields (`api_key`, `org_id`, `query_metadata`,
  `file_ids`, `data_types`, `render`, `input_items`, `sanitize`) from the
  response. Set to `false` only if you need to inspect the raw query record.
</ParamField>

## Response

<ResponseField name="query_id" type="string">
  Server-generated identifier for this query. Include it when reporting issues
  to support so the platform team can correlate to server logs.
</ResponseField>

<ResponseField name="status" type="string">
  Terminal status — `completed` for successful queries, `failed` if the worker
  returned an error.
</ResponseField>

<ResponseField name="response" type="object">
  Structured payload from the worker. The primary model output is the array
  at `response.response` (typically one or more strings). The remaining fields
  echo the prompt inputs (`query`, `prompt`, `system`, `instruction`) and
  per-stage timing (`generation_latency`, `query_gpq_latency`,
  `query_queue_latency`, `results_timestamp`, `prefetch_stats`) for debugging.
</ResponseField>

<ResponseField name="query_timestamp" type="number">
  Unix timestamp when the query was submitted.
</ResponseField>

<ResponseField name="loading_timestamp" type="number">
  Unix timestamp when data loading began.
</ResponseField>

<ResponseField name="inference_timestamp" type="number">
  Unix timestamp when inference began.
</ResponseField>

<ResponseField name="response_timestamp" type="number">
  Unix timestamp when the response was finalized.
</ResponseField>

<ResponseField name="query_queue_time_sec" type="number">
  Seconds spent in the queue before processing began.
</ResponseField>

<ResponseField name="inference_time_sec" type="number">
  Seconds spent on inference.
</ResponseField>

<ResponseField name="query_response_time_sec" type="number">
  End-to-end latency from submission to response.
</ResponseField>

<ResponseField name="gpq_node" type="string">
  Identifier of the GPQ worker node that processed the query.
</ResponseField>

<ResponseField name="error_messages" type="string[]">
  Plain-string error log accumulated by GPQ during query processing. Only
  present when GPQ has appended at least one message — successful queries
  typically omit this field entirely.
</ResponseField>

<ResponseField name="error_msg" type="string">
  Single error string set by GPQ only when `status` is `failed`.
</ResponseField>

<Note>
  Non-2xx responses (400, 429, 504) are reduced to an `{ "errors": [...] }`
  envelope by the shared API response wrapper — fields like `query_id`,
  `status`, and timing data are stripped. 401 responses are rendered as
  `{ "detail": "..." }` by FastAPI. See [Errors](/api-reference/errors)
  for the shared `AtaiError` shape.
</Note>

<RequestExample>
  ```bash Text — structured-output reasoning theme={"system"}
  # The canonical archetypeai-swat-demo-direct-query pattern: the entire state
  # snapshot is rendered into `query` as natural language, with a strict
  # system prompt that enforces JSON output shape. No file uploads.
  curl -X POST https://api.u1.archetypeai.app/v0.5/query \
    -H "Authorization: Bearer $ATAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "Newton::c2_4_7b_251215a172f6d7",
      "query": "Current plant state:\n- P1 raw intake: NORMAL\n- P3 ultrafiltration: ATTACK (LIT301=800.16, z=1.5)\n\nReturn one JSON card per anomalous stage.",
      "system_prompt": "Return ONLY a JSON array of {origin,target,direction,text} objects.",
      "instruction_prompt": "Return ONLY a JSON array of {origin,target,direction,text} objects.",
      "file_ids": [],
      "max_new_tokens": 700,
      "sanitize_response": false
    }'
  ```

  ```bash Image — describe an uploaded screenshot theme={"system"}
  # Upload returns { "file_id": "dashboard.png", "file_uid": "fil_..." }.
  # Pass the *file_id* (filename) in file_ids — the file_uid (fil_...) is
  # rejected as `unsupported_file_type` because the API filters by extension.
  curl -X POST https://api.u1.archetypeai.app/v0.5/query \
    -H "Authorization: Bearer $ATAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "Newton::c2_4_7b_251215a172f6d7",
      "query": "Describe what you see. Identify any stages flagged as anomalous.",
      "file_ids": ["dashboard.png"],
      "max_new_tokens": 400,
      "sanitize_response": false
    }'
  ```

  ```bash JSON — analyze an uploaded JSON file theme={"system"}
  # .json and .txt files have their contents injected into the prompt
  # context automatically. Upload first via /v0.5/files (with mime
  # `text/plain` — the file extension is what the rest of the pipeline
  # checks), then reference by filename.
  curl -X POST https://api.u1.archetypeai.app/v0.5/query \
    -H "Authorization: Bearer $ATAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "Newton::c2_4_7b_251215a172f6d7",
      "query": "What is the status field and which sensor has the highest value?",
      "file_ids": ["plant_state.json"],
      "max_new_tokens": 250,
      "sanitize_response": false
    }'
  ```

  ```bash Numeric — Omega embedding of a sensor window theme={"system"}
  # Channel-first window: outer array = N channels, inner arrays = window_size
  # values per channel. Response carries one 768-dim embedding per channel,
  # at response.response[i].
  curl -X POST https://api.u1.archetypeai.app/v0.5/query \
    -H "Authorization: Bearer $ATAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "OmegaEncoder::omega_embeddings_01",
      "query": "",
      "normalize_input": false,
      "events": [
        {
          "type": "data.numeric_array",
          "event_data": {
            "contents": [
              [2.53, 2.52, 2.53, 2.54],
              [574.2, 575.1, 576.0, 577.3]
            ]
          }
        }
      ]
    }'
  ```

  ```python Python theme={"system"}
  import os
  import requests

  api_key = os.environ["ATAI_API_KEY"]

  response = requests.post(
      "https://api.u1.archetypeai.app/v0.5/query",
      headers={
          "Authorization": f"Bearer {api_key}",
          "Content-Type": "application/json",
      },
      json={
          "model": "Newton::c2_4_7b_251215a172f6d7",
          "query": "Describe what you see in this dashboard.",
          "file_ids": ["dashboard.png"],
          "max_new_tokens": 400,
          "sanitize_response": False,
      },
  )

  result = response.json()

  if response.status_code == 200 and result.get("status") == "completed":
      # The model's text output is at result["response"]["response"][0].
      # For Omega numeric encoders the same path holds an array of
      # per-channel 768-dim embeddings instead of a string.
      print(result["response"]["response"][0])
  else:
      print(f"Error ({response.status_code}):", result.get("errors"))
  ```

  ```javascript JavaScript theme={"system"}
  const response = await fetch('https://api.u1.archetypeai.app/v0.5/query', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.ATAI_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'Newton::c2_4_7b_251215a172f6d7',
      query: 'Describe what you see in this dashboard.',
      file_ids: ['dashboard.png'],
      max_new_tokens: 400,
      sanitize_response: false
    })
  });

  const result = await response.json();

  if (response.ok && result.status === 'completed') {
    // The model's text output is at result.response.response[0].
    // For Omega numeric encoders the same path holds an array of
    // per-channel 768-dim embeddings instead of a string.
    console.log(result.response.response[0]);
  } else {
    console.error(`Error (${response.status}):`, result.errors);
  }
  ```
</RequestExample>

<ResponseExample>
  ```json 200 - Newton text reasoning theme={"system"}
  {
    "query_id": "260519c33f8455cddda9a8",
    "status": "completed",
    "query_timestamp": 1779157948.572,
    "loading_timestamp": 1779157948.608,
    "inference_timestamp": 1779157948.630,
    "response_timestamp": 1779157956.404,
    "query_queue_time_sec": 0.035,
    "inference_time_sec": 7.774,
    "query_response_time_sec": 7.831,
    "gpq_node": "",
    "response": {
      "success": true,
      "response": [
        "The image appears to be a screenshot from a software interface designed for monitoring and analyzing a six-stage water treatment process..."
      ],
      "query": "Describe what you see. Identify any stages flagged as anomalous.",
      "prompt": "Describe what you see. Identify any stages flagged as anomalous.",
      "system": "...",
      "instruction": "...",
      "generation_latency": 7.77,
      "query_gpq_latency": 7.83,
      "query_queue_latency": 0.05,
      "results_timestamp": "20260519_02:32:36",
      "prefetch_stats": { "loading_time": 0.012 }
    }
  }
  ```

  ```json 200 - Omega numeric encoder theme={"system"}
  {
    "query_id": "260518ba9e70f220c2dc48",
    "status": "completed",
    "inference_time_sec": 0.35,
    "query_response_time_sec": 0.41,
    "gpq_node": "",
    "response": {
      "success": true,
      "response": [
        [-0.375, 0.607, -0.733, "..."],
        [-0.412, 0.193, -0.886, "..."]
      ]
    }
  }
  ```

  ```json 400 - Missing required parameter theme={"system"}
  {
    "errors": [
      {
        "code": "missing_parameter",
        "message": "Failed to find key: model",
        "suggestion": "Resubmit your query with the expected parameters.",
        "error_uid": "err-260506a1b2c3d4"
      }
    ]
  }
  ```

  ```json 400 - Invalid model theme={"system"}
  {
    "errors": [
      {
        "code": "invalid_model_version",
        "message": "Failed to validate the model_version: newton-1",
        "suggestion": "Check to ensure the model is mounted and ready.",
        "error_uid": "err-260506b2c3d4e5"
      }
    ]
  }
  ```

  ```json 400 - Unsupported file type theme={"system"}
  {
    "errors": [
      {
        "code": "unsupported_file_type",
        "message": "Found unsupported file type with file: fil_526q1cy4nj9rrvtkgqe03mz8n6",
        "suggestion": "Supported file types are ['.png', '.jpg', '.jpeg', '.txt', '.json', '.csv', '.mp4']",
        "error_uid": "err-260506c3d4e5f6"
      }
    ]
  }
  ```

  ```json 401 - Unauthorized theme={"system"}
  {
    "detail": "Invalid access for key: "
  }
  ```

  ```json 429 - Capacity reached theme={"system"}
  {
    "errors": [
      {
        "code": "gpq_capacity_reached",
        "message": "Failed to submit query, GPQ capacity reached!",
        "suggestion": "Try again later when there is more capacity or add more GPUs to the fleet.",
        "error_uid": "err-260506d4e5f6a7"
      }
    ]
  }
  ```

  ```json 504 - Timeout theme={"system"}
  {
    "errors": [
      {
        "code": "query_timeout",
        "message": "Response timed out after 60.0 seconds for query: 260506a1b2c3d4e5f6",
        "suggestion": "Try again later when there is more capacity or add more GPUs to the fleet.",
        "error_uid": "err-260506e5f6a7b8"
      }
    ]
  }
  ```
</ResponseExample>
