> ## Agent Instructions > Start with /introduction/getting-started. Use the Direct Query API (POST /query) with the Newton Fusion model (text, image, and video reasoning) or the Newton Omega encoder (time-series embeddings). ATAI_API_ENDPOINT must include the version path: /v0.5 for most APIs, /v0.6 for the Fine-Tuning Service. Pages whose descriptions are marked (Archived) document the legacy Lens runtime — do not use them for new projects. # About the Agents API Source: https://docs.archetypeai.app/api-reference/agents/about An API to manage, create, and run agents against your data. The Agents API provides actions that manage blueprints, from which agent bundles are created; agent bundles, from which agents are created; and agents, which analyze the data you provide using configurations established by the blueprints on which they're based. For details about agents and their role in the Archetype platform ecosystem, see [this overview about agents](/core-concepts/agents/overview), which also provides information about the platform-provided blueprints. # Create Blueprint Source: https://docs.archetypeai.app/api-reference/agents/blueprints/create-blueprint POST /agents/blueprints Register a new blueprint, or a new version of an existing key Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint registers a blueprint under a human-readable **key** and returns the stored blueprint with its assigned `blp_` ID. Supply the blueprint as a JSON `document`, as a `yaml_document`, or as both. Set `replacement_of` to re-point an existing key at a new version; the previous blueprint is archived and flagged inactive, and bundles and agents pinned to it keep resolving it by ID. ## Request Human-readable blueprint key as shown in the table below. The reference users put in agent configurations. A service-level catalog key (not part of the `agent_core` blueprint). | Blueprint Key | Blueprint Name | | - | - | | `mga` | Manual Generation Agent | | `osm` | Operational State Monitoring Agent | | `red` | Rare Event Detection Agent | | `tva` | Task Verification Agent | The blueprint document, in the `agent_core` shape. It carries the blueprint's own `name`/`description` and its `values`/`bundles`, the `connectors`/`nodes` id-keyed node maps, and a `graph` of edges. Any `blueprint_id` in the document is ignored — the service assigns one on store. **Optional:** Provide this parameter, `yaml_document`, or both. When only `yaml_document` is given, the document is parsed from it. When both are given, they must describe the same blueprint. A YAML rendering of the blueprint (the same shape as `document`). Stored verbatim so authored comments/formatting are preserved and returned by the get endpoint. **Optional:** Provide this parameter, `document`, or both. When only this is provided, `document` is parsed from it; when both this parameter and `document` are provided, they must describe the same blueprint. Set to `true` to publish a platform-authored (gallery) blueprint visible to every org; this requires the super-admin grant. Defaults to `false`, registering it under the caller's organization (which requires the admin role). Replacement mode: the `blp_` id of the blueprint currently holding `blueprint_key`, which this request re-points to a new version. The previous blueprint is archived under `-` and flagged inactive; existing bundles/agents keep resolving it by id. Must be the current active holder of `blueprint_key` in the same scope (`canonical` or not); omit to create a blueprint under a new and unique key. ### Blueprint document The blueprint's edges: `{"edges": [{"from": "", "to": ""}]}`. ID-keyed map of source/sink nodes. Each entry is `{"key": "", "config": {...}}`, where `key` is a node key from the node registry. Defaults to empty. ID-keyed map of every non-connector node, in the same entry shape as `connectors`. Defaults to empty. The blueprint's own name. The blueprint's own description. The blueprint's default values. The blueprint's models. Map of artifact name to artifact reference (string values). Optional metrics catalog: the objectives an eval can score this blueprint against, the recommended primary, the node whose output it scores, and family-specific scoring metadata. A blueprint publishes at most one catalog; one publishing none cannot be evaluated or optimized. See [Get Blueprint](/api-reference/agents/blueprints/get-blueprint) for the full shape. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Ignored on create — the service assigns the id when it stores the blueprint. ## Response Returns the stored blueprint. TypeID-encoded blueprint identifier (`blp_` prefix). The key this blueprint was registered under. Name of the blueprint. Description of the blueprint. The blueprint document, in the `agent_core` shape — the same format accepted on create, now carrying the assigned `blueprint_id`. The YAML rendering of the blueprint, when included. Present when one was stored (or requested via `?yaml=true`); omitted otherwise. True for platform-authored (gallery) blueprints shared with every org; false for blueprints owned by a specific org. True for the current version of a key; false once it has been replaced by a newer blueprint (its key was archived to `-`). Bundles/agents pinned to an inactive blueprint keep working — the console can badge them. Where this blueprint came from, when it was not authored directly. Omitted for an authored blueprint, so it is absent on a blueprint created through this endpoint. See [Get Blueprint](/api-reference/agents/blueprints/get-blueprint). [v1.1.12+](/release-notes/1.1.x#v1-1-12) Creation timestamp (date-time). ```bash cURL - JSON Document theme={"system"} curl -X POST "$ATAI_API_URL/agents/blueprints" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "blueprint_key": "osm", "document": { "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "connectors": { "input": {"key": "", "config": {}}, "output": {"key": "", "config": {}} }, "nodes": { "classifier": {"key": "", "config": {}} }, "graph": { "edges": [ {"from": "input", "to": "classifier"}, {"from": "classifier", "to": "output"} ] }, "values": {}, "artifacts": {} } }' ``` ```bash cURL - New Version Of A Key theme={"system"} curl -X POST "$ATAI_API_URL/agents/blueprints" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "blueprint_key": "osm", "replacement_of": "blp_01jc8k2m9vr4te7hn5b3qdzx8w", "yaml_document": "name: Open-set monitor\ngraph:\n edges: []\n" }' ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/blueprints", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "blueprint_key": "osm", "document": { "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "connectors": { "input": {"key": "", "config": {}}, "output": {"key": "", "config": {}}, }, "nodes": { "classifier": {"key": "", "config": {}}, }, "graph": { "edges": [ {"from": "input", "to": "classifier"}, {"from": "classifier", "to": "output"}, ] }, }, }, ) if response.status_code == 201: blueprint = response.json() print(f"Created {blueprint['id']} under key {blueprint['blueprint_key']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch(`${process.env.ATAI_API_URL}/agents/blueprints`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ blueprint_key: 'osm', document: { name: 'Open-set monitor', description: 'Classifies incoming records against a known class vocabulary.', connectors: { input: { key: '', config: {} }, output: { key: '', config: {} } }, nodes: { classifier: { key: '', config: {} } }, graph: { edges: [ { from: 'input', to: 'classifier' }, { from: 'classifier', to: 'output' } ] } } }) }); const body = await response.json(); if (response.status === 201) { console.log(`Created ${body.id} under key ${body.blueprint_key}`); } else { console.error('Error:', body.errors); } ``` ```json 201 - Created theme={"system"} { "id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "blueprint_key": "osm", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "document": { "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "connectors": { "input": {"key": "", "config": {}}, "output": {"key": "", "config": {}} }, "nodes": { "classifier": {"key": "", "config": {}} }, "graph": { "edges": [ {"from": "input", "to": "classifier"}, {"from": "classifier", "to": "output"} ] }, "values": {}, "artifacts": {} }, "yaml_document": null, "is_canonical": false, "is_active": true, "created_at": "2026-08-11T14:32:07Z" } ``` ```json 400 - Invalid request theme={"system"} { "errors": [ { "code": "", "message": "Invalid request, or `replacement_of` does not match the given key/scope.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 403 - Admin role required theme={"system"} { "errors": [ { "code": "", "message": "Admin role required (super-admin required for canonical blueprints).", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - replacement_of blueprint not found theme={"system"} { "errors": [ { "code": "", "message": "`replacement_of` blueprint not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Key or version conflict theme={"system"} { "errors": [ { "code": "", "message": "Blueprint key already exists, or `replacement_of` is no longer the active version.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Creating a blueprint requires the admin role; `canonical: true` requires the super-admin grant. * Omit `replacement_of` to create a blueprint under a new and unique key; a key that already exists returns `409`. * `replacement_of` must name the current active holder of `blueprint_key` in the same scope (canonical or org-owned). * Node keys used in `connectors` and `nodes` come from the node registry — see `GET /agents/nodes/registry`. * Give the document a `metrics` catalog if the blueprint is to be evaluated with `POST /agents/evals` or searched with `POST /agents/optimizations`; a blueprint publishing none cannot be scored. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * Every version registered under a key stays readable — list them with `GET /agents/blueprints/{reference}/versions`. [v1.1.12+](/release-notes/1.1.x#v1-1-12) # Delete Blueprint Source: https://docs.archetypeai.app/api-reference/agents/blueprints/delete-blueprint DELETE /agents/blueprints/{reference} Delete a blueprint by id or key Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint deletes a blueprint, addressed either by its `blp_` id or by its key. A blueprint that is still pinned by a bundle cannot be deleted — delete the referencing bundles first. ## Request Blueprint `blp_` id or key (e.g. `osm`). ## Response Returns `204 No Content` with an empty body on success. ```bash cURL theme={"system"} curl -X DELETE "$ATAI_API_URL/agents/blueprints/blp_01jc9n7k3xf8mbq2v5t0ary6de" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.delete( f"{base_url}/agents/blueprints/blp_01jc9n7k3xf8mbq2v5t0ary6de", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 204: print("Blueprint deleted") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/blueprints/blp_01jc9n7k3xf8mbq2v5t0ary6de`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); if (response.status === 204) { console.log('Blueprint deleted'); } else { const body = await response.json(); console.error('Error:', body.errors); } ``` ```json 204 - Blueprint deleted theme={"system"} ``` ```json 400 - Invalid reference theme={"system"} { "errors": [ { "code": "", "message": "Invalid reference.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 403 - Admin role required theme={"system"} { "errors": [ { "code": "", "message": "Admin role required (super-admin required for canonical blueprints).", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Blueprint not found theme={"system"} { "errors": [ { "code": "", "message": "Blueprint not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Still referenced by a bundle theme={"system"} { "errors": [ { "code": "", "message": "Blueprint is still referenced by a bundle.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Deleting a blueprint requires the admin role; deleting a canonical blueprint requires super-admin. * A `409` means at least one bundle still pins this blueprint. Delete those bundles first. * Success returns `204` with no body — check the status code rather than parsing a response. # Get Blueprint Source: https://docs.archetypeai.app/api-reference/agents/blueprints/get-blueprint GET /agents/blueprints/{reference} Retrieve a single blueprint, including its full document Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns one blueprint, addressed either by its immutable `blp_` id or by its key. Unlike the list endpoint, the response carries the full blueprint `document`, and optionally its YAML rendering. ## Request Blueprint `blp_` id or key (e.g. `osm`). Controls the `yaml_document` in the response. Omitted: include the stored YAML if one exists. `true`: always include, generating it from the document when none is stored. `false`: never include. ## Response TypeID-encoded blueprint identifier (`blp_` prefix). Human-readable key for the blueprint, e.g. `osm`. Name of the blueprint. Description of the blueprint. The blueprint document, in the `agent_core` shape — the same format accepted on create, now carrying the assigned `blueprint_id`. The YAML rendering of the blueprint, when included. Present when one was stored (or requested via `?yaml=true`); omitted otherwise. See the `yaml` query parameter. True for platform-authored (gallery) blueprints shared with every org; false for blueprints owned by a specific org. True for the current version of a key; false once it has been replaced by a newer blueprint (its key was archived to `-`). Bundles/agents pinned to an inactive blueprint keep working — the console can badge them. Where this blueprint came from, when it was not authored directly. Omitted for an authored blueprint. It names the blueprint that was customized and the exact overrides applied to it, so the derived blueprint's ancestry stays readable even after whatever produced it has been deleted. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Creation timestamp (date-time). ### Source object (`source`) [v1.1.12+](/release-notes/1.1.x#v1-1-12) The blueprint this one was derived from. Parameter value overrides applied on top of that blueprint's own. Model slot overrides applied on top of that blueprint's own. Artifact locations applied on top of that blueprint's own, keyed by artifact name. What produced this blueprint, as an id pair plus an optional label. The `id` prefix says what kind of thing it was: `otr_` is an optimization trial, whose `parent_id` is then the optimization run it belonged to. * `id` (string, required) — the producer itself; an `otr_` id for an optimization trial. * `parent_id` (string, required) — the run the producer belonged to; an `opt_` id for an optimization trial. * `name` (string) — the human label of the enclosing run, when one was given to it. ### Blueprint document fields The blueprint's edges: `{"edges": [{"from": "", "to": ""}]}`. The assigned blueprint id, echoed inside the document. Id-keyed map of source/sink nodes. Each entry is `{"key": "", "config": {...}}`. Id-keyed map of every non-connector node, in the same entry shape as `connectors`. The blueprint's own name. The blueprint's own description. The blueprint's default values. The blueprint's models. Map of artifact name to artifact reference (string values). Optional metrics catalog: what an eval may score this blueprint against, as the blueprint itself publishes it. A blueprint publishing none cannot be evaluated. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * `primary` (string, required) — the run's headline, as `.`, naming a declared target and one of its objectives. Also the objective an optimization maximizes by default. * `targets` (array) — the targets this blueprint can be scored on. Exactly one is supported today. ### Metrics target (`document.metrics.targets[]`) [v1.1.12+](/release-notes/1.1.x#v1-1-12) One thing the agent decides, and the unit an eval scores. The target's name. Identifies it in the metrics report, in an eval request's `targets` overrides, and in each input's own declarations — where it is also the default name of the column the labels are read from. The target's type. `category` — exactly one of N mutually exclusive classes per scored unit. Every objective an eval may compute for this target: `macro_f1`, `accuracy`. Must be non-empty. Where this target's decision is in the agent's output — the named output column that holds it. For a `category` target, the classes it predicts. A blueprint rarely knows them literally: they can be written as a `${…}` reference that is substituted only when the blueprint is resolved. How this target's scored items are formed: what one scored thing is, and how a prediction is matched to the ground truth it is compared against. Two wire forms — the bare name (`pairing: by_time`) when every parameter defaults, and a single-key map (`pairing: {"by_time": {"downsampling": "majority_vote"}}`) when one does not. ```bash cURL - By Key theme={"system"} curl "$ATAI_API_URL/agents/blueprints/osm" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - By Id, With YAML theme={"system"} curl "$ATAI_API_URL/agents/blueprints/blp_01jc9n7k3xf8mbq2v5t0ary6de?yaml=true" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.get( f"{base_url}/agents/blueprints/osm", headers={"Authorization": f"Bearer {api_key}"}, params={"yaml": "true"}, ) if response.status_code == 200: blueprint = response.json() print(f"{blueprint['name']} ({blueprint['id']}), active={blueprint['is_active']}") print(blueprint.get("yaml_document")) else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/blueprints/osm?yaml=true`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`${body.name} (${body.id}), active=${body.is_active}`); console.log(body.yaml_document); } else { console.error('Error:', body.errors); } ``` ```json 200 - Success theme={"system"} { "id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "blueprint_key": "osm", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "document": { "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "connectors": { "input": {"key": "", "config": {}}, "output": {"key": "", "config": {}} }, "nodes": { "classifier": {"key": "", "config": {}} }, "graph": { "edges": [ {"from": "input", "to": "classifier"}, {"from": "classifier", "to": "output"} ] }, "values": {}, "artifacts": {}, "metrics": { "primary": "state.macro_f1", "targets": [ { "name": "state", "type": "category", "labels": "${models.classifier.parameters.states}", "objectives": ["macro_f1", "accuracy"], "predicted": "predicted_state", "pairing": "by_time" } ] } }, "yaml_document": "name: Open-set monitor\ngraph:\n edges: []\n", "is_canonical": true, "is_active": true, "created_at": "2026-08-11T14:32:07Z" } ``` ```json 200 - Promoted from an optimization trial theme={"system"} { "id": "blp_01jcb3r7n8k5wq2vt6y0mdhx4s", "blueprint_key": "osm-otr-01jcb2v9h4x7mq3nt8k5rdzy6w", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "document": { "blueprint_id": "blp_01jcb3r7n8k5wq2vt6y0mdhx4s", "name": "Open-set monitor", "graph": {"edges": []}, "values": {"window_size": 512}, "artifacts": {"fit-classifier": "s3://.../fit-classifier"} }, "yaml_document": null, "is_canonical": false, "is_active": true, "source": { "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "values": {"window_size": 512}, "models": {}, "artifacts": {"fit-classifier": "s3://.../fit-classifier"}, "created_by": { "id": "otr_01jcb2v9h4x7mq3nt8k5rdzy6w", "parent_id": "opt_01jcb1m3t7v5xq8nr2h6kdzs4w", "name": "Window size sweep" } }, "created_at": "2026-09-18T11:24:03Z" } ``` ```json 400 - Invalid reference theme={"system"} { "errors": [ { "code": "", "message": "Invalid reference.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Blueprint not found theme={"system"} { "errors": [ { "code": "", "message": "Blueprint not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * `reference` accepts either a `blp_` id or a blueprint key, so the same URL shape works for both. * Ask for `?yaml=true` when you want YAML even for a blueprint that was created from JSON — the service renders it from the document. * A blueprint with `is_active: false` has been replaced by a newer version of its key; it remains readable by id. * List every version of a key with `GET /agents/blueprints/{reference}/versions`. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * `source` is present only on a derived blueprint — one promoted from an optimization trial, for example — and records the blueprint that was searched together with the overrides applied to it. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * A blueprint without a `metrics` catalog in its document cannot be evaluated or optimized. [v1.1.12+](/release-notes/1.1.x#v1-1-12) # List Blueprint Versions Source: https://docs.archetypeai.app/api-reference/agents/blueprints/list-blueprint-versions GET /agents/blueprints/{reference}/versions Page through every version registered under one blueprint key Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint returns all versions of one blueprint key as a cursor-paginated page of blueprint summaries, newest first. Each time a key is re-pointed at a new version with `replacement_of`, the previous blueprint is archived under `-` and flagged inactive. This endpoint walks that history: the current active version plus every archived one. `reference` accepts either the key itself or a `blp_` id, which is resolved to its key first — so any version of a key is a valid way to ask for all of them. ## Request Blueprint key (e.g. `osm`) or a `blp_` id (resolved to its key). Page size. Minimum `1`, maximum `1000`. Forward cursor: return versions older than the one with this id. Pass the `next_cursor` of the previous page (or the id of its last version) to fetch the next page. Mutually exclusive with `before`. Backward cursor: return versions newer than the one with this id. Pass the id of the first version of the current page to walk back. Mutually exclusive with `after`. ## Response All versions of the key, newest first. Each entry is a blueprint summary. True when more results exist beyond this page in the direction of travel. Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is false. ### Blueprint summary object TypeID-encoded blueprint identifier (`blp_` prefix). Human-readable key for this version. The active version holds the bare key; an archived one holds `-`. Name of the blueprint. Description of the blueprint. True for platform-authored (gallery) blueprints shared with every org; false for blueprints owned by a specific org. True for the current version of a key; false once it has been replaced by a newer blueprint. Number of bundles visible to the caller's organization pinned to this blueprint. Present only when the read asked for it. Creation timestamp (date-time). ```bash cURL - By Key theme={"system"} curl "$ATAI_API_URL/agents/blueprints/osm/versions" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - By Id theme={"system"} curl "$ATAI_API_URL/agents/blueprints/blp_01jc9n7k3xf8mbq2v5t0ary6de/versions?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} cursor = None while True: params = {"limit": 100} if cursor: params["after"] = cursor response = requests.get(f"{base_url}/agents/blueprints/osm/versions", headers=headers, params=params) page = response.json() for version in page["data"]: marker = "active" if version["is_active"] else "archived" print(f"{version['blueprint_key']} ({version['id']}) [{marker}] {version['created_at']}") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/blueprints/osm/versions`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const page = await response.json(); page.data.forEach(version => { const marker = version.is_active ? 'active' : 'archived'; console.log(`${version.blueprint_key} (${version.id}) [${marker}] ${version.created_at}`); }); ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "blueprint_key": "osm", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "is_canonical": true, "is_active": true, "created_at": "2026-08-11T14:32:07Z" }, { "id": "blp_01jc8k2m9vr4te7hn5b3qdzx8w", "blueprint_key": "osm-2026-07-02", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "is_canonical": true, "is_active": false, "created_at": "2026-07-02T09:15:44Z" } ], "has_more": false, "next_cursor": null } ``` ```json 400 - Invalid reference or cursor theme={"system"} { "errors": [ { "code": "", "message": "Invalid reference or cursor.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - No blueprint with this key theme={"system"} { "errors": [ { "code": "", "message": "No blueprint with this key.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Passing a `blp_` id resolves it to its key first, so asking about any one version returns the whole history of that key. * At most one version of a key is active at a time; the rest carry `is_active: false` and an archived key of the form `-`. * Summaries omit the full blueprint document — fetch a single version by id with `GET /agents/blueprints/{reference}`. * `after` and `before` are mutually exclusive — send at most one of them. # List Blueprints Source: https://docs.archetypeai.app/api-reference/agents/blueprints/list-blueprints GET /agents/blueprints Page through the blueprint catalog Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns the blueprint catalog as a cursor-paginated page of blueprint summaries, newest first. Summaries omit the full blueprint document — fetch a single blueprint with `GET /agents/blueprints/{reference}` when you need its `document` or `yaml_document`. ## Request Page size. Minimum `1`, maximum `1000`. Forward cursor: return blueprints older than the one with this id. Pass the `next_cursor` of the previous page to fetch the next page. Mutually exclusive with `before`. Backward cursor: return blueprints newer than the one with this id. Pass the `prev_cursor` of the current page to walk back. Mutually exclusive with `after`. Filter to a single key. When `true`, each item carries `bundles_count` — the number of bundles visible to the caller's organization pinned to that blueprint. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response The page, newest first. Each entry is a blueprint summary. True when more results exist beyond this page in the direction of travel. Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is false. Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. ### Blueprint summary object TypeID-encoded blueprint identifier (`blp_` prefix). Human-readable key for the blueprint, e.g. `osm`. Name of the blueprint. Description of the blueprint. True for platform-authored (gallery) blueprints shared with every org; false for blueprints owned by a specific org. True for the current version of a key; false once it has been replaced by a newer blueprint (its key was archived to `-`). Number of bundles visible to the caller's organization — its own plus canonical ones — pinned to this blueprint. Present only when the list was requested with `bundles_count=true`; omitted otherwise. A blueprint with no matching bundles reports `0`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Creation timestamp (date-time). ```bash cURL - First Page theme={"system"} curl "$ATAI_API_URL/agents/blueprints?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Filter By Key theme={"system"} curl "$ATAI_API_URL/agents/blueprints?key=osm" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - With Bundle Counts theme={"system"} curl "$ATAI_API_URL/agents/blueprints?bundles_count=true" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} cursor = None while True: params = {"limit": 100} if cursor: params["after"] = cursor response = requests.get(f"{base_url}/agents/blueprints", headers=headers, params=params) page = response.json() for blueprint in page["data"]: print(f"{blueprint['blueprint_key']}: {blueprint['name']} ({blueprint['id']})") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/blueprints?limit=20`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const page = await response.json(); page.data.forEach(blueprint => { console.log(`${blueprint.blueprint_key}: ${blueprint.name} (${blueprint.id})`); }); if (page.has_more) { console.log(`Next cursor: ${page.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "blueprint_key": "osm", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "is_canonical": true, "is_active": true, "created_at": "2026-08-11T14:32:07Z" }, { "id": "blp_01jc8k2m9vr4te7hn5b3qdzx8w", "blueprint_key": "osm-2026-07-02", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "is_canonical": true, "is_active": false, "created_at": "2026-07-02T09:15:44Z" } ], "has_more": true, "next_cursor": "blp_01jc8k2m9vr4te7hn5b3qdzx8w", "prev_cursor": null } ``` ```json 200 - With bundles_count=true theme={"system"} { "data": [ { "id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "blueprint_key": "osm", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "is_canonical": true, "is_active": true, "bundles_count": 3, "created_at": "2026-08-11T14:32:07Z" }, { "id": "blp_01jc8k2m9vr4te7hn5b3qdzx8w", "blueprint_key": "osm-2026-07-02", "name": "Open-set monitor", "description": "Classifies incoming records against a known class vocabulary.", "is_canonical": true, "is_active": false, "bundles_count": 0, "created_at": "2026-07-02T09:15:44Z" } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 200 - Empty page theme={"system"} { "data": [], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ## Important Notes * `after` and `before` are mutually exclusive — send at most one of them. * Results are ordered newest first in both cursor directions, so render `data` as returned. * An archived (replaced) blueprint stays in the catalog with `is_active: false` and a key of the form `-`. * `bundles_count=true` counts only the bundles visible to the caller's organization — its own plus canonical ones — so the count is per-viewer. The count is computed over the blueprints on the current page. [v1.1.11+](/release-notes/1.1.x#v1-1-11) # Create Bundle Source: https://docs.archetypeai.app/api-reference/agents/bundles/create-bundle POST /agents/bundles Create a deployable bundle that pins a blueprint Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint creates a bundle: a named, deployable customization of a blueprint. The bundle pins one blueprint by ID or key and carries the parameters a run will use — `values`, an optional `model` override, and optional `artifacts`. Runs bind only their I/O, via `POST /agents/bundles/{bundle_id}/run`. ## Request Blueprint reference to pin: a `blp_` ID or key (e.g. `osm`). While `blueprint` accepts either a `blp_` ID or a key, the response records the resolved immutable `blueprint_id`. Human label for this bundle, e.g. `Pump A monitor`. Optional human description of this bundle. Defaults to an empty string. Capped at 512 characters, mirroring the console's client-side cap. [v1.1.12+](/release-notes/1.1.x#v1-1-12) User value overrides, layered over the blueprint defaults at run time. Must be a JSON object; defaults to `{}`. Per-slot model overrides: slot name to registry tag. Must be a flat JSON object of strings; defaults to `{}`, which uses the blueprint's default model for every slot. Optional artifact links, e.g. `{"calibration": "s3://.../knn_index"}`. Publish as a canonical (platform-wide) bundle, visible to every org. Requires the super-admin role; defaults to an org-owned bundle. ## Response Returns the created bundle. TypeID-encoded bundle identifier (`bnd_` prefix). Human label for the bundle. Human description of the bundle. The pinned blueprint's immutable `blp_` id. Resolve its key via the blueprint registry when needed. The value overrides stored on the bundle. Build lifecycle of the bundle: `building`, `ready`, or `failed`. True for a canonical (platform-authored) bundle, visible to every org. Creation timestamp (date-time). Owning organization; omitted for a canonical bundle. Per-slot model overrides: slot name to registry tag. If this object is empty, the bundle uses the blueprint's default for every slot. Artifact links attached to the bundle. The bundle's five most recent runs, newest first. Present only when a read asked for it via `include_latest_runs=true`. ```bash cURL theme={"system"} curl -X POST "$ATAI_API_URL/agents/bundles" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "blueprint": "osm", "name": "Pump A monitor", "description": "Open-set monitor tuned for pump A telemetry.", "values": {}, "artifacts": { "calibration": "s3://.../knn_index" } }' ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/bundles", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "blueprint": "osm", "name": "Pump A monitor", "description": "Open-set monitor tuned for pump A telemetry.", "values": {}, "artifacts": {"calibration": "s3://.../knn_index"}, }, ) if response.status_code == 201: bundle = response.json() print(f"Created bundle {bundle['id']} pinning {bundle['blueprint_id']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch(`${process.env.ATAI_API_URL}/agents/bundles`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ blueprint: 'osm', name: 'Pump A monitor', description: 'Open-set monitor tuned for pump A telemetry.', values: {}, artifacts: { calibration: 's3://.../knn_index' } }) }); const body = await response.json(); if (response.status === 201) { console.log(`Created bundle ${body.id} pinning ${body.blueprint_id}`); } else { console.error('Error:', body.errors); } ``` ```json 201 - Created theme={"system"} { "id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "name": "Pump A monitor", "description": "Open-set monitor tuned for pump A telemetry.", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "models": {}, "values": {}, "artifacts": { "calibration": "s3://.../knn_index" }, "status": "ready", "is_canonical": false, "created_at": "2026-08-11T15:02:19Z" } ``` ```json 400 - Invalid request theme={"system"} { "errors": [ { "code": "", "message": "Invalid request.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 403 - Super-admin required theme={"system"} { "errors": [ { "code": "", "message": "Super-admin required for canonical bundles.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Blueprint not found theme={"system"} { "errors": [ { "code": "", "message": "Blueprint not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * The pin is immutable: a later version of the key does not change what this bundle runs. * Parameters and model live on the bundle, not on the run request — a run supplies only connectors. * `canonical: true` requires the super-admin role. # Delete Bundle Source: https://docs.archetypeai.app/api-reference/agents/bundles/delete-bundle DELETE /agents/bundles/{bundle_id} Delete a bundle by id Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint deletes a bundle by its `bnd_` id. A bundle that is still referenced by runs or evals returns `409` — delete those first. Deleting the bundles that pin a blueprint is the prerequisite for deleting that blueprint, which returns `409` while any bundle still references it. ## Request Bundle `bnd_` id. ## Response Returns `204 No Content` with an empty body on success. ```bash cURL theme={"system"} curl -X DELETE "$ATAI_API_URL/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.delete( f"{base_url}/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 204: print("Bundle deleted") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); if (response.status === 204) { console.log('Bundle deleted'); } else { const body = await response.json(); console.error('Error:', body.errors); } ``` ```json 204 - Bundle deleted theme={"system"} ``` ```json 403 - Super-admin required theme={"system"} { "errors": [ { "code": "", "message": "Super-admin required for canonical bundles.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Bundle not found theme={"system"} { "errors": [ { "code": "", "message": "Bundle not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Still referenced by runs or evals theme={"system"} { "errors": [ { "code": "", "message": "Bundle is still referenced by runs or evals.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Deleting a canonical bundle requires the super-admin role. * A `409` means at least one run or eval still references this bundle. Delete those first. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * Success returns `204` with no body — check the status code rather than parsing a response. # Get Bundle Source: https://docs.archetypeai.app/api-reference/agents/bundles/get-bundle GET /agents/bundles/{bundle_id} Retrieve a single bundle, optionally with its recent runs Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns one bundle by its `bnd_` id. Set `include_latest_runs=true` to attach the bundle's most recent runs, so a bundle detail view can show run history without a second call to `/agents/instances`. ## Request Bundle `bnd_` id. Include the bundle's most recent runs as `latest_runs`. Off by default — it costs an extra join per bundle. ## Response TypeID-encoded bundle identifier (`bnd_` prefix). Human label for the bundle. Human description of the bundle. The pinned blueprint's immutable `blp_` id. Resolve its key via the blueprint registry when needed. User value overrides, layered over the blueprint defaults at run time. Build lifecycle of the bundle: `building`, `ready`, or `failed`. True for a canonical (platform-authored) bundle, visible to every org. Creation timestamp (date-time). Owning org; omitted for a canonical bundle. Per-slot model overrides: slot name to registry tag. If this object is empty, the bundle uses the blueprint's default for every slot. Artifact links attached to the bundle. The bundle's five most recent runs, newest first. Present only when the read asked for it via `include_latest_runs=true`; an empty array means the bundle has never been run. Runs are scoped to the caller's org, so a canonical bundle shows only the caller's own runs of it. ### Run summary object (`latest_runs[]`) TypeID-encoded agent identifier (`agt_` prefix). Agent lifecycle status: `running`, `paused`, `completed`, `failed`, or `cancelled`. Creation timestamp (date-time). When the run started; `null` before then. When the run finished; `null` while unfinished. External executor's job id for this run (a JOS `job_` id). Present once the run has been dispatched. Failure detail; `null` unless the run failed. ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - With Run History theme={"system"} curl "$ATAI_API_URL/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w?include_latest_runs=true" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.get( f"{base_url}/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w", headers={"Authorization": f"Bearer {api_key}"}, params={"include_latest_runs": "true"}, ) if response.status_code == 200: bundle = response.json() print(f"{bundle['name']} pins {bundle['blueprint_id']} (status {bundle['status']})") for run in bundle.get("latest_runs") or []: print(f" {run['id']}: {run['status']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w?include_latest_runs=true`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`${body.name} pins ${body.blueprint_id} (status ${body.status})`); (body.latest_runs ?? []).forEach(run => console.log(` ${run.id}: ${run.status}`)); } else { console.error('Error:', body.errors); } ``` ```json 200 - Success theme={"system"} { "id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "name": "Pump A monitor", "description": "Open-set monitor tuned for pump A telemetry.", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "models": {}, "values": {}, "artifacts": { "calibration": "s3://.../knn_index" }, "status": "ready", "is_canonical": false, "created_at": "2026-08-11T15:02:19Z", "latest_runs": [ { "id": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "status": "running", "job_id": "job_01jc9q9k4t8v2mnr5xh7bdzy3s", "created_at": "2026-08-11T15:10:00Z", "started_at": "2026-08-11T15:10:04Z", "completed_at": null, "error": null } ] } ``` ```json 404 - Bundle not found theme={"system"} { "errors": [ { "code": "", "message": "Bundle not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Without `include_latest_runs=true`, `latest_runs` is absent — an empty array means the bundle has never been run. * A run's name is always its bundle's name, so it is not repeated in `latest_runs`. Fetch the full run (connectors, blueprint reference) from `GET /agents/instances/{agent_id}`. # List Bundles Source: https://docs.archetypeai.app/api-reference/agents/bundles/list-bundles GET /agents/bundles Page through the bundles available to your organization Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated page of bundles. By default the page is most recently run first, with never-run bundles last. Filter by pinned blueprint, search by name or id, and optionally include each bundle's most recent runs so run history can be rendered without a second call to `/agents/instances`. Choose a different ordering with the `sort` and `order` parameters. ## Request Page size. Minimum `1`, maximum `1000`. Forward cursor: return the bundles that follow this one in the current sort order. Pass the `next_cursor` of the previous page to fetch the next page. Mutually exclusive with `before`. Valid only under the `sort` it was minted for. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Backward cursor: return the bundles that precede this one in the current sort order. Mutually exclusive with `after`. Valid only under the `sort` it was minted for. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Sort field: `last_run_at` (default) ranks bundles by their newest visible run, `created_at` by creation, `name` alphabetically. A cursor is only valid under the sort it was minted for; replaying it with a different `sort` is rejected with HTTP status code `400`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Sort direction: `asc` or `desc`. Defaults per field — `desc` for `last_run_at` and `created_at`, `asc` for `name`. Keep it constant while paging with a cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Case-insensitive substring match over the bundle name and id. Omit for no search filter. Restrict to bundles pinning this blueprint (`blp_` id, exact match). Include each bundle's most recent runs as `latest_runs`. Off by default — it costs an extra join per bundle in the page. ## Response The page, in the requested `sort` and `order` — in *both* cursor directions, so render it as returned. Each entry is a bundle. The default (`sort` omitted) is most recently run first: ordered by each bundle's newest visible run, with never-run bundles last (newest created first within either group). Run recency is scoped like `latest_runs` — to the caller's org and own runs — so that order is per-viewer. [v1.1.11+](/release-notes/1.1.x#v1-1-11) True when more results exist beyond this page in the direction of travel. Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is false. Cursor to step back the way this page was reached — pass it as `before` after paging forward, or as `after` after paging backward. `null` on a request that carried no cursor: the newest page has nothing to step back to. Provided because the cursor is opaque, so a client cannot mint the backward anchor from a row itself. [v1.1.12+](/release-notes/1.1.x#v1-1-12) ### Bundle object TypeID-encoded bundle identifier (`bnd_` prefix). Human label for the bundle. Human description of the bundle. The pinned blueprint's immutable `blp_` id. Resolve its key via the blueprint registry when needed. User value overrides, layered over the blueprint defaults at run time. Build lifecycle of the bundle: `building`, `ready`, or `failed`. `true` for a canonical (platform-authored) bundle, visible to every organization. Creation timestamp (date-time). Owning org; omitted for a canonical bundle. Per-slot model overrides: slot name to registry tag. If this object is empty, the bundle uses the blueprint's default for every slot. Artifact links attached to the bundle. The bundle's five most recent runs, newest first. Present only when the read asked for it via `include_latest_runs=true`; an empty array means the bundle has never been run. Runs are scoped to the caller's org, so a canonical bundle shows only the caller's own runs of it. ### Run summary object (`latest_runs[]`) TypeID-encoded agent identifier (`agt_` prefix). Agent lifecycle status: `running`, `paused`, `completed`, `failed`, or `cancelled`. Creation timestamp (date-time). When the run started; `null` before then. When the run finished; `null` while unfinished. External executor's job id for this run (a JOS `job_` id). Present once the run has been dispatched. Failure detail; `null` unless the run failed. ```bash cURL - First Page theme={"system"} curl "$ATAI_API_URL/agents/bundles?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Search, With Run History theme={"system"} curl "$ATAI_API_URL/agents/bundles?query=pump&include_latest_runs=true" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - By Pinned Blueprint theme={"system"} curl "$ATAI_API_URL/agents/bundles?blueprint_id=blp_01jc9n7k3xf8mbq2v5t0ary6de" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Sorted By Name theme={"system"} curl "$ATAI_API_URL/agents/bundles?sort=name" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Oldest Created First theme={"system"} curl "$ATAI_API_URL/agents/bundles?sort=created_at&order=asc" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.get( f"{base_url}/agents/bundles", headers={"Authorization": f"Bearer {api_key}"}, params={"limit": 20, "include_latest_runs": "true"}, ) page = response.json() for bundle in page["data"]: runs = bundle.get("latest_runs") or [] print(f"{bundle['name']} ({bundle['id']}) status={bundle['status']} runs={len(runs)}") ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ limit: '20', include_latest_runs: 'true' }); const response = await fetch( `${process.env.ATAI_API_URL}/agents/bundles?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const page = await response.json(); page.data.forEach(bundle => { const runs = bundle.latest_runs ?? []; console.log(`${bundle.name} (${bundle.id}) status=${bundle.status} runs=${runs.length}`); }); ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "name": "Pump A monitor", "description": "Open-set monitor tuned for pump A telemetry.", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "models": {}, "values": {}, "artifacts": { "calibration": "s3://.../knn_index" }, "status": "ready", "is_canonical": false, "created_at": "2026-08-11T15:02:19Z" } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 200 - With include_latest_runs=true theme={"system"} { "data": [ { "id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "name": "Pump A monitor", "description": "Open-set monitor tuned for pump A telemetry.", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "models": {}, "values": {}, "artifacts": {}, "status": "ready", "is_canonical": false, "created_at": "2026-08-11T15:02:19Z", "latest_runs": [ { "id": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "status": "completed", "job_id": "job_01jc9q9k4t8v2mnr5xh7bdzy3s", "created_at": "2026-08-11T15:10:00Z", "started_at": "2026-08-11T15:10:04Z", "completed_at": "2026-08-11T15:18:41Z", "error": null } ] } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 200 - Empty page theme={"system"} { "data": [], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ## Important Notes * `after` and `before` are mutually exclusive — send at most one of them. * A cursor snapshots the edge row's sort key, so it is only valid under the `sort` it was minted for. Keep `sort` and `order` constant while paging; replaying a cursor under a different `sort` returns `400` rather than a wrong or empty page. [v1.1.11+](/release-notes/1.1.x#v1-1-11) * Every sort resolves to a full keyset ending in `id`. Because TypeIDs are random UUIDv4, `id` is only the final tiebreak, never a sort key of its own. [v1.1.11+](/release-notes/1.1.x#v1-1-11) * `include_latest_runs=true` costs an extra join per bundle in the page; leave it off for plain listings. * `latest_runs` is capped at the five most recent runs and is scoped to the caller's org. * A bundle in Phase 1 is built on create, so `status` is normally `ready`; `building`/`failed` exist for the eventual image-build path. # Run Bundle Source: https://docs.archetypeai.app/api-reference/agents/bundles/run-bundle POST /agents/bundles/{bundle_id}/run Start a run of a bundle by binding its inputs and outputs Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint starts a run of a bundle and returns the created agent. The request supplies only the run's I/O binding — parameters and model come from the bundle. Each run is a separate agent: to re-run, call this endpoint again. ## Request Bundle `bnd_` id to run. Source/sink connectors binding this run's I/O. Bound at run time — I/O stays external to the agent ("build once, run anywhere"). One or more input refs; multiple files are staged on the same JOS input port. Each entry is a data ref. Optional output ref. Omitted (the default): the runner writes one output per input, named after the input. Provided: for concatenable formats (e.g. CSV) all output folds into this single file; for standalone-document sinks (`json/per-request`) it namespaces each per-request artifact instead of concatenating them. Passed to the runner as the `output_ref` job-config key. [v1.1.12+](/release-notes/1.1.x#v1-1-12) ### Data ref Storage kind, e.g. `file` or `dataset`. Identifier within that storage kind, e.g. `file_abc123`. Optional format hint, e.g. `csv`. ## Response Returns `202 Accepted` with the created agent. TypeID-encoded agent identifier (`agt_` prefix). Name of the agent (a run's name is its bundle's name). Organization identifier the agent belongs to. The bundle this agent was run from (provenance). Human-readable pinned blueprint reference (its key), e.g. `osm`. Immutable blueprint id the bundle pinned. Agent lifecycle status: `running`, `paused`, `completed`, `failed`, or `cancelled`. Creation timestamp (date-time). The I/O binding this run was started with; `null` when none is recorded. External executor's job id for the current run (a JOS `job_` id). Present once the run has been dispatched; lets clients query JOS for run progress. When the run started; `null` before then. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ```bash cURL - One Input theme={"system"} curl -X POST "$ATAI_API_URL/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w/run" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "connectors": { "source": [ {"type": "file", "id": "file_abc123", "format": "csv"} ] } }' ``` ```bash cURL - Multiple Inputs, Single Output theme={"system"} curl -X POST "$ATAI_API_URL/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w/run" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "connectors": { "source": [ {"type": "file", "id": "file_abc123", "format": "csv"}, {"type": "file", "id": "file_def456", "format": "csv"} ], "sink": {"type": "file", "id": "file_ghi789"} } }' ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w/run", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "connectors": { "source": [{"type": "file", "id": "file_abc123", "format": "csv"}], } }, ) if response.status_code == 202: agent = response.json() print(f"Run accepted: {agent['id']} (status {agent['status']})") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/bundles/bnd_01jc9pd42kzq7v8n3h5m6rtx0w/run`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ connectors: { source: [{ type: 'file', id: 'file_abc123', format: 'csv' }] } }) } ); const body = await response.json(); if (response.status === 202) { console.log(`Run accepted: ${body.id} (status ${body.status})`); } else { console.error('Error:', body.errors); } ``` ```json 202 - Run accepted theme={"system"} { "id": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "name": "Pump A monitor", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "bundle_id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "blueprint": "osm", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "connectors": { "source": [ {"type": "file", "id": "file_abc123", "format": "csv"} ], "sink": null }, "status": "running", "job_id": "job_01jc9q9k4t8v2mnr5xh7bdzy3s", "created_at": "2026-08-11T15:10:00Z", "started_at": null, "completed_at": null, "error": null } ``` ```json 404 - Bundle not found theme={"system"} { "errors": [ { "code": "", "message": "Bundle not found, or a model slot's tag not found in the registry.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 501 - Serving not enabled theme={"system"} { "errors": [ { "code": "", "message": "`mode: serving` requested where serving is not enabled.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Parameters and model come from the bundle, not the run request — the body carries only connectors and the optional `mode`. * Omit `sink` to get one output per input, named after the input; provide it to fold concatenable output into a single file, or to namespace each per-request artifact for a standalone-document sink. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * `mode` is recorded on the agent, so a run stays `batch` or `serving` for its whole life. Only a `serving` run answers `/query` and `/connect`. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * A `404` covers both an unknown bundle and a model slot whose tag is not in the registry. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * Each run is a new agent. To re-run, call this endpoint again rather than restarting an existing agent. * Track progress with `GET /agents/instances/{agent_id}`, its `/events` and `/logs` pages, and `/results` for outputs. # Cancel Eval Source: https://docs.archetypeai.app/api-reference/agents/evals/cancel-eval POST /agents/evals/{eval_id}/cancel Cancel a pending or running eval Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint cancels a pending or running eval and returns it in its `cancelled` state. An eval that has already terminated (with `status` whose value is `completed`, `failed`, or `cancelled`) has nothing to cancel and returns HTTP status code `409`. Canceling is the prerequisite for deleting a non-terminal eval. Attempting to delete a non-terminal eval fails, returning HTTP status `409`. Cancel the eval first to avoid this error. ## Request Eval `evl_` id. ## Response Returns the cancelled eval, in the same format that [Get Eval](/api-reference/agents/evals/get-eval) returns. TypeID-encoded eval identifier (`evl_` prefix). Human label for the eval. Organization identifier the eval belongs to. The blueprint being evaluated. The run's headline, as `.`. The examples the eval was created against, as resolved. The fully-expanded configuration this eval ran under. Eval lifecycle status; `cancelled` after a successful cancel. Subject id (`usr_...` or `key_...`) that created this eval. Creation timestamp (date-time). When the runner picked the eval up; `null` if it never did. When the eval finished; `null` while unfinished. This is always `null` for a cancelled eval since the report is populated only when an eval reaches `completed`. References to the files the run produced. A cancelled eval keeps its partial predictions entry — the rows scored so far are still readable. A cancelled eval keeps the rows it already scored. Its predictions artifact stays in `output_artifacts` with `metadata.status` set to `partial`. Failure detail; `null` unless the eval failed. ```bash cURL theme={"system"} curl -X POST "$ATAI_API_URL/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y/cancel" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y/cancel", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 200: evaluation = response.json() print(f"{evaluation['id']} is now {evaluation['status']}") elif response.status_code == 409: print("Eval already terminal") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y/cancel`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`${body.id} is now ${body.status}`); } else if (response.status === 409) { console.error('Eval already terminal'); } else { console.error('Error:', body.errors); } ``` ```json 200 - Eval cancelled theme={"system"} { "id": "evl_01jcb0h2m6t4xr9nv3k7pdzs5y", "name": "Pump A regression", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "primary": "state.macro_f1", "examples": [ { "name": "site-a-morning", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_abc123", "format": "csv", "crc32c": "AAAAAA=="} ] } ], "rendered_config": {}, "status": "cancelled", "metrics_report": null, "output_artifacts": [ { "type": "file", "id": "file_jkl012", "format": "ndjson", "metadata": {"kind": "predictions", "status": "partial", "row_count": 1840} } ], "created_by": "usr_01jc8m4p3rt6vx9qn2h5kdzb7y", "created_at": "2026-09-18T11:24:03Z", "started_at": "2026-09-18T11:24:09Z", "completed_at": null, "error": null } ``` ```json 404 - Eval not found theme={"system"} { "errors": [ { "code": "", "message": "Eval not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Eval already terminal theme={"system"} { "errors": [ { "code": "", "message": "Eval already terminal.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Create Eval Source: https://docs.archetypeai.app/api-reference/agents/evals/create-eval POST /agents/evals Score a blueprint against a set of labeled examples Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint creates an evaluation: the blueprint to evaluate, the examples to score it on, and — only where the run differs from what the blueprint declares — how to score them. Only blueprints that publish a `metrics` catalog support being evaluated. The eval is created `pending` and returns immediately. Poll [Get Eval](/api-reference/agents/evals/get-eval) to watch it reach `completed`, `failed`, or `cancelled`, and to read its `metrics_report`. Use [List Eval Examples](/api-reference/agents/evals/list-eval-examples) to find out where it scored badly. Only each example's `inputs` is required. An example following the conventions its blueprint declares needs nothing else: it is named after its input file, and each target's labels are read from a column named after the target. State a deviation once: on the run's `targets` when every example shares it, on the example itself when only one does. ## Request The blueprint to evaluate — a `blp_` id. Must exist and be visible to the caller's organization. The examples to score. Must be non-empty. Optional human label. Defaults to an empty string. The run's headline, as `.` — e.g. `state.macro_f1`. Defaults to the blueprint's own. Must name a target this run scores and an objective it computes for it. Emit the per-row predictions NDJSON artifact alongside the metrics report. The artifact is what makes a score explainable. Set `false` to skip it when the input is large enough that a row-per-row artifact is not worth its size. Per-target overrides for this run, keyed by target name. Every field of an entry is optional and falls back to what the blueprint's target declares, so a run that wants nothing different omits this entirely — and one that does need a change states it once here rather than on every file. `targets` overrides apply to every example of the run; an example may still override them for itself. A key must name a target the blueprint declares, and `objectives` may only narrow what the target offers, never widen it. ### Example object (`examples[]`) One thing an eval scores the agent on: the inputs handed to the agent, and the ground truth expected of it. The data handed to the agent for this example. Currently, only one `file` reference is permitted. Each entry is a data ref. `inputs` is the only property required on an example. A conventionally-shaped example writes nothing else; it is named after its input file, and each target's labels come from a column named after the target. The name by which this example is identified in the run's results. Defaults to the file name of its input, without the extension. Names must be unique within a request: results are keyed by name, and two examples sharing one cannot be told apart in a report. The annotation supplied with this example, keyed by a name of your choosing: where its values are and, where they are not recorded at the cadence the agent emits at, how they reduce. This says nothing about which target it serves; that's done by `binding`. This means the same annotation can be written once and scored against different agents. Omit `binding` entirely to use the convention: each target's labels are a column of the input named after the target. Which targets each annotation serves, keyed by the annotation's name; each value is an array of target names. Omit it whenever the names line up: an annotation named after a target serves that target, and a single annotation serves a single target whatever either is called. Free-form tags for this example. Carried through to its results, where they are what makes a long per-example table answer a question — which site, which shift, which operator. ### Data ref (`examples[].inputs[]`) Storage kind, e.g. `file` or `dataset`. Identifier within that storage kind, e.g. `file_abc123`. Optional format hint, e.g. `csv`. ### Ground-truth declaration (`examples[].ground_truth.`) Both fields of this object are optional and layer over what the run already settled, because the two are independent statements: an annotation in a column of its own overrides `from` and leaves the reduction alone; an annotation recorded at a coarser cadence than the rest of the set overrides `downsampling` and leaves its location alone. Where this example keeps the annotation's values. Omitted to keep whatever the run settled on — by default, a column named after the target it serves. One of two forms: * `{"column": "state"}` — the labels are a column of the input itself, one label per record. An optional `values` map (`{"0": "idle", "1": "running"}`) maps each value as it appears in the column onto the label it means, for an input that spells its labels differently. A value the map does not cover is a read error, not a silently dropped record. * `{"constant": "idle"}` — one label covers the whole input, and every record is scored against it. How these labels collapse to the one value a scored unit is compared against: `last_record` or `majority_vote`. Omitted to keep the rule the target's pairing declares. ### Target override (`targets.`) The fields here are the scoring protocol — how the agent is measured — never what the agent decides or where its decision lands, which only the blueprint may say. Which of the target's objectives to compute: `macro_f1`, `accuracy`. Must be a subset of what the target declares; an eval may narrow the list, never widen it. Where every input of this run keeps the target's labels, when they all agree and disagree with the target's name. An input may still override it. Same two forms as a ground-truth declaration's `from`. The window rule for every input of this run: `last_record` or `majority_vote`. An input may still override it. ## Response Returns `201 Created` with the eval in `pending` status. TypeID-encoded eval identifier (`evl_` prefix). Human label for the eval. Organization identifier the eval belongs to. The blueprint being evaluated. The run's headline, as `.` — resolved at creation, so this is what was actually scored rather than what was asked for. The examples the eval was created against, as resolved: each carries the name its results are keyed by and inputs stamped with the CRC32C of the bytes scored and the fully-resolved ground-truth declarations, so the row records what was read rather than what was asked for. The fully-expanded configuration this eval runs under, resolved when the eval was created: the blueprint being evaluated, the bundle's values and artifact locations, and the test files to score against. A self-describing record of the run, so an eval still says exactly what it ran even after its bundle or blueprint moves on. Opaque JSON on the wire — treat the shape as informational. Eval lifecycle status: `pending`, `running`, `completed`, `failed`, or `cancelled`. Subject id (`usr_...` or `key_...`) that created this eval. Creation timestamp (date-time). When the runner picked the eval up; `null` before then. When the eval finished; `null` while unfinished. Aggregate and per-target scoring results. Populated when the eval reaches `completed`; `null` while pending, running, cancelled, or failed. See [Get Eval](/api-reference/agents/evals/get-eval) for its shape. Refs to the files the run produced. Each `id` is a data-service file id, so an artifact is downloadable through the files API. Failure detail; `null` unless the eval failed. ### Resolved example object (`examples[]`) How this example is identified in the run's results. Example names must be unique within a request, because results are keyed by name. The example's 1-based position in the run, fixing the order results are listed in. The data handed to the agent, each ref carrying the CRC32C of the bytes scored. The free-form tags the example was created with, if any. ```bash cURL - Conventional Examples theme={"system"} curl -X POST "$ATAI_API_URL/agents/evals" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Pump A regression", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "examples": [ {"inputs": [{"type": "file", "id": "file_abc123", "format": "csv"}]}, {"inputs": [{"type": "file", "id": "file_def456", "format": "csv"}]} ] }' ``` ```bash cURL - With Overrides theme={"system"} curl -X POST "$ATAI_API_URL/agents/evals" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Pump A regression", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "primary": "state.macro_f1", "emit_predictions": false, "targets": { "state": { "objectives": ["macro_f1"], "from": {"column": "ground_truth_state"}, "downsampling": "majority_vote" } }, "examples": [ { "name": "site-a-morning", "inputs": [{"type": "file", "id": "file_abc123", "format": "csv"}], "metadata": {"site": "a", "shift": "morning"} }, { "name": "site-b-idle-run", "inputs": [{"type": "file", "id": "file_def456", "format": "csv"}], "ground_truth": { "state": {"from": {"constant": "idle"}} }, "metadata": {"site": "b", "shift": "night"} } ] }' ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/evals", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "name": "Pump A regression", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "examples": [ {"inputs": [{"type": "file", "id": "file_abc123", "format": "csv"}]}, {"inputs": [{"type": "file", "id": "file_def456", "format": "csv"}]}, ], }, ) if response.status_code == 201: evaluation = response.json() print(f"Created {evaluation['id']} ({evaluation['status']}) scoring {evaluation['primary']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch(`${process.env.ATAI_API_URL}/agents/evals`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Pump A regression', blueprint_id: 'blp_01jc9n7k3xf8mbq2v5t0ary6de', examples: [ { inputs: [{ type: 'file', id: 'file_abc123', format: 'csv' }] }, { inputs: [{ type: 'file', id: 'file_def456', format: 'csv' }] } ] }) }); const body = await response.json(); if (response.status === 201) { console.log(`Created ${body.id} (${body.status}) scoring ${body.primary}`); } else { console.error('Error:', body.errors); } ``` ```json 201 - Created theme={"system"} { "id": "evl_01jcb0h2m6t4xr9nv3k7pdzs5y", "name": "Pump A regression", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "primary": "state.macro_f1", "examples": [ { "name": "file_abc123", "ordinal": 1, "inputs": [ { "type": "file", "id": "file_abc123", "format": "csv", "crc32c": "AAAAAA==", "metadata": { "targets": { "state": {"from": {"column": "state"}, "downsampling": "last_record"} } } } ] } ], "rendered_config": {}, "status": "pending", "metrics_report": null, "output_artifacts": null, "created_by": "usr_01jc8m4p3rt6vx9qn2h5kdzb7y", "created_at": "2026-09-18T11:24:03Z", "started_at": null, "completed_at": null, "error": null } ``` ```json 400 - Invalid request theme={"system"} { "errors": [ { "code": "", "message": "Invalid request.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Blueprint not found theme={"system"} { "errors": [ { "code": "", "message": "Blueprint not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Delete Eval Source: https://docs.archetypeai.app/api-reference/agents/evals/delete-eval DELETE /agents/evals/{eval_id} Delete a terminal eval by id Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint deletes an eval by its `evl_` id. Only terminal evals (thoase whose status is `completed`, `failed`, or `cancelled`) can be deleted.. An eval that is still `pending` or `running` returns HTTP status `409`; cancel it first with [Cancel Eval](/api-reference/agents/evals/cancel-eval). ## Request Eval `evl_` id of the eval to delete. ## Response Returns `204 No Content` with an empty body on success. Check the status code for a `204` response rather than parsing a response. ```bash cURL theme={"system"} curl -X DELETE "$ATAI_API_URL/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.delete( f"{base_url}/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 204: print("Eval deleted") elif response.status_code == 409: print("Eval is not terminal — cancel it first") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); if (response.status === 204) { console.log('Eval deleted'); } else if (response.status === 409) { console.error('Eval is not terminal — cancel it first'); } else { const body = await response.json(); console.error('Error:', body.errors); } ``` ```json 204 - Eval deleted theme={"system"} ``` ```json 404 - Eval not found theme={"system"} { "errors": [ { "code": "", "message": "Eval not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Eval is not in a terminal state theme={"system"} { "errors": [ { "code": "", "message": "Eval is not in a terminal state (cancel it first).", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Get Eval Source: https://docs.archetypeai.app/api-reference/agents/evals/get-eval GET /agents/evals/{eval_id} Retrieve one eval, its status, and its metrics report Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint returns one eval by its `evl_` id. Fields beyond the always-present ones are populated as the eval progresses: * `started_at` is populated when the runner picks up the eval * `output_artifacts` is populated as the run progresses. An entry whose `metadata.status` is `partial` holds the rows scored so far, which is also what a failed or cancelled mid-run eval leaves behind. * `metrics_report` is populated upon successful completion and is `null` until then * `completed_at` is populated upon successful completion * `error` is populated on a `failed` completion. The `metrics_report` answers the question "is this agent good enough?" To answer "where is this agent bad?" page through [List Eval Examples](/api-reference/agents/evals/list-eval-examples). ## Request Eval `evl_` id. ## Response TypeID-encoded eval identifier (`evl_` prefix). Human label for the eval. Organization identifier the eval belongs to. The blueprint being evaluated. The run's headline, as `.` — resolved at creation, so this is what was actually scored rather than what was asked for. The examples the eval was created against, as resolved: each carries the name its results are keyed by and inputs stamped with the CRC32C of the bytes scored and the fully-resolved ground-truth declarations. `examples` records what the run actually read; that is, resolved names, the CRC32C of the bytes scored, and fully-resolved ground-truth declarations, rather than what the request asked for. The fully-expanded configuration this eval runs under, resolved when the eval was created. An eval does not run the blueprint quite unchanged: it runs the whole pipeline with a scoring stage in place of the blueprint's own sink, and the ground-truth labels declared alongside each input. Opaque JSON on the wire — treat the shape as informational. Eval lifecycle status: `pending`, `running`, `completed`, `failed`, or `cancelled`. Evals are always created with the status `pending`. Once they're dispatched, their state changes to `running`. From there, it will eventually enter one of the three terminal states: `completed`, `failed`, or `cancelled`. Subject id (`usr_...` or `key_...`) that created this eval. Creation timestamp (date-time). When the runner picked the eval up; `null` before then. When the eval finished; `null` while unfinished. Aggregate and per-target scoring results. Populated when the eval reaches `completed`; `null` while pending, running, cancelled, or failed. See [Metrics report](#metrics-report-metrics_report) for the format of this object. Refs to the files the run produced. Each `id` is a data-service file id, so an artifact is downloadable through the files API, and each carries `metadata` saying which artifact it is. See [Output artifact ref](#output-artifact-ref-output_artifacts) for the format of the objects in this array. Populated *while the run goes*, not only at the end: each batch of scored rows is appended to the predictions file and updates the entry, whose `metadata.status` stays `partial` until the run's final push marks it `complete`. An eval that failed or was cancelled mid-run keeps its partial entry — the rows scored so far are still readable. Failure detail; `null` unless the eval failed. ### Metrics report (`metrics_report`) The run's headline plus one entry per scored target. Wire-format version. Bumped on breaking changes; additive changes (a new target type, a new optional field) stay on the same version. The run's headline score. Deliberately repeats a value that also appears in the named target's `aggregate`: a reader wanting the one number the run is judged by gets it without following a pointer into the map. * `target` (string, required) — the target this headline is about. * `name` (string, required) — the metric's name, e.g. `macro_f1`. * `value` (number, required) — its value. One entry per scored target, keyed by target name. See [Target report](#target-report-metrics_report-targets-\) for the format of a target record. ### Target report (`metrics_report.targets.`) Every objective this run computed for the target, by name. The target's type. For `category` — one class per scored unit — the three fields below are also present. The class vocabulary, fixing the index order of `per_class` and the confusion matrix. Per-class `precision`, `recall`, `f1`, and `support` — parallel arrays aligned to `class_names`. `support` counts real occurrences of each class in the ground-truth stream, independent of what the classifier predicted. Row = true class, column = predicted class, both in `class_names` order. ### Output artifact ref (`output_artifacts[]`) Storage kind, e.g. `file`. Data-service file id, so the artifact is downloadable through the files API. Optional format hint. Whole-file CRC32C checksum of the referenced bytes, base64-encoded exactly as S3 emits it. `null` when the data service has no checksum for the file. For an artifact an eval produced: `kind` (which artifact it is), `status` (`partial` or `complete`), and `row_count` (rows in the file — how many scored rows a reader will find in it). ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import time import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} eval_id = "evl_01jcb0h2m6t4xr9nv3k7pdzs5y" while True: response = requests.get(f"{base_url}/agents/evals/{eval_id}", headers=headers) evaluation = response.json() if evaluation["status"] in ("completed", "failed", "cancelled"): break time.sleep(5) if evaluation["status"] == "completed": headline = evaluation["metrics_report"]["primary"] print(f"{headline['target']}.{headline['name']} = {headline['value']}") else: print(f"{evaluation['status']}: {evaluation.get('error')}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`${body.name} [${body.status}]`); if (body.metrics_report) { const { target, name, value } = body.metrics_report.primary; console.log(`${target}.${name} = ${value}`); } } else { console.error('Error:', body.errors); } ``` ```json 200 - Completed theme={"system"} { "id": "evl_01jcb0h2m6t4xr9nv3k7pdzs5y", "name": "Pump A regression", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "primary": "state.macro_f1", "examples": [ { "name": "site-a-morning", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_abc123", "format": "csv", "crc32c": "AAAAAA=="} ], "metadata": {"site": "a", "shift": "morning"} } ], "rendered_config": {}, "status": "completed", "metrics_report": { "schema_version": "v1", "primary": {"target": "state", "name": "macro_f1", "value": 0.87}, "targets": { "state": { "type": "category", "aggregate": {"macro_f1": 0.87, "accuracy": 0.91}, "class_names": ["running", "idle", "fault_bearing"], "per_class": { "precision": [0.93, 0.88, 0.74], "recall": [0.96, 0.85, 0.69], "f1": [0.94, 0.86, 0.71], "support": [4120, 1880, 260] }, "confusion_matrix": [ [3955, 140, 25], [220, 1598, 62], [45, 36, 179] ] } } }, "output_artifacts": [ { "type": "file", "id": "file_jkl012", "format": "ndjson", "crc32c": "AAAAAA==", "metadata": {"kind": "predictions", "status": "complete", "row_count": 6260} } ], "created_by": "usr_01jc8m4p3rt6vx9qn2h5kdzb7y", "created_at": "2026-09-18T11:24:03Z", "started_at": "2026-09-18T11:24:09Z", "completed_at": "2026-09-18T11:31:52Z", "error": null } ``` ```json 404 - Eval not found theme={"system"} { "errors": [ { "code": "", "message": "Eval not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes The run-level figure is every example pooled, never the mean of the per-example results from [List Eval Examples](/api-reference/agents/evals/list-eval-examples). # List Eval Examples Source: https://docs.archetypeai.app/api-reference/agents/evals/list-eval-examples GET /agents/evals/{eval_id}/examples Page through what an eval measured for each of its examples Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint lists what an eval measured for each of its examples. The eval's own `metrics_report` answers "is this agent good enough"; these answer "where is it bad". Each example is scored on its own rows as the run streams, and the run-level report is those examples pooled — so the two always agree, and a run-level figure is never the mean of what this returns. Results are ordered by the example's position in the run, oldest first. That is deliberately not the newest-first order the other lists use: an example set has no time order, so the useful order is the one the caller supplied. An eval that has not completed lists no examples rather than erroring. Results appear when the run reports them. The HTTP status code returned is `404` both if the specified eval ID is unknown and if the ID exists but belongs to another organization. ## Request Eval `evl_` id. Page size. Minimum `1`, maximum `1000`. Forward cursor: return examples after this page's last one. Pass the previous page's `next_cursor`. Mutually exclusive with `before`. Backward cursor: return examples before this page's first one. Pass the current page's `prev_cursor`. Mutually exclusive with `after`. ## Response The page, in the order the eval was given its examples. Unlike every other list in this API this is *not* newest-first: an example set has no time order, and reversing the list the caller supplied would only make it harder to read. Each entry in this array is an [Example result object](#example-result-object). `true` when more results exist beyond this page in the direction of travel. Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is false. Cursor to step back the way this page was reached. `null` on the first page. ### Example result object Identifier of this example result. How the example is identified — its own `name`, or the stem of its input file when it declared none. The example's 1-based position in the run, and the order results are listed in. The example's input refs, each carrying the CRC32C of the bytes scored. Whether this example was scored: `completed` or `failed`. Narrower than the eval's own status on purpose — an example is not dispatched, paused, or cancelled on its own. It is part of a run that either got far enough to score it or did not. One entry per scored target. Absent when the example was not scored. Same shape as the run report's `targets`, narrowed to this example's rows — so a client that renders the run's numbers renders an example's with no second code path. `targets` is absent on an example whose `status` is `failed`; when the status is `failed`, read `error` instead. The free-form tags the example was created with. What a long per-example table is sliced by — which site, which shift, which operator. Why the example was not scored. Present when `status` is `failed`. ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y/examples?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} eval_id = "evl_01jcb0h2m6t4xr9nv3k7pdzs5y" cursor = None while True: params = {"limit": 100} if cursor: params["after"] = cursor response = requests.get(f"{base_url}/agents/evals/{eval_id}/examples", headers=headers, params=params) page = response.json() for example in page["data"]: if example["status"] == "failed": print(f"{example['ordinal']:>3} {example['name']}: {example['error']}") continue score = example["targets"]["state"]["aggregate"]["macro_f1"] print(f"{example['ordinal']:>3} {example['name']}: macro_f1={score}") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/evals/evl_01jcb0h2m6t4xr9nv3k7pdzs5y/examples?limit=20`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const page = await response.json(); page.data.forEach(example => { if (example.status === 'failed') { console.error(`${example.ordinal} ${example.name}: ${example.error}`); return; } const score = example.targets.state.aggregate.macro_f1; console.log(`${example.ordinal} ${example.name}: macro_f1=${score}`); }); ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "", "name": "site-a-morning", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_abc123", "format": "csv", "crc32c": "AAAAAA=="} ], "status": "completed", "targets": { "state": { "type": "category", "aggregate": {"macro_f1": 0.91, "accuracy": 0.94}, "class_names": ["running", "idle"], "per_class": { "precision": [0.95, 0.9], "recall": [0.97, 0.86], "f1": [0.96, 0.88], "support": [2100, 900] }, "confusion_matrix": [[2037, 63], [126, 774]] } }, "metadata": {"site": "a", "shift": "morning"}, "error": null }, { "id": "", "name": "site-b-idle-run", "ordinal": 2, "inputs": [ {"type": "file", "id": "file_def456", "format": "csv", "crc32c": "AAAAAA=="} ], "status": "failed", "metadata": {"site": "b", "shift": "night"}, "error": "" } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 200 - Not completed yet theme={"system"} { "data": [], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 400 - Invalid query parameter theme={"system"} { "errors": [ { "code": "", "message": "Invalid query parameter.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Eval not found theme={"system"} { "errors": [ { "code": "", "message": "Eval not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # List Evals Source: https://docs.archetypeai.app/api-reference/agents/evals/list-evals GET /agents/evals Page through evals, filtered by status or blueprint Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated page of evals, newest first. Each entry is a full eval, with the same fields [Get Eval](/api-reference/agents/evals/get-eval) returns. Filter by lifecycle status, by the blueprint being evaluated, or search by name and ID. ## Request Page size. Minimum `1`, maximum `1000`. Forward cursor: return evals older than the one with this ID. Pass the `next_cursor` of the previous page (or the id of its last eval) to fetch the next page. This parameter is mutually exclusive with `before`; do not include both. Backward cursor: return evals newer than the one with this ID. Pass the ID of the first eval of the current page to walk back. This parameter is mutually exclusive with `after`; do not include both. Filter to a single lifecycle status (e.g. `pending`, `completed`). Omit for all statuses. One of `pending`, `running`, `completed`, `failed`, `cancelled`. Case-insensitive substring match over the eval name and ID. Omit for no search filter. To search for an exact blueprint ID, use the `blueprint_id` parameter instead. Restrict to evals of this blueprint (`blp_` ID, exact match). Unlike `query`, this requires a full match to the specified blueprint ID. ## Response The page, newest first. Each entry is an eval, in the shape [Get Eval](/api-reference/agents/evals/get-eval) returns. Each entry carries the full eval. If the eval has completed, it includes the `metrics_report`, so you don't need to make another request to show scores. Results are ordered newest first in both cursor directions, so render `data` as returned. `true` when more results exist beyond this page in the direction of travel. Cursor for the next page in the same direction; pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is `false`. ```bash cURL - First Page theme={"system"} curl "$ATAI_API_URL/agents/evals?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Completed Only theme={"system"} curl "$ATAI_API_URL/agents/evals?status=completed" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - One Blueprint theme={"system"} curl "$ATAI_API_URL/agents/evals?blueprint_id=blp_01jc9n7k3xf8mbq2v5t0ary6de" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} cursor = None while True: params = {"limit": 100, "status": "completed"} if cursor: params["after"] = cursor response = requests.get(f"{base_url}/agents/evals", headers=headers, params=params) page = response.json() for evaluation in page["data"]: report = evaluation.get("metrics_report") headline = report["primary"]["value"] if report else None print(f"{evaluation['id']} {evaluation['name']} [{evaluation['status']}] {evaluation['primary']}={headline}") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ limit: '20', status: 'completed' }); const response = await fetch( `${process.env.ATAI_API_URL}/agents/evals?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const page = await response.json(); page.data.forEach(evaluation => { const headline = evaluation.metrics_report?.primary?.value ?? null; console.log(`${evaluation.id} ${evaluation.name} [${evaluation.status}] ${evaluation.primary}=${headline}`); }); ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "evl_01jcb0h2m6t4xr9nv3k7pdzs5y", "name": "Pump A regression", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "primary": "state.macro_f1", "examples": [ { "name": "site-a-morning", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_abc123", "format": "csv", "crc32c": "AAAAAA=="} ] } ], "rendered_config": {}, "status": "completed", "metrics_report": { "schema_version": "v1", "primary": {"target": "state", "name": "macro_f1", "value": 0.87}, "targets": { "state": { "type": "category", "aggregate": {"macro_f1": 0.87, "accuracy": 0.91}, "class_names": ["running", "idle"], "per_class": { "precision": [0.93, 0.88], "recall": [0.96, 0.85], "f1": [0.94, 0.86], "support": [4120, 1880] }, "confusion_matrix": [[3955, 165], [282, 1598]] } } }, "output_artifacts": [ { "type": "file", "id": "file_jkl012", "format": "ndjson", "metadata": {"kind": "predictions", "status": "complete", "row_count": 6000} } ], "created_by": "usr_01jc8m4p3rt6vx9qn2h5kdzb7y", "created_at": "2026-09-18T11:24:03Z", "started_at": "2026-09-18T11:24:09Z", "completed_at": "2026-09-18T11:31:52Z", "error": null } ], "has_more": false, "next_cursor": null } ``` ```json 200 - Empty page theme={"system"} { "data": [], "has_more": false, "next_cursor": null } ``` ```json 400 - Invalid query parameter theme={"system"} { "errors": [ { "code": "", "message": "Invalid query parameter.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Cancel Agent Source: https://docs.archetypeai.app/api-reference/agents/instances/cancel-agent POST /agents/instances/{agent_id}/cancel Cancel a running or paused agent run Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint cancels an agent run and returns the updated agent. You can only cancel agents whose status is either `running` or `paused`. If the agent has already reached one of the terminal states (`completed`, `failed`, or `cancelled`), this returns HTTP status code `409`. Once an agent has been cancelled, it cannot be resumed or restarted. If you want to temporarily stop an agent, pause it using the [Pause Agent](/api-reference/agents/instances/pause-agent) endpoint. You must cancel agents which are running or paused before deleting them. ## Request TypeID-encoded agent identifier (starting with the prefix `agt_`). ## Response Returns the cancelled agent. TypeID-encoded agent identifier of the cancelled agent. Name of the agent (a run's name is its bundle's name). Organization identifier the agent belongs to. The bundle this agent was run from (provenance). Human-readable pinned blueprint reference (its key), e.g. `osm`. Immutable blueprint ID the bundle pinned. Agent lifecycle status; `cancelled` after a successful cancel. Creation timestamp (date-time). The I/O binding this run was started with; `null` when none is recorded. External executor's job ID for the current run (a JOS `job_` ID). Present once the run has been dispatched. When the run started; `null` before then. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ```bash cURL theme={"system"} curl -X POST "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/cancel" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/cancel", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 200: agent = response.json() print(f"Agent {agent['id']} is now {agent['status']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/cancel`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`Agent ${body.id} is now ${body.status}`); } else { console.error('Error:', body.errors); } ``` ```json 200 - Agent cancelled theme={"system"} { "id": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "name": "Pump A monitor", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "bundle_id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "blueprint": "osm", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "connectors": { "source": [ {"type": "file", "id": "file_abc123", "format": "csv"} ], "sink": null }, "status": "cancelled", "job_id": "job_01jc9q9k4t8v2mnr5xh7bdzy3s", "created_at": "2026-08-11T15:10:00Z", "started_at": "2026-08-11T15:10:04Z", "completed_at": "2026-08-11T15:14:02Z", "error": null } ``` ```json 404 - Agent not found theme={"system"} { "errors": [ { "code": "", "message": "Agent not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Agent already terminal theme={"system"} { "errors": [ { "code": "", "message": "Agent already terminal.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Delete Agent Source: https://docs.archetypeai.app/api-reference/agents/instances/delete-agent DELETE /agents/instances/{agent_id} Delete a terminal agent run Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint deletes an agent (bundle run) by its `agt_` id. Only terminal runs can be deleted. A run that is still `running` or `paused` returns `409` — cancel it first with `POST /agents/instances/{agent_id}/cancel`. ## Request Agent `agt_` id. ## Response Returns `204 No Content` with an empty body on success. ```bash cURL theme={"system"} curl -X DELETE "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} agent_url = f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f" response = requests.delete(agent_url, headers=headers) if response.status_code == 204: print("Agent deleted") elif response.status_code == 409: # Not terminal yet — cancel, then delete. requests.post(f"{agent_url}/cancel", headers=headers) requests.delete(agent_url, headers=headers) else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const agentUrl = `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f`; const headers = { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` }; const response = await fetch(agentUrl, { method: 'DELETE', headers }); if (response.status === 204) { console.log('Agent deleted'); } else if (response.status === 409) { // Not terminal yet — cancel, then delete. await fetch(`${agentUrl}/cancel`, { method: 'POST', headers }); await fetch(agentUrl, { method: 'DELETE', headers }); } else { const body = await response.json(); console.error('Error:', body.errors); } ``` ```json 204 - Agent deleted theme={"system"} ``` ```json 404 - Agent not found theme={"system"} { "errors": [ { "code": "", "message": "Agent not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Agent is not in a terminal state theme={"system"} { "errors": [ { "code": "", "message": "Agent is not in a terminal state (cancel it first).", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Terminal statuses are `completed`, `failed`, and `cancelled`. A `running` or `paused` agent must be cancelled before it can be deleted. * Success returns `204` with no body — check the status code rather than parsing a response. # Get Agent Source: https://docs.archetypeai.app/api-reference/agents/instances/get-agent GET /agents/instances/{agent_id} Retrieve a single agent run and its current status Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns one agent (bundle run) by its `agt_` id, including its lifecycle status, I/O binding, and the executor job id once the run has been dispatched. ## Request Agent `agt_` id. ## Response TypeID-encoded agent identifier (`agt_` prefix). Name of the agent (a run's name is its bundle's name). Organization identifier the agent belongs to. The bundle this agent was run from (provenance). Human-readable pinned blueprint reference (its key), e.g. `osm`. Immutable blueprint id the bundle pinned. Agent lifecycle status: `running`, `paused`, `completed`, `failed`, or `cancelled`. Creation timestamp (date-time). Source/sink connectors binding this run's I/O; `null` when none is recorded. One or more input refs; multiple files are staged on the same JOS input port. The single output ref, when the run was started with one. Omitted (the default): the runner writes one output per input, named after the input. External executor's job id for the current run (a JOS `job_` id). Present once the run has been dispatched; lets clients query JOS for run progress. When the run started; `null` before then. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.get( f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 200: agent = response.json() print(f"{agent['name']} [{agent['status']}] job={agent.get('job_id')}") if agent.get("error"): print(f"Error detail: {agent['error']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`${body.name} [${body.status}] job=${body.job_id}`); } else { console.error('Error:', body.errors); } ``` ```json 200 - Success theme={"system"} { "id": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "name": "Pump A monitor", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "bundle_id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "blueprint": "osm", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "connectors": { "source": [ {"type": "file", "id": "file_abc123", "format": "csv"} ], "sink": null }, "status": "completed", "job_id": "job_01jc9q9k4t8v2mnr5xh7bdzy3s", "created_at": "2026-08-11T15:10:00Z", "started_at": "2026-08-11T15:10:04Z", "completed_at": "2026-08-11T15:18:41Z", "error": null } ``` ```json 404 - Agent not found theme={"system"} { "errors": [ { "code": "", "message": "Agent not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Lifecycle: a run starts `running`, can move to `paused` and back via `/pause` and `/resume`, and terminates in `completed`, `failed`, or `cancelled`. * `job_id` appears once the run has been dispatched to the executor; use it to query JOS for run progress. * `mode` records how the run was started. A `serving` run is the one that answers `POST /agents/instances/{agent_id}/query` and `GET /agents/instances/{agent_id}/connect`. [v1.1.12+](/release-notes/1.1.x#v1-1-12) * To re-run, run the bundle again — each run is a new agent. # Get Agent Logs Source: https://docs.archetypeai.app/api-reference/agents/instances/get-agent-logs GET /agents/instances/{agent_id}/logs Page through an agent run's executor-sourced log lines Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns a page of run log entries, newest first. Log lines come from the executor (JOS job events) rather than from the agent event log, so they carry the executor's own severity vocabulary and event kinds. The list is empty for a no-op run. Filter by severity, or search the message and event type. ## Request Agent `agt_` id. Page size. Minimum `1`, maximum `1000`. Forward cursor: return log lines older than this page. Pass the previous page's `next_cursor`. Opaque — not a log id; never compute on it. Mutually exclusive with `before`. Backward cursor: return log lines newer than this page. Opaque, as `after` is. Mutually exclusive with `after`. Filter to a single severity. Omit for all severities. One of `INFO`, `WARN`, `ERROR`, `SUCCESS`, `FAILED` — any case is accepted, and `warning` is accepted for `warn`. Case-insensitive substring match over the line's message and event type. Omit for no search filter. ## Response The page, newest first. Each entry is a log line. True when more log lines exist beyond this page in the direction of travel. Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is false. Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ### Log entry object One executor-sourced log line for a run (a JOS job event). Executor-assigned log id. Stable, but not this list's cursor. Severity of the line, in the executor's vocabulary: `INFO`, `WARN`, `ERROR`, `SUCCESS`, or `FAILED`. Executor's event kind, e.g. `status_change`. When the line was logged (date-time). The log message; `null` when the event carries none. Index of the worker that logged the line, when it came from one. ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/logs?limit=50" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Errors Only theme={"system"} curl "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/logs?level=ERROR" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Search theme={"system"} curl "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/logs?search=status_change" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} logs_url = f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/logs" cursor = None while True: params = {"limit": 100} if cursor: params["after"] = cursor response = requests.get(logs_url, headers=headers, params=params) if response.status_code != 200: print(f"Error: {response.json()['errors']}") break page = response.json() for line in page["data"]: print(f"[{line['level']}] {line['event_type']}: {line.get('message')}") if not page["has_more"]: break # The cursor is opaque — pass it back verbatim. cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ limit: '50', level: 'ERROR' }); const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/logs?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { body.data.forEach(line => { console.log(`[${line.level}] ${line.event_type}: ${line.message}`); }); } else { console.error('Error:', body.errors); } ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "log_01jc9q9m4d", "level": "SUCCESS", "event_type": "status_change", "message": "Job completed.", "index": null, "created_at": "2026-08-11T15:18:41Z" }, { "id": "log_01jc9q9k8r", "level": "INFO", "event_type": "status_change", "message": "Worker started.", "index": 0, "created_at": "2026-08-11T15:10:07Z" } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 200 - Empty (no-op run) theme={"system"} { "data": [], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 400 - Invalid cursor theme={"system"} { "errors": [ { "code": "", "message": "Invalid cursor.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Agent not found theme={"system"} { "errors": [ { "code": "", "message": "Agent not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * The cursor here is **opaque** and is not a log id. Pass `next_cursor` back verbatim; never derive it from `data[last].id` or compute on it. * `after` and `before` are mutually exclusive — send at most one of them. * `level` uses the executor's vocabulary, which includes `SUCCESS` and `FAILED` — these have no equivalent in the agent event log's three levels. * A no-op run produces no executor logs, so `data` comes back empty. # Get Agent Results Source: https://docs.archetypeai.app/api-reference/agents/instances/get-agent-results GET /agents/instances/{agent_id}/results Page through the output artifacts an agent run produced Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns a page of a run's output refs, newest first. Results come from the executor (JOS job outputs), so each entry names the output port it was written to and points at the stored file. The list is empty for a no-op run. ## Request Agent `agt_` id. Page size. Minimum `1`, maximum `1000`. Forward cursor: return results older than this page. Pass the previous page's `next_cursor`. Opaque — not a result id; never compute on it. Mutually exclusive with `before`. Backward cursor: return results newer than this page. Opaque, as `after` is. Mutually exclusive with `after`. ## Response The page, newest first. Each entry is one artifact the run produced. True when more results exist beyond this page in the direction of travel. Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is false. Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ### Result entry object Executor-assigned output id. Stable, but not this list's cursor. Executor output port the result was written to. The stored file this result points at. When the result was recorded (date-time). When the result expires; `null` when it does not. ### File ref object (`data`) Fetchable reference to the bytes — a presigned URL, or a data-service ref that has to be downloaded through the authenticated proxy. Name of the stored file. File extension; `null` when unknown. File type; `null` when unknown. Size of the file in bytes; `null` when unknown. Executor-recorded attributes. Carries `job_output.status`, which marks a result written by a run that only partially succeeded. ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/results?limit=50" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} results_url = f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/results" cursor = None while True: params = {"limit": 100} if cursor: params["after"] = cursor response = requests.get(results_url, headers=headers, params=params) if response.status_code != 200: print(f"Error: {response.json()['errors']}") break page = response.json() for result in page["data"]: file_ref = result["data"] print(f"{result['port_name']}: {file_ref['filename']} -> {file_ref['ref']}") if not page["has_more"]: break # The cursor is opaque — pass it back verbatim. cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/results?limit=50`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { body.data.forEach(result => { console.log(`${result.port_name}: ${result.data.filename} -> ${result.data.ref}`); }); } else { console.error('Error:', body.errors); } ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "out_01jc9q9m6f", "port_name": "predictions", "data": { "ref": "https://", "filename": "predictions.ndjson", "file_extension": "ndjson", "file_type": null, "num_bytes": 48213, "file_attributes": { "job_output.status": "" } }, "expires_at": "2026-08-12T15:18:41Z", "created_at": "2026-08-11T15:18:41Z" } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 200 - Empty (no-op run) theme={"system"} { "data": [], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 400 - Invalid cursor theme={"system"} { "errors": [ { "code": "", "message": "Invalid cursor.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Agent not found theme={"system"} { "errors": [ { "code": "", "message": "Agent not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * The cursor here is **opaque** and is not a result ID. Pass `next_cursor` back verbatim; never derive it from `data[last].id`. * `ref` may be a presigned URL or a data-service ref — the latter must be downloaded through the authenticated proxy. * Check `file_attributes["job_output.status"]`: it marks a result written by a run that only partially succeeded. * A no-op run produces no outputs, so `data` comes back empty. # List Agent Events Source: https://docs.archetypeai.app/api-reference/agents/instances/list-agent-events GET /agents/instances/{agent_id}/events Page through an agent run's event log Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns a page of an agent's event log, newest first. Events are the agent-side log: an id, a three-level severity, a message, and a timestamp. For the executor's own log lines, use `GET /agents/instances/{agent_id}/logs`. ## Request Agent `agt_` id. Page size. Minimum `1`, maximum `1000`. Forward cursor: return events older than the one with this id. Pass the `next_cursor` of the previous page to fetch the next page. Mutually exclusive with `before`. Backward cursor: return events newer than the one with this id. Pass the `prev_cursor` of the current page to walk back. Mutually exclusive with `after`. ## Response The page, newest first. Each entry is an event. True when more events exist beyond this page in the direction of travel. Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is false. Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. ### Event object Event id — the keyset cursor value for `after`/`before`. Event severity for the agent event log: `info`, `warning`, or `error`. The event message. When the event was recorded (date-time). ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/events?limit=50" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Next Page theme={"system"} curl "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/events?after=evt_01jc9q9m2x" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} events_url = f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/events" cursor = None while True: params = {"limit": 100} if cursor: params["after"] = cursor response = requests.get(events_url, headers=headers, params=params) if response.status_code != 200: print(f"Error: {response.json()['errors']}") break page = response.json() for event in page["data"]: print(f"[{event['level']}] {event['created_at']} {event['message']}") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/events?limit=50`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { body.data.forEach(event => { console.log(`[${event.level}] ${event.created_at} ${event.message}`); }); } else { console.error('Error:', body.errors); } ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "evt_01jc9q9m2x", "level": "info", "message": "Run dispatched to executor.", "created_at": "2026-08-11T15:10:04Z" }, { "id": "evt_01jc9q8w7b", "level": "info", "message": "Run created.", "created_at": "2026-08-11T15:10:00Z" } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 200 - Empty page theme={"system"} { "data": [], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 400 - Invalid cursor theme={"system"} { "errors": [ { "code": "", "message": "Invalid cursor.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Agent not found theme={"system"} { "errors": [ { "code": "", "message": "Agent not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Pass the `next_cursor` of the previous page as `after` to fetch the next page, and the `prev_cursor` of the current page as `before` to walk back. * `after` and `before` are mutually exclusive — send at most one of them. * Events use the agent-side severity vocabulary (`info`, `warning`, `error`), which is narrower than the executor log levels returned by `/logs`. # List Agents Source: https://docs.archetypeai.app/api-reference/agents/instances/list-agents GET /agents/instances Page through agent runs, filtered by status, bundle, or blueprint Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated page of agents (bundle runs), newest first. An agent exists only as a run, so lifecycle status lives on the agent itself. Filter by status, by the bundle a run came from, or by the blueprint that bundle pinned. ## Request Page size. Minimum `1`, maximum `1000`. Forward cursor: return agents older than the one with this id. Pass the `next_cursor` of the previous page to fetch the next page. Mutually exclusive with `before`. Backward cursor: return agents newer than the one with this id. Pass the `prev_cursor` of the current page to walk back. Mutually exclusive with `after`. Filter to a single lifecycle status (e.g. `running`). Omit for all statuses. One of `running`, `paused`, `completed`, `failed`, `cancelled`. Case-insensitive substring match over the agent name, id, bundle id, and blueprint key. Omit for no search filter. Restrict to runs of this bundle (`bnd_` id, exact match). Restrict to runs whose bundle pins this blueprint (`blp_` id, exact match). ## Response The page, newest first. Each entry is an agent. True when more results exist beyond this page in the direction of travel. Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when you supplied `before`. `null` when `has_more` is false. Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. ### Agent object TypeID-encoded agent identifier (`agt_` prefix). Name of the agent (a run's name is its bundle's name). Organization identifier the agent belongs to. The bundle this agent was run from (provenance). Human-readable pinned blueprint reference (its key), e.g. `osm`. Immutable blueprint id the bundle pinned. Agent lifecycle status: `running`, `paused`, `completed`, `failed`, or `cancelled`. Creation timestamp (date-time). The I/O binding this run was started with; `null` when none is recorded. External executor's job id for the current run (a JOS `job_` id). Present once the run has been dispatched; lets clients query JOS for run progress. When the run started; `null` before then. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ```bash cURL - First Page theme={"system"} curl "$ATAI_API_URL/agents/instances?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Running Only theme={"system"} curl "$ATAI_API_URL/agents/instances?status=running" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Runs Of One Bundle theme={"system"} curl "$ATAI_API_URL/agents/instances?bundle_id=bnd_01jc9pd42kzq7v8n3h5m6rtx0w" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} cursor = None while True: params = {"limit": 100, "status": "running"} if cursor: params["after"] = cursor response = requests.get(f"{base_url}/agents/instances", headers=headers, params=params) page = response.json() for agent in page["data"]: print(f"{agent['id']} {agent['name']} [{agent['status']}] blueprint={agent['blueprint']}") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ limit: '20', status: 'running' }); const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const page = await response.json(); page.data.forEach(agent => { console.log(`${agent.id} ${agent.name} [${agent.status}] blueprint=${agent.blueprint}`); }); ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "name": "Pump A monitor", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "bundle_id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "blueprint": "osm", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "connectors": { "source": [ {"type": "file", "id": "file_abc123", "format": "csv"} ], "sink": null }, "status": "running", "job_id": "job_01jc9q9k4t8v2mnr5xh7bdzy3s", "created_at": "2026-08-11T15:10:00Z", "started_at": "2026-08-11T15:10:04Z", "completed_at": null, "error": null } ], "has_more": true, "next_cursor": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "prev_cursor": null } ``` ```json 200 - Empty page theme={"system"} { "data": [], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ## Important Notes * `after` and `before` are mutually exclusive — send at most one of them. * Results are ordered newest first in both cursor directions, so render `data` as returned. * `query` matches the agent name, id, bundle id, and blueprint key; `bundle_id` and `blueprint_id` are exact-match filters. # Pause Agent Source: https://docs.archetypeai.app/api-reference/agents/instances/pause-agent POST /agents/instances/{agent_id}/pause Pause a running agent Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint pauses a running agent and returns the updated agent with status `paused`. Only a `running` agent can be paused; anything else returns `409`. Resume it later with `POST /agents/instances/{agent_id}/resume`. ## Request Agent `agt_` id. ## Response Returns the paused agent. TypeID-encoded agent identifier (`agt_` prefix). Name of the agent (a run's name is its bundle's name). Organization identifier the agent belongs to. The bundle this agent was run from (provenance). Human-readable pinned blueprint reference (its key), e.g. `osm`. Immutable blueprint id the bundle pinned. Agent lifecycle status; `paused` after a successful pause. Creation timestamp (date-time). The I/O binding this run was started with; `null` when none is recorded. External executor's job id for the current run (a JOS `job_` id). Present once the run has been dispatched. When the run started; `null` before then. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ```bash cURL theme={"system"} curl -X POST "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/pause" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/pause", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 200: agent = response.json() print(f"Agent {agent['id']} is now {agent['status']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/pause`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`Agent ${body.id} is now ${body.status}`); } else { console.error('Error:', body.errors); } ``` ```json 200 - Agent paused theme={"system"} { "id": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "name": "Pump A monitor", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "bundle_id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "blueprint": "osm", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "connectors": { "source": [ {"type": "file", "id": "file_abc123", "format": "csv"} ], "sink": null }, "status": "paused", "job_id": "job_01jc9q9k4t8v2mnr5xh7bdzy3s", "created_at": "2026-08-11T15:10:00Z", "started_at": "2026-08-11T15:10:04Z", "completed_at": null, "error": null } ``` ```json 404 - Agent not found theme={"system"} { "errors": [ { "code": "", "message": "Agent not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Agent not running theme={"system"} { "errors": [ { "code": "", "message": "Agent not running.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Pause is valid only from `running`. Calling it on a paused or terminal agent returns `409`. * A paused agent can be resumed or cancelled. # Query Agent Source: https://docs.archetypeai.app/api-reference/agents/instances/query-agent POST /agents/instances/{agent_id}/query Send a serving agent a payload and get its answer Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint sends a payload to a running serving agent and returns its answer. The body is whatever the blueprint's source connector accepts, and the answer is whatever its sink produces — the platform passes both through unchanged and wraps the answer in the fields every serving agent reports the same way. ## Request Serving agent `agt_` id to query. Whatever the agent's source connector accepts. The shape belongs to the blueprint, not to this endpoint — see the blueprint's source connector for what it takes. ## Response Whether the query produced an answer: `completed` or `failed`. Over HTTP the status line already says so, and this is only ever `completed`; the `failed` value exists for the `/connect` frame protocol, where there is no status line. The agent's answer, passed through as it came back. Opaque to the platform — its shape belongs to the blueprint's connectors. Total server-side time, in milliseconds. ```bash cURL theme={"system"} curl -X POST "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/query" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "records": [ {"timestamp": "2026-09-18T11:24:03Z", "vibration": 0.41, "flow": 12.6} ] }' ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/query", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "records": [ {"timestamp": "2026-09-18T11:24:03Z", "vibration": 0.41, "flow": 12.6} ] }, ) if response.status_code == 200: body = response.json() print(f"{body['status']} in {body['query_response_time_ms']} ms") print(body["response"]) else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/query`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ records: [ { timestamp: '2026-09-18T11:24:03Z', vibration: 0.41, flow: 12.6 } ] }) } ); const body = await response.json(); if (response.ok) { console.log(`${body.status} in ${body.query_response_time_ms} ms`); console.log(body.response); } else { console.error('Error:', body.errors); } ``` ```json 200 - The agent's answer theme={"system"} { "status": "completed", "response": { "predicted_state": "running", "p_running": 0.94, "p_idle": 0.06 }, "query_response_time_ms": 38.4 } ``` ```json 404 - No agent with this id theme={"system"} { "errors": [ { "code": "", "message": "No agent with this id in the caller's org.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Not a running serving agent theme={"system"} { "errors": [ { "code": "", "message": "The agent was not run in serving mode, or is no longer running.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Start the agent with `mode: serving` on `POST /agents/bundles/{bundle_id}/run`. A `batch` run never answers this endpoint. * Both the request body and `response` are opaque to the platform: their shapes are the blueprint's source and sink connectors, not this endpoint's. * A `404` covers both an unknown id and one belonging to another organization — the two are indistinguishable by design. * Use `GET /agents/instances/{agent_id}/connect` when you want one open session for many payloads instead of a request per payload. # Resume Agent Source: https://docs.archetypeai.app/api-reference/agents/instances/resume-agent POST /agents/instances/{agent_id}/resume Resume a paused agent Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint resumes a paused agent and returns the updated agent with status `running`. Only a `paused` agent can be resumed; anything else returns `409`. ## Request Agent `agt_` id. ## Response Returns the resumed agent. TypeID-encoded agent identifier (`agt_` prefix). Name of the agent (a run's name is its bundle's name). Organization identifier the agent belongs to. The bundle this agent was run from (provenance). Human-readable pinned blueprint reference (its key), e.g. `osm`. Immutable blueprint id the bundle pinned. Agent lifecycle status; `running` after a successful resume. Creation timestamp (date-time). The I/O binding this run was started with; `null` when none is recorded. External executor's job id for the current run (a JOS `job_` id). Present once the run has been dispatched. When the run started; `null` before then. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ```bash cURL theme={"system"} curl -X POST "$ATAI_API_URL/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/resume" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/resume", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 200: agent = response.json() print(f"Agent {agent['id']} is now {agent['status']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/instances/agt_01jc9q8v5nm3ry7t2bkz4dhs6f/resume`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`Agent ${body.id} is now ${body.status}`); } else { console.error('Error:', body.errors); } ``` ```json 200 - Agent resumed theme={"system"} { "id": "agt_01jc9q8v5nm3ry7t2bkz4dhs6f", "name": "Pump A monitor", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "bundle_id": "bnd_01jc9pd42kzq7v8n3h5m6rtx0w", "blueprint": "osm", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "connectors": { "source": [ {"type": "file", "id": "file_abc123", "format": "csv"} ], "sink": null }, "status": "running", "job_id": "job_01jc9q9k4t8v2mnr5xh7bdzy3s", "created_at": "2026-08-11T15:10:00Z", "started_at": "2026-08-11T15:10:04Z", "completed_at": null, "error": null } ``` ```json 404 - Agent not found theme={"system"} { "errors": [ { "code": "", "message": "Agent not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Agent not paused theme={"system"} { "errors": [ { "code": "", "message": "Agent not paused.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Resume is valid only from `paused`. Calling it on a running or terminal agent returns `409`. * Pause and resume move an agent back and forth between `running` and `paused`; neither is terminal. # List Node Registry Source: https://docs.archetypeai.app/api-reference/agents/nodes/list-node-registry GET /agents/nodes/registry List the nodes available for building blueprints Requires [version 1.1.9](/release-notes/1.1.x#v1-1-9) or later of the Archetype platform. ## Overview This endpoint returns the nodes available in the configured `agent_core` registry, split into `connectors` (sources and sinks) and `nodes` (everything else). Each list is sorted by node key. Use it to discover the node `key` values a blueprint's `connectors`/`nodes` maps can reference, along with each node's port contract, config schema, and default config. ## Request This endpoint takes no parameters. ## Response Registered source/sink nodes, sorted by node key. Every other registered node, sorted by node key. ### Node object The node key referenced from a blueprint's `connectors`/`nodes`. Description of the node. The node's input and output ports (sorted by port name). Input ports, each with a `name` and a `type`. Output ports, each with a `name` and a `type`. JSON Schema for the node's config (`{}` when the node takes no config). The node's default config as a JSON object. ### Port object Name of the port. The port's data type, e.g. `Record` or `Window`. ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/nodes/registry" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.get( f"{base_url}/agents/nodes/registry", headers={"Authorization": f"Bearer {api_key}"}, ) registry = response.json() for section in ("connectors", "nodes"): print(f"{section}:") for node in registry[section]: inputs = ", ".join(p["name"] for p in node["contract"]["inputs"]) or "-" outputs = ", ".join(p["name"] for p in node["contract"]["outputs"]) or "-" print(f" {node['key']}: in=[{inputs}] out=[{outputs}]") ``` ```javascript JavaScript theme={"system"} const response = await fetch(`${process.env.ATAI_API_URL}/agents/nodes/registry`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const registry = await response.json(); ['connectors', 'nodes'].forEach(section => { console.log(`${section}:`); registry[section].forEach(node => { const inputs = node.contract.inputs.map(p => p.name).join(', ') || '-'; const outputs = node.contract.outputs.map(p => p.name).join(', ') || '-'; console.log(` ${node.key}: in=[${inputs}] out=[${outputs}]`); }); }); ``` ```json 200 - Success theme={"system"} { "connectors": [ { "key": "", "description": "Reads records from an external data ref.", "contract": { "inputs": [], "outputs": [ {"name": "out", "type": "Record"} ] }, "config_schema": {}, "default_config": {} } ], "nodes": [ { "key": "", "description": "Groups records into windows.", "contract": { "inputs": [ {"name": "in", "type": "Record"} ], "outputs": [ {"name": "out", "type": "Window"} ] }, "config_schema": { "type": "object", "properties": {} }, "default_config": {} } ] } ``` ## Important Notes * A blueprint document must place each entry in the right section: connectors under `connectors`, everything else under `nodes`. Registration validates this. * `config_schema` is `{}` when a node takes no config. * Port `type` values (e.g. `Record`, `Window`) determine which nodes can be wired together in a blueprint's `graph.edges`. # Cancel Optimization Source: https://docs.archetypeai.app/api-reference/agents/optimizations/cancel-optimization POST /agents/optimizations/{optimization_id}/cancel Cancel a pending or running optimization run Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint cancels a pending or running optimization and returns it in its `cancelled` state. It also cancels any non-terminal trials, so the trial list does not leave a stale row behind. Trials that had already completed keep their results and stay counted in `progress.completed`. A run that is already terminal — that is, one whose `status` is one of `completed`, `failed`, or `cancelled` — has nothing to cancel and returns HTTP status code `409`. One use case for this endpoint is to cancel a running optimization prior to deleting it using [Delete Optimization](/api-reference/agents/optimizations/delete-optimization), since deleting an optimization will fail with a `409` HTTP status code if its state is non-terminal. ## Request Optimization `opt_` id. ## Response Returns the cancelled run, in the same format returned by [Get Optimization](/api-reference/agents/optimizations/get-optimization). TypeID-encoded optimization identifier (`opt_` prefix). Human label for the run. Organization identifier the run belongs to. The blueprint being searched. The primary metric name that was being maximized. The parameter space the run sampled from. The run's budget knobs — `max_trials`. The scoring examples as resolved. Optimization lifecycle status; `cancelled` after a successful cancel. Per-status trial counts. Trials that were still pending or running move to `cancelled`. Subject id (`usr_...` or `key_...`) that created this run. Creation timestamp (date-time). The trial the run picked as its winner. Set by the promotion step on successful completion, so it is `null` on a cancelled run. When the run started; `null` if it never did. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ```bash cURL theme={"system"} curl -X POST "$ATAI_API_URL/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w/cancel" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w/cancel", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 200: run = response.json() print(f"{run['id']} is now {run['status']}") elif response.status_code == 409: print("Optimization already terminal") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w/cancel`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { console.log(`${body.id} is now ${body.status}`); } else if (response.status === 409) { console.error('Optimization already terminal'); } else { console.error('Error:', body.errors); } ``` ```json 200 - Optimization cancelled theme={"system"} { "id": "opt_01jcb1m3t7v5xq8nr2h6kdzs4w", "name": "Window size sweep", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "objective": "macro_f1", "search_space": { "parameters": { "window_size": { "kind": "value", "spec": {"type": "categorical", "values": [512, 1024, 2048]} } } }, "budget": {"max_trials": 24}, "constraints": null, "training_examples": null, "calibration_examples": null, "validation_examples": [ { "name": "file_def456", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_def456", "format": "csv", "crc32c": "AAAAAA=="} ] } ], "status": "cancelled", "progress": { "pending": 0, "running": 0, "completed": 12, "failed": 0, "cancelled": 12, "infeasible": 2 }, "best_trial_id": null, "created_by": "usr_01jc8m4p3rt6vx9qn2h5kdzb7y", "created_at": "2026-09-18T12:02:44Z", "started_at": "2026-09-18T12:02:51Z", "completed_at": null, "error": null } ``` ```json 404 - Optimization not found theme={"system"} { "errors": [ { "code": "", "message": "Optimization not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Optimization already terminal theme={"system"} { "errors": [ { "code": "", "message": "Optimization already terminal.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Create Optimization Source: https://docs.archetypeai.app/api-reference/agents/optimizations/create-optimization POST /agents/optimizations Start a hyperparameter search over a blueprint Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint creates and starts an optimization run over a blueprint. It returns immediately with the run's ID and a `pending` status. The platform drives it to `completed`, `failed`, or `cancelled` through its controller; poll [Get Optimization](/api-reference/agents/optimizations/get-optimization) to observe progress and the winning trial. A run samples points from `search_space`, fits and scores a trial at each one, and maximizes `objective` — a metric name the blueprint's metrics schema declares. Every trial's eval scores against `validation_examples`. Trials that violate `constraints` are marked infeasible and are excluded from the winner. The three example sets play different roles: `training_examples` feed the fit and are never scored, `validation_examples` are what every trial's eval scores against, and `calibration_examples` are a family-specific held-out slice. A trial that violates any `min_metric` constraint is marked `feasible: false` and cannot win, but it is still promotable if you prefer it over the winner. The run does not publish a blueprint per trial. Materialize the one you want with the [Promote Trial](/api-reference/agents/optimizations/promote-trial) endpoint. ## Request The blueprint to search — a `blp_` ID. Must be visible to the caller's organization. Primary metric name to maximize. Must be one of the objectives declared by the blueprint's metrics schema. Budget knobs for the run. * `max_trials` (integer, required) — how many trials the run may create. Minimum `1`. Scoring examples — every trial's eval scores against these. Each entry is an example, in the same shape [Create Eval](/api-reference/agents/evals/create-eval) accepts. Human label for this run. The parameter space to sample from. Keys must match tunable blueprint values (`values.*`). Fit examples. Omit when the blueprint's fit needs no external training data — a Task Verification Agent or Manual Generation Agent run tuning inference-time knobs, for example. Consumed by the fit, never scored. Omit `training_examples` when the blueprint's fit needs no external training data. Calibration examples: a family-specific held-out slice, e.g. Activity Detection threshold calibration. Per-trial feasibility constraints. A trial that fails any of them is marked `feasible: false` and excluded from `best_trial_id`. * `min_metric` (array) — "the trial's `metric` must be ≥ `min_value`" checks. ### Search space (`search_space`) Each entry names a parameter, the values it can take, and where the sampled value plugs in at trial time. Parameter name to entry. The name is the destination key inside the entry's `kind` bucket at trial time. Which override kind the sampled value writes to: `value`, `model`, or `fitting`. Each maps to a distinct argument the training / eval resolution consumes. The domain the sampler draws from. One of three forms: * `{"type": "categorical", "values": [...]}` — a fixed set to sample from, e.g. `["Uniform", "Distance"]` or `[512, 1024, 2048]`. Each value is an integer or a string. * `{"type": "int_range", "min": 16, "max": 1024}` — an integer range, both bounds inclusive. * `{"type": "float_range", "min": 0.01, "max": 0.5}` — a float range, both bounds inclusive. ### Metric threshold (`constraints.min_metric[]`) Metric name — must be a value the trial's metrics report emits, e.g. `macro_f1` or `recall`. Minimum acceptable value, inclusive. When set, the threshold applies to this class's per-class value of `metric` — class `fault_bearing` recall, for example. Unset applies it to the aggregate. ## Response Returns `201 Created` with the run in `pending` status. See [Get Optimization](/api-reference/agents/optimizations/get-optimization) for the full field list. TypeID-encoded optimization identifier (`opt_` prefix). Human label for the run. Organization identifier the run belongs to. The blueprint being searched. The primary metric name being maximized. `objective` must be one of the objectives the blueprint's metrics schema declares; a blueprint publishing no metrics catalog cannot be optimized. The parameter space the run samples from. The run's budget knobs. The scoring examples as resolved: named, their inputs pinned with the CRC32C of the bytes used, and their ground-truth declarations filled in from the blueprint's defaults. Optimization lifecycle status: `pending`, `running`, `completed`, `failed`, or `cancelled`. Per-status trial counts, so a caller can render a progress bar without listing trials. All zero on a fresh run. Subject id (`usr_...` or `key_...`) that created this run. Creation timestamp (date-time). Set by the promotion step on successful completion; the trial the run picked as its winner. The fit examples as resolved; `null` when the run supplied none. The calibration examples as resolved; `null` when the run supplied none. The per-trial feasibility constraints; `null` when the run supplied none. When the run started; `null` before then. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ```bash cURL theme={"system"} curl -X POST "$ATAI_API_URL/agents/optimizations" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Window size sweep", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "objective": "macro_f1", "budget": {"max_trials": 24}, "search_space": { "parameters": { "window_size": { "kind": "value", "spec": {"type": "categorical", "values": [512, 1024, 2048]} }, "n_neighbors": { "kind": "fitting", "spec": {"type": "int_range", "min": 3, "max": 25} } } }, "constraints": { "min_metric": [ {"metric": "recall", "class": "fault_bearing", "min_value": 0.8} ] }, "training_examples": [ {"inputs": [{"type": "file", "id": "file_abc123", "format": "csv"}]} ], "validation_examples": [ {"inputs": [{"type": "file", "id": "file_def456", "format": "csv"}]} ] }' ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.post( f"{base_url}/agents/optimizations", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "name": "Window size sweep", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "objective": "macro_f1", "budget": {"max_trials": 24}, "search_space": { "parameters": { "window_size": { "kind": "value", "spec": {"type": "categorical", "values": [512, 1024, 2048]}, }, "n_neighbors": { "kind": "fitting", "spec": {"type": "int_range", "min": 3, "max": 25}, }, } }, "training_examples": [ {"inputs": [{"type": "file", "id": "file_abc123", "format": "csv"}]} ], "validation_examples": [ {"inputs": [{"type": "file", "id": "file_def456", "format": "csv"}]} ], }, ) if response.status_code == 201: run = response.json() print(f"Created {run['id']} ({run['status']}) maximising {run['objective']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch(`${process.env.ATAI_API_URL}/agents/optimizations`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'Window size sweep', blueprint_id: 'blp_01jc9n7k3xf8mbq2v5t0ary6de', objective: 'macro_f1', budget: { max_trials: 24 }, search_space: { parameters: { window_size: { kind: 'value', spec: { type: 'categorical', values: [512, 1024, 2048] } }, n_neighbors: { kind: 'fitting', spec: { type: 'int_range', min: 3, max: 25 } } } }, training_examples: [ { inputs: [{ type: 'file', id: 'file_abc123', format: 'csv' }] } ], validation_examples: [ { inputs: [{ type: 'file', id: 'file_def456', format: 'csv' }] } ] }) }); const body = await response.json(); if (response.status === 201) { console.log(`Created ${body.id} (${body.status}) maximising ${body.objective}`); } else { console.error('Error:', body.errors); } ``` ```json 201 - Created theme={"system"} { "id": "opt_01jcb1m3t7v5xq8nr2h6kdzs4w", "name": "Window size sweep", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "objective": "macro_f1", "search_space": { "parameters": { "window_size": { "kind": "value", "spec": {"type": "categorical", "values": [512, 1024, 2048]} }, "n_neighbors": { "kind": "fitting", "spec": {"type": "int_range", "min": 3, "max": 25} } } }, "budget": {"max_trials": 24}, "constraints": { "min_metric": [ {"metric": "recall", "class": "fault_bearing", "min_value": 0.8} ] }, "training_examples": [ { "name": "file_abc123", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_abc123", "format": "csv", "crc32c": "AAAAAA=="} ] } ], "calibration_examples": null, "validation_examples": [ { "name": "file_def456", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_def456", "format": "csv", "crc32c": "AAAAAA=="} ] } ], "status": "pending", "progress": { "pending": 0, "running": 0, "completed": 0, "failed": 0, "cancelled": 0, "infeasible": 0 }, "best_trial_id": null, "created_by": "usr_01jc8m4p3rt6vx9qn2h5kdzb7y", "created_at": "2026-09-18T12:02:44Z", "started_at": null, "completed_at": null, "error": null } ``` ```json 400 - Invalid request theme={"system"} { "errors": [ { "code": "", "message": "Invalid request.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Blueprint not found theme={"system"} { "errors": [ { "code": "", "message": "Blueprint not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Delete Optimization Source: https://docs.archetypeai.app/api-reference/agents/optimizations/delete-optimization DELETE /agents/optimizations/{optimization_id} Delete a terminal optimization run and its trials Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint deletes a terminal optimization and its trials. Only a terminal run; that is, one whose status is `completed`, `failed`, or `cancelled` can be deleted. Anything else returns an HTTP status code `409`. The winner-promoted blueprint, if any, is a separate row and is left in place — deleting the run that produced it does not remove it from the catalog. Deleting an optimization run also deletes its completed trials. A blueprint promoted from one of those trials is a separate row and survives. A run that is still `pending` or `running` returns `409`. Cancel it first using the [Cancel Optimization](/api-reference/agents/optimizations/cancel-optimization) endpoint. ## Request Optimization `opt_` ID. ## Response Returns `204 No Content` with an empty body on success. Check the status code rather than parsing a response. ```bash cURL theme={"system"} curl -X DELETE "$ATAI_API_URL/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] response = requests.delete( f"{base_url}/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w", headers={"Authorization": f"Bearer {api_key}"}, ) if response.status_code == 204: print("Optimization deleted") elif response.status_code == 409: print("Optimization is not terminal — cancel it first") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); if (response.status === 204) { console.log('Optimization deleted'); } else if (response.status === 409) { console.error('Optimization is not terminal — cancel it first'); } else { const body = await response.json(); console.error('Error:', body.errors); } ``` ```json 204 - Optimization deleted theme={"system"} ``` ```json 404 - Optimization not found theme={"system"} { "errors": [ { "code": "", "message": "Optimization not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Optimization is not in a terminal state theme={"system"} { "errors": [ { "code": "", "message": "Optimization is not in a terminal state (cancel it first).", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Get Optimization Source: https://docs.archetypeai.app/api-reference/agents/optimizations/get-optimization GET /agents/optimizations/{optimization_id} Retrieve one optimization run and its trial-status breakdown Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint returns one optimization run by its `opt_` ID, with a trial-status breakdown so a caller can render a progress bar without listing trials. Poll it to follow a run from `pending` through `running` to `completed`, `failed`, or `cancelled`, and to read `best_trial_id` once the run has picked a winner. The winning trial is *not* automatically promoted into a blueprint. To promote the winning trial once the run is complete, use the [Promote Trial](/api-reference/agents/optimizations/promote-trial) endpoint to promote the trial whose ID is found in `best_trial_id`. Returns a `404` HTTP status code both when the specified optimization ID is unknown and when it belongs to another organization. These two cases are intentionally indistinguishable. ## Request Optimization `opt_` ID. ## Response TypeID-encoded optimization identifier (`opt_` prefix). Human label for the run. Organization identifier the run belongs to. The blueprint being searched. The primary metric name being maximized. The parameter space the run samples from: `parameters`, a map of parameter name to an entry carrying a `kind` (`value`, `model`, or `fitting`) and a `spec` domain. The run's budget knobs — `max_trials`. The scoring examples as resolved: named, their inputs pinned with the CRC32C of the bytes used, and their ground-truth declarations filled in from the blueprint's defaults. Optimization lifecycle status: `pending`, `running`, `completed`, `failed`, or `cancelled`. Per-status trial counts, so a caller can render a progress bar without listing trials. All zero on a fresh run. For the per-trial details behind `progress`, page the results from the [List Optimization Trials](/api-reference/agents/optimizations/list-optimization-trials) endpoint. Subject id (`usr_...` or `key_...`) that created this run. Creation timestamp (date-time). Set upon successful completion to indicate the feasible trial the run picked as its winner. This value is `null` for non-terminal optimization runs. The trial specified by `best_trial_id` is *not* automatically promoted into a blueprint. To do so, you must explicitly send the value of `best_trial_id` to the [Promote Trial](/api-reference/agents/optimizations/promote-trial) endpoint as the value of its `trial_id` parameter. The fit examples as resolved; `null` when the run supplied none. The calibration examples as resolved; `null` when the run supplied none. The per-trial feasibility constraints; `null` when the run supplied none. When the run started; `null` before then. When the run finished; `null` while unfinished. Failure detail; `null` unless the run failed. ### Progress object (`progress`) Every trial ever created for the run is counted; a completed trial stays in `completed` after the run itself moves on. To get the total number of trials created for the run, calculate `pending + running + completed + failed + cancelled`. Do not add `infeasible` as part of this calculation; infeasible trials are included in `completed`. The number of trials created but not yet dispatched. The number of trials currently running. The number of trials that finished successfully. The number of trials that failed. The number of trials that were cancelled. The number of trials that reached `completed` but violated the run's feasibility constraints. Not eligible to win. This bucket overlaps `completed` — such a trial is counted in both. No other bucket overlaps. ```bash cURL theme={"system"} curl "$ATAI_API_URL/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import time import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} optimization_id = "opt_01jcb1m3t7v5xq8nr2h6kdzs4w" while True: response = requests.get(f"{base_url}/agents/optimizations/{optimization_id}", headers=headers) run = response.json() progress = run["progress"] done = progress["completed"] + progress["failed"] + progress["cancelled"] print(f"{run['status']}: {done}/{run['budget']['max_trials']} trials, {progress['infeasible']} infeasible") if run["status"] in ("completed", "failed", "cancelled"): break time.sleep(15) if run["best_trial_id"]: print(f"Winner: {run['best_trial_id']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( `${process.env.ATAI_API_URL}/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const body = await response.json(); if (response.ok) { const { completed, failed, cancelled, infeasible } = body.progress; const done = completed + failed + cancelled; console.log(`${body.status}: ${done}/${body.budget.max_trials} trials, ${infeasible} infeasible`); if (body.best_trial_id) { console.log(`Winner: ${body.best_trial_id}`); } } else { console.error('Error:', body.errors); } ``` ```json 200 - Completed theme={"system"} { "id": "opt_01jcb1m3t7v5xq8nr2h6kdzs4w", "name": "Window size sweep", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "objective": "macro_f1", "search_space": { "parameters": { "window_size": { "kind": "value", "spec": {"type": "categorical", "values": [512, 1024, 2048]} }, "n_neighbors": { "kind": "fitting", "spec": {"type": "int_range", "min": 3, "max": 25} } } }, "budget": {"max_trials": 24}, "constraints": { "min_metric": [ {"metric": "recall", "class": "fault_bearing", "min_value": 0.8} ] }, "training_examples": [ { "name": "file_abc123", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_abc123", "format": "csv", "crc32c": "AAAAAA=="} ] } ], "calibration_examples": null, "validation_examples": [ { "name": "file_def456", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_def456", "format": "csv", "crc32c": "AAAAAA=="} ] } ], "status": "completed", "progress": { "pending": 0, "running": 0, "completed": 22, "failed": 2, "cancelled": 0, "infeasible": 5 }, "best_trial_id": "otr_01jcb2v9h4x7mq3nt8k5rdzy6w", "created_by": "usr_01jc8m4p3rt6vx9qn2h5kdzb7y", "created_at": "2026-09-18T12:02:44Z", "started_at": "2026-09-18T12:02:51Z", "completed_at": "2026-09-18T13:47:05Z", "error": null } ``` ```json 404 - Optimization not found theme={"system"} { "errors": [ { "code": "", "message": "Optimization not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # List Optimization Trials Source: https://docs.archetypeai.app/api-reference/agents/optimizations/list-optimization-trials GET /agents/optimizations/{optimization_id}/trials Page through one optimization run's trials, optionally filtered by status Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of one run's trials. Trials are listed newest first — highest `trial_number` first — regardless of which direction you're paging through them. A trial records the point it sampled from the parent's search space, what that point scored, and whether it satisfied the run's feasibility constraints. A trial's state moves independently from the parent: a failed trial does not fail the run. Returns a `404` HTTP status code both when the specified optimization ID is unknown and when it belongs to another organization. These two cases are intentionally indistinguishable from one another. ## Request Parent optimization `opt_` id. Page size. Minimum `1`, maximum `1000`. Forward cursor: return trials with a lower `trial_number` than this one. Pass the `next_cursor` of the previous page to fetch the next page. Mutually exclusive with `before`. Backward cursor: return trials with a higher `trial_number` than this one. Pass the `prev_cursor` of the current page to walk back. Mutually exclusive with `after`. Filter to a single lifecycle status. Omit for all statuses. One of `pending`, `running`, `completed`, `failed`, `cancelled`. ## Response The page, newest trial first (highest `trial_number`). True when more results exist beyond this page in the direction of travel. Cursor to continue in the direction of travel: pass as `after` on a forward page, as `before` when the request used `before`. `null` when `has_more` is false. Cursor to step back the way the page was reached. `null` when the request carried no cursor. ### Trial object Fields beyond the always-present ones fill in as the trial advances: `started_at` when it dispatches, `metrics_report` / `objective_value` / `feasible` / `completed_at` on success, `error` on failure. TypeID-encoded trial identifier (`otr_` prefix). The parent run's `opt_` id. 1-based ordinal within the parent run. Dense and deterministic. The sampled point in the parent's search space, as `{parameter_name: value}`. Opaque shape — the value's type varies per parameter and is defined by the parent's `search_space`. Trial lifecycle status: `pending`, `running`, `completed`, `failed`, or `cancelled`. Creation timestamp (date-time). Convenience projection of `metrics_report`'s objective value. `null` until the trial has scored. Feasibility against the parent's `constraints`. `null` while pending; only `true` trials qualify for the parent's `best_trial_id`. Only trials for which `feasible` is `true` qualify to be selected as the `best_trial_id`. However, you *can* promote infeasible trials. Whether or not that's a good idea is your decision. The trial's scored metrics report, in the same shape an eval returns. `null` until the trial has scored. When the trial dispatched; `null` before then. When the trial finished; `null` while unfinished. Failure details if the trial failed; otherwise `null`. ```bash cURL - First Page theme={"system"} curl "$ATAI_API_URL/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w/trials?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Completed Only theme={"system"} curl "$ATAI_API_URL/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w/trials?status=completed" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} optimization_id = "opt_01jcb1m3t7v5xq8nr2h6kdzs4w" cursor = None while True: params = {"limit": 100, "status": "completed"} if cursor: params["after"] = cursor response = requests.get( f"{base_url}/agents/optimizations/{optimization_id}/trials", headers=headers, params=params, ) page = response.json() for trial in page["data"]: mark = "" if trial["feasible"] else " (infeasible)" print(f"#{trial['trial_number']:>3} {trial['objective_value']} {trial['trial_values']}{mark}") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ limit: '20', status: 'completed' }); const response = await fetch( `${process.env.ATAI_API_URL}/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w/trials?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const page = await response.json(); page.data.forEach(trial => { const mark = trial.feasible ? '' : ' (infeasible)'; console.log(`#${trial.trial_number} ${trial.objective_value} ${JSON.stringify(trial.trial_values)}${mark}`); }); ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "otr_01jcb2v9h4x7mq3nt8k5rdzy6w", "optimization_id": "opt_01jcb1m3t7v5xq8nr2h6kdzs4w", "trial_number": 24, "trial_values": {"window_size": 1024, "n_neighbors": 11}, "status": "completed", "objective_value": 0.89, "feasible": true, "metrics_report": { "schema_version": "v1", "primary": {"target": "state", "name": "macro_f1", "value": 0.89}, "targets": { "state": { "type": "category", "aggregate": {"macro_f1": 0.89, "accuracy": 0.93}, "class_names": ["running", "idle", "fault_bearing"], "per_class": { "precision": [0.94, 0.9, 0.79], "recall": [0.97, 0.87, 0.82], "f1": [0.95, 0.88, 0.8], "support": [4120, 1880, 260] }, "confusion_matrix": [ [3996, 106, 18], [199, 1636, 45], [31, 16, 213] ] } } }, "created_at": "2026-09-18T13:38:12Z", "started_at": "2026-09-18T13:38:20Z", "completed_at": "2026-09-18T13:47:01Z", "error": null }, { "id": "otr_01jcb2t4k9r2wq6nv8h3mdzx5p", "optimization_id": "opt_01jcb1m3t7v5xq8nr2h6kdzs4w", "trial_number": 23, "trial_values": {"window_size": 512, "n_neighbors": 4}, "status": "completed", "objective_value": 0.84, "feasible": false, "metrics_report": null, "created_at": "2026-09-18T13:29:44Z", "started_at": "2026-09-18T13:29:51Z", "completed_at": "2026-09-18T13:37:58Z", "error": null } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 400 - Invalid query parameter theme={"system"} { "errors": [ { "code": "", "message": "Invalid query parameter.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Optimization not found theme={"system"} { "errors": [ { "code": "", "message": "Optimization not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # List Optimizations Source: https://docs.archetypeai.app/api-reference/agents/optimizations/list-optimizations GET /agents/optimizations Page through optimization runs, optionally filtered by status, name, and/or blueprint Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of the caller's optimization runs, newest first. Each row carries the same trial-status breakdown as `GET /agents/optimizations/{optimization_id}` — the platform aggregates the whole page in a single query rather than fanning out per row, so a listing can render a progress bar per run without a read each. ## Request Page size. Minimum `1`, maximum `1000`. Forward cursor: return runs older than the one with this ID. Pass the `next_cursor` of the previous page to fetch the next page. Mutually exclusive with `before`. This parameter is mutually exclusive with `before`; using both results in an error. Backward cursor: return runs newer than the one with this ID. Pass the `prev_cursor` of the current page to walk back. Mutually exclusive with `after`. This parameter is mutually exclusive with `after`; using both results in an error. Filter to a single lifecycle status (e.g. `pending`, `completed`). Omit for all statuses. One of `pending`, `running`, `completed`, `failed`, `cancelled`. This is an exact-match filter. Case-insensitive substring match over the run name and ID. Omit for no search filter. Restrict to runs targeting the blueprint with the specified `blp_` ID. This is an exact-match filter. ## Response The page, ordered newest first. Each entry is an optimization run, in the same format [Get Optimization](/api-reference/agents/optimizations/get-optimization) returns. Pages are always sorted newest-first, so you should always render the contents of `data` as returned. Since each row in `data` includes a `progress` property that summarizes the progress that run is making, you don't need to perform a secondary lookup to get that information. `true` when more results exist beyond this page in the direction of travel. Cursor to continue in the direction of travel: pass as `after` on a forward page, as `before` when the request used `before`. `null` when `has_more` is false. Cursor to step back the way the page was reached. `null` when the request carried no cursor. ```bash cURL - First Page theme={"system"} curl "$ATAI_API_URL/agents/optimizations?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Running Only theme={"system"} curl "$ATAI_API_URL/agents/optimizations?status=running" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - One Blueprint theme={"system"} curl "$ATAI_API_URL/agents/optimizations?blueprint_id=blp_01jc9n7k3xf8mbq2v5t0ary6de" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] headers = {"Authorization": f"Bearer {api_key}"} cursor = None while True: params = {"limit": 100} if cursor: params["after"] = cursor response = requests.get(f"{base_url}/agents/optimizations", headers=headers, params=params) page = response.json() for run in page["data"]: progress = run["progress"] done = progress["completed"] + progress["failed"] + progress["cancelled"] print(f"{run['id']} {run['name']} [{run['status']}] {done}/{run['budget']['max_trials']}") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ limit: '20' }); const response = await fetch( `${process.env.ATAI_API_URL}/agents/optimizations?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const page = await response.json(); page.data.forEach(run => { const { completed, failed, cancelled } = run.progress; const done = completed + failed + cancelled; console.log(`${run.id} ${run.name} [${run.status}] ${done}/${run.budget.max_trials}`); }); ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "opt_01jcb1m3t7v5xq8nr2h6kdzs4w", "name": "Window size sweep", "org_id": "org_01jc8m5r2vq9xt4bn7h3kdzs6w", "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "objective": "macro_f1", "search_space": { "parameters": { "window_size": { "kind": "value", "spec": {"type": "categorical", "values": [512, 1024, 2048]} } } }, "budget": {"max_trials": 24}, "constraints": null, "training_examples": null, "calibration_examples": null, "validation_examples": [ { "name": "file_def456", "ordinal": 1, "inputs": [ {"type": "file", "id": "file_def456", "format": "csv", "crc32c": "AAAAAA=="} ] } ], "status": "running", "progress": { "pending": 9, "running": 3, "completed": 12, "failed": 0, "cancelled": 0, "infeasible": 2 }, "best_trial_id": null, "created_by": "usr_01jc8m4p3rt6vx9qn2h5kdzb7y", "created_at": "2026-09-18T12:02:44Z", "started_at": "2026-09-18T12:02:51Z", "completed_at": null, "error": null } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 200 - Empty page theme={"system"} { "data": [], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 400 - Invalid query parameter theme={"system"} { "errors": [ { "code": "", "message": "Invalid query parameter.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # Promote Trial Source: https://docs.archetypeai.app/api-reference/agents/optimizations/promote-trial POST /agents/optimizations/{optimization_id}/trials/{trial_id}/promote Publish one optimization trial as a blueprint of its own Requires [version 1.1.12](/release-notes/1.1.x#v1-1-12) or later of the Archetype platform. ## Overview This endpoint promotes one trial of an optimization to a blueprint of its own. An optimization does not publish a blueprint per trial — a run of hundreds of trials would bury your catalog, and most trials are never wanted. This endpoint materializes the one you pick: the searched blueprint with that trial's parameter values, model choices, and trained artifacts applied, so the result is a blueprint you can evaluate, package, or use as the base of another optimization by its returned `blueprint_id`. The new blueprint belongs to your organization and records where it came from in its `source` field — the blueprint that was searched, the overrides applied, and the trial that produced them. Only a `completed` trial can be promoted; attempting to promote a trial whose status has any other value will result in an HTTP `409` error. A trial that met none of the run's constraints is still promotable despite being classified as `infeasible` — the choice of which trade-off to ship is yours. Every field of the body is optional, so `{}` is a complete request. ## Request Parent optimization `opt_` id. Trial `otr_` id to promote. Key to publish the promoted blueprint under. Defaults to the searched blueprint's key suffixed with the trial's id, which is unique per trial; supply one to choose a friendlier handle. Rejected with `409` when your organization already has an active blueprint under this key. If you don't specify a `blueprint_key`, a key is generated by appending the trial's ID to the end of the searched blueprint's key. Promoting the same trial twice in this manner will respond with a `409` error rather than creating a duplicate. Name for the promoted blueprint. Defaults to the searched blueprint's. Must not be blank when supplied. Description for the promoted blueprint. Defaults to the searched blueprint's. ## Response Returns `201 Created` with the promoted blueprint, in the shape [Get Blueprint](/api-reference/agents/blueprints/get-blueprint) returns. TypeID-encoded blueprint identifier (`blp_` prefix) of the new blueprint. Use this blueprint ID as the `blueprint_id` for a new eval, another optimization, or to create a new bundle using [Create Bundle](/api-reference/agents/bundles/create-bundle). The key the promoted blueprint was published under. Name of the blueprint. Description of the blueprint. The blueprint document: the searched blueprint with the trial's parameter values, model choices, and trained artifacts applied. `false` — a promoted blueprint belongs to your organization, not the platform gallery. True for the current version of the key. Where this blueprint came from: the blueprint that was searched, the overrides applied, and the trial that produced them. The YAML rendering of the blueprint, when one is included. Creation timestamp (date-time). ### Source object (`source`) The blueprint this one was derived from — the one the optimization searched. Parameter value overrides applied on top of that blueprint's own. Model slot overrides applied on top of that blueprint's own. Artifact locations applied on top of that blueprint's own, keyed by artifact name. What produced this blueprint. * `id` (string, required) — the producer itself: the `otr_` id of the promoted trial. * `parent_id` (string, required) — the run it belonged to: the `opt_` id of the optimization. * `name` (string) — the human label of the enclosing run, when one was given to it. ```bash cURL - Generated Key theme={"system"} curl -X POST "$ATAI_API_URL/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w/trials/otr_01jcb2v9h4x7mq3nt8k5rdzy6w/promote" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{}' ``` ```bash cURL - Chosen Key And Name theme={"system"} curl -X POST "$ATAI_API_URL/agents/optimizations/opt_01jcb1m3t7v5xq8nr2h6kdzs4w/trials/otr_01jcb2v9h4x7mq3nt8k5rdzy6w/promote" \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "blueprint_key": "osm-pump-a", "name": "Open-set monitor (pump A)", "description": "Tuned on the September pump A sweep." }' ``` ```python Python theme={"system"} import os import requests base_url = os.environ["ATAI_API_URL"] api_key = os.environ["ATAI_API_KEY"] optimization_id = "opt_01jcb1m3t7v5xq8nr2h6kdzs4w" trial_id = "otr_01jcb2v9h4x7mq3nt8k5rdzy6w" response = requests.post( f"{base_url}/agents/optimizations/{optimization_id}/trials/{trial_id}/promote", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={"blueprint_key": "osm-pump-a", "name": "Open-set monitor (pump A)"}, ) if response.status_code == 201: blueprint = response.json() print(f"Promoted to {blueprint['id']} under key {blueprint['blueprint_key']}") else: print(f"Error: {response.json()['errors']}") ``` ```javascript JavaScript theme={"system"} const optimizationId = 'opt_01jcb1m3t7v5xq8nr2h6kdzs4w'; const trialId = 'otr_01jcb2v9h4x7mq3nt8k5rdzy6w'; const response = await fetch( `${process.env.ATAI_API_URL}/agents/optimizations/${optimizationId}/trials/${trialId}/promote`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ blueprint_key: 'osm-pump-a', name: 'Open-set monitor (pump A)' }) } ); const body = await response.json(); if (response.status === 201) { console.log(`Promoted to ${body.id} under key ${body.blueprint_key}`); } else { console.error('Error:', body.errors); } ``` ```json 201 - The promoted blueprint theme={"system"} { "id": "blp_01jcb3r7n8k5wq2vt6y0mdhx4s", "blueprint_key": "osm-pump-a", "name": "Open-set monitor (pump A)", "description": "Tuned on the September pump A sweep.", "document": { "blueprint_id": "blp_01jcb3r7n8k5wq2vt6y0mdhx4s", "name": "Open-set monitor (pump A)", "graph": {"edges": []}, "values": {"window_size": 1024}, "artifacts": {"fit-classifier": "s3://.../fit-classifier"} }, "yaml_document": null, "is_canonical": false, "is_active": true, "source": { "blueprint_id": "blp_01jc9n7k3xf8mbq2v5t0ary6de", "values": {"window_size": 1024}, "models": {}, "artifacts": {"fit-classifier": "s3://.../fit-classifier"}, "created_by": { "id": "otr_01jcb2v9h4x7mq3nt8k5rdzy6w", "parent_id": "opt_01jcb1m3t7v5xq8nr2h6kdzs4w", "name": "Window size sweep" } }, "created_at": "2026-09-18T14:05:38Z" } ``` ```json 400 - Invalid blueprint_key or empty name theme={"system"} { "errors": [ { "code": "", "message": "Invalid `blueprint_key`, or an empty `name`.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Optimization, trial, or searched blueprint not found theme={"system"} { "errors": [ { "code": "", "message": "Optimization, trial, or the searched blueprint not found.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Trial not completed, or key taken theme={"system"} { "errors": [ { "code": "", "message": "Trial has not completed, or its blueprint key is already taken.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` # About the Batch Processing API Source: https://docs.archetypeai.app/api-reference/batch/about An API to run and manage batch processing jobs against multiple files. The Batch Processing API uses the Jobs Orchestration Service (JOS) to run processing jobs against multiple files. JOS owns the entire lifecycle of the jobs it runs: it validates the configuration, manages job pipelines, handles Kubernetes resource management, monitors the progress of the job, and publishes events. For additional information, see [this Batch Processing overview](/core-concepts/batch-processing/overview). # List Job Events Source: https://docs.archetypeai.app/api-reference/batch/events/list-job-events GET /batch/jobs/{id}/events Retrieve a cursor-paginated list of events for a specific job Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of events emitted during job execution, newest first. Events provide observability into what happened during processing, including informational messages, warnings, errors, and terminal outcomes. ## Request The unique job identifier Filter events by level: `INFO`, `WARN`, `ERROR`, `SUCCESS`, or `FAILED`. Unknown values return `400`. Filter events by type (e.g., `inference.success`, `inference.failed`) Filter events associated with a specific input Page size, between `1` and `1000`. Clamped server-side. Forward cursor: return events recorded before the event with this ID. Pass the previous page's `next_cursor`. Mutually exclusive with `before` — sending both returns `400`. A malformed cursor also returns `400`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Backward cursor: return events recorded after the event with this ID. Pass the current page's `prev_cursor`. Mutually exclusive with `after`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response The job identifier Array of event objects, newest first in both cursor directions, each containing: * `id` — Unique event identifier * `event_type` — Type of event (e.g., `inference.success`) * `level` — Event level: `INFO`, `WARN`, `ERROR`, `SUCCESS`, or `FAILED` * `message` — Optional human-readable message * `payload` — Event-specific data * `input_id` — Associated input ID (if applicable) * `index` — Event index within the input (if applicable) * `created_at` — Event timestamp `true` when more events exist beyond this page in the direction of travel. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/events?level=ERROR&limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/events", headers={"Authorization": f"Bearer {api_key}"}, params={ "level": "ERROR", "limit": 20 } ) data = response.json() for event in data["data"]: print(f" [{event['level']}] {event['event_type']}: {event.get('message', '')}") # Pass the cursor back verbatim as `after` to fetch the next page. if data["has_more"]: print(f"Next page cursor: {data['next_cursor']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const params = new URLSearchParams({ level: 'ERROR', limit: '20' }); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/events?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); data.data.forEach(event => { console.log(` [${event.level}] ${event.event_type}: ${event.message || ''}`); }); if (data.has_more) { console.log(`Next page cursor: ${data.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "data": [ { "id": 1001, "event_type": "inference.success", "level": "SUCCESS", "message": "Inference completed for input", "payload": { "duration_ms": 1250 }, "input_id": "inp_abc123def456", "index": 0, "created_at": "2026-04-14T10:05:00Z" }, { "id": 1002, "event_type": "inference.failed", "level": "FAILED", "message": "Input file format not supported", "payload": { "error_code": "UNSUPPORTED_FORMAT" }, "input_id": "inp_ghi789jkl012", "index": 1, "created_at": "2026-04-14T10:05:30Z" } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 400 - Invalid Request theme={"system"} { "code": "...", "message": "...", "error_uid": "err_abc123" } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # Get Inputs Progress Counts Source: https://docs.archetypeai.app/api-reference/batch/io/get-inputs-progress-counts GET /batch/jobs/{id}/inputs/progress/counts Per-status counts of tracked inputs for a job Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview Returns per-status counts across the job's tracked (non-`reference`) inputs. Mirrors the `input_progress` field embedded on `GET /batch/jobs/{id}` but lets you scope by port. Cheaper than walking the input list to compute badges. ## Request The unique job identifier Scope the counts to a single input port (e.g. `worker.inference`) ## Response The job identifier Inputs not yet picked up by a worker Present when `total_bytes` is known and all processing inputs that have reported progress include the `input_bytes` metric. Otherwise, this property is absent. The value is the sum of the most recent `input_bytes` reported by all processing inputs, plus the file sizes (`num_bytes`) of all completed and failed inputs. The total file size across all tracked inputs, scoped to the `port_name` filter if provided. Present only when there's at least one tracked input and all sizes are known. Otherwise, this value is absent. Inputs currently being processed Inputs that finished successfully Inputs that finished with an error ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/inputs/progress/counts?port_name=worker.inference" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/inputs/progress/counts", headers={"Authorization": f"Bearer {api_key}"}, params={"port_name": "worker.inference"}, ) counts = response.json() print(f" pending={counts['pending']} processing={counts['processing']} " f"completed={counts['completed']} failed={counts['failed']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const params = new URLSearchParams({ port_name: 'worker.inference' }); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/inputs/progress/counts?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const counts = await response.json(); console.log(`pending=${counts.pending} processing=${counts.processing} completed=${counts.completed} failed=${counts.failed}`); ``` ```json 200 - Success theme={"system"} { "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "pending": 0, "processing": 1, "completed": 8, "failed": 1, "processed_bytes": 40551733, "total_bytes": 105332974 } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # Get Inputs Progress Traces Source: https://docs.archetypeai.app/api-reference/batch/io/get-inputs-progress-traces GET /batch/jobs/{id}/inputs/progress/traces Bucketed cumulative file and per-kind item counters across the job lifetime Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview Returns a fixed-resolution time series of cumulative file completions/failures (from `job_inputs`) and per-kind cumulative item counters (from `job_progress.metrics`) over the job's lifetime. Suitable for backing a job-progress chart. `t` is the **end** of each bucket; the last point sits at the job's terminal timestamp (or `now()` for live jobs). The response supports `If-None-Match` — when the cached representation is still current, the endpoint returns `304 Not Modified`, letting polling clients short-circuit chart redraws. ## Request The unique job identifier Number of bucket points to return. Clamped to `[10, 1000]`; defaults to `100`. ## Response The job identifier Width of each bucket, in seconds Timestamp of the most recent underlying event — `MAX` over `job_progress.created_at` and `job_inputs.completed_at`. `null` when the job has neither finished any inputs nor emitted any progress. Lets polling clients short-circuit redraws when nothing has changed since the previous poll. Trace points, each containing: * `t` — RFC 3339 timestamp at the bucket end * `step` — Total finished inputs (`completed + failed`) at the bucket end. Matches the `step` from [List Inputs With Progress](/api-reference/batch/io/list-inputs-progress) — a 1-indexed completion rank across the job * `files` — Cumulative file-level counts at the bucket end: `{ "completed": int, "failed": int }` * `items` — Per-kind cumulative item counters from `job_progress.metrics`. Keys are the distinct `job_progress.kind` values observed for the job; values are `{ "success": int, "failed": int }`. Empty when no progress has been emitted yet. ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/inputs/progress/traces?buckets=50" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/inputs/progress/traces", headers={"Authorization": f"Bearer {api_key}"}, params={"buckets": 50}, ) data = response.json() print(f" bucket_seconds={data['bucket_seconds']} latest={data['latest_event_at']}") for p in data["points"][-3:]: print(f" {p['t']} step={p['step']} files={p['files']} items={p['items']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const params = new URLSearchParams({ buckets: '50' }); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/inputs/progress/traces?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); console.log(`bucket_seconds=${data.bucket_seconds} latest=${data.latest_event_at}`); data.points.slice(-3).forEach(p => { console.log(` ${p.t} step=${p.step} files=${JSON.stringify(p.files)} items=${JSON.stringify(p.items)}`); }); ``` ```json 200 - Success theme={"system"} { "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "bucket_seconds": 30.0, "latest_event_at": "2026-04-14T10:15:00Z", "points": [ { "t": "2026-04-14T10:02:30Z", "step": 0, "files": { "completed": 0, "failed": 0 }, "items": {} }, { "t": "2026-04-14T10:03:00Z", "step": 0, "files": { "completed": 0, "failed": 0 }, "items": { "inference": { "success": 1, "failed": 0 } } }, { "t": "2026-04-14T10:15:00Z", "step": 9, "files": { "completed": 8, "failed": 1 }, "items": { "inference": { "success": 478, "failed": 12 } } } ] } ``` ```json 304 - Not Modified theme={"system"} (empty body — cached representation matches the request's If-None-Match) ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` Save `latest_event_at` between polls and send it via the `If-None-Match` header. The server returns `304 Not Modified` when nothing has changed, letting you skip the chart redraw. # List Inputs Source: https://docs.archetypeai.app/api-reference/batch/io/list-inputs GET /batch/jobs/{id}/inputs Retrieve a cursor-paginated list of inputs for a specific job Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of input files associated with a job, newest first. You can filter by port name or processing status. ## Request The unique job identifier Filter inputs by port name Filter inputs by processing status: `pending`, `processing`, `completed`, `failed`, or `reference`. `reference` is a terminal sentinel applied to inputs attached to non-tracked ports (e.g. n-shot example files) — they're persisted for visibility but never transition through the `pending → processing → completed/failed` lifecycle. Case-insensitive substring search matched against the input's filename and `file_id`. Composes with other filters using AND logic. [v1.1.10+](/release-notes/1.1.x#v1-1-10) Page size, between `1` and `1000`. Clamped server-side. Forward cursor: return inputs tracked before the input with this ID. Pass the previous page's `next_cursor`. Mutually exclusive with `before` — sending both returns `400`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Backward cursor: return inputs tracked after the input with this ID. Pass the current page's `prev_cursor`. Mutually exclusive with `after`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response The job identifier Array of input objects, newest first (`created_at` descending) in both cursor directions, each containing: * `id` — Unique input identifier * `job_id` — Parent job identifier * `port_name` — Input port name * `file_id` — Original file ID * `data` — Resolved data reference (`DataRef`) with required `ref` (URL) and `filename`, plus optional `file_type`, `file_extension`, `num_bytes`, `metadata`, `file_tags`, `file_attributes`. When emitted in per-worker JSONL manifests, also includes the `input_id` so containers can do per-input progress tracking. * `status` — Processing status: `pending`, `processing`, `completed`, `failed`, or `reference` (terminal sentinel for inputs on non-tracked ports such as n-shot examples) * `error_message` — Error details (if failed) * `created_at` — Creation timestamp * `completed_at` — Completion timestamp (if completed) `true` when more inputs exist beyond this page in the direction of travel. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/inputs?status=completed&limit=10" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/inputs", headers={"Authorization": f"Bearer {api_key}"}, params={ "status": "completed", "limit": 10 } ) data = response.json() for inp in data["data"]: print(f" {inp['id']}: {inp['data']['filename']} — {inp['status']}") # Pass the cursor back verbatim as `after` to fetch the next page. if data["has_more"]: print(f"Next page cursor: {data['next_cursor']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const params = new URLSearchParams({ status: 'completed', limit: '10' }); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/inputs?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); data.data.forEach(inp => { console.log(` ${inp.id}: ${inp.data.filename} — ${inp.status}`); }); if (data.has_more) { console.log(`Next page cursor: ${data.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "data": [ { "id": "inp_abc123def456", "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "port_name": "worker.inference", "file_id": "file_abc123", "data": { "ref": "https://storage.example.com/files/tep_inference.csv", "filename": "tep_inference.csv", "file_type": "text/csv", "file_extension": ".csv", "num_bytes": 245760, "metadata": {}, "file_tags": null, "file_attributes": null }, "status": "completed", "error_message": null, "created_at": "2026-04-14T10:00:00Z", "completed_at": "2026-04-14T10:05:00Z" } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 400 - Invalid Request theme={"system"} { "code": "...", "message": "...", "error_uid": "err_abc123" } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # List Inputs With Progress Source: https://docs.archetypeai.app/api-reference/batch/io/list-inputs-progress GET /batch/jobs/{id}/inputs/progress Tracked inputs paired with their latest progress entry Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns tracked inputs for a job, each paired with its most recent `job_progress` row (if any). Use it to drive per-input progress UIs without N+1 fetches against the progress endpoint. Inputs attached to non-tracked ports (e.g. n-shot reference files) are always excluded. The page is cursor-paginated and comes back in display order: `processing` inputs first, then `pending`, then finished (`completed`/`failed`) ones, each group sorted by its activity time in the direction `order` gives. Unlike the other batch lists, this order is not newest first. ## Request The unique job identifier Scope results to a single input port (e.g. `worker.inference`) Statuses to include. Repeat this parameter to specify several statuses to filter on (`?status=pending&status=processing`). Accepts `pending`, `processing`, `completed`, and `failed`. The `reference` status is always excluded. Sort direction within each status bucket. `asc` (the default) puts the oldest first; `desc` puts the most recently active inputs at the top. A cursor marks a position in the list and stays valid under either direction. Page size, between `1` and `1000`. Clamped server-side. Forward cursor: return the inputs that follow this page's last input in the display order. This value is opaque and doesn't correspond to any identifier you can rely upon. Instead, pass the previous page's `next_cursor` back verbatim. This parameter is mutually exclusive with `before`; including both returns an HTTP `400` error. A malformed cursor also returns `400`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Backward cursor: return the inputs that precede this page's first input in the display order. Just like `after`, this parameter's value is opaque and doesn't correspond reliably to a specific input. This parameter is mutually exclusive with `after`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response The job identifier Array of `InputWithLatestProgress` objects, in the display order described above in both cursor directions, each containing: * `input` — The `InputResponse` (same shape as the response for [List Inputs](/api-reference/batch/io/list-inputs#response)) * `latest_progress` — The most recent `job_progress` row for this input, or `null` if none yet * `step` — 1-indexed completion rank across the whole job, ordered by `completed_at`. `null` for inputs still in `pending` or `processing` — assigned only when the input reaches `completed` or `failed`. Ties (same `completed_at`) are broken by input id. **Distinct from `latest_progress.step`**, which is the container-reported training/inference step inside a single input. `true` when more inputs exist beyond this page in the direction of travel. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/inputs/progress?status=processing&status=pending&order=desc&limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/inputs/progress", headers={"Authorization": f"Bearer {api_key}"}, params=[ ("status", "processing"), ("status", "pending"), ("order", "desc"), ("limit", 20), ], ) data = response.json() for item in data["data"]: inp = item["input"] progress = item.get("latest_progress") pct = progress["metrics"].get("percent_complete") if progress else None print(f" {inp['id']} [{inp['status']}] step={item.get('step')} progress={pct}") # Pass the cursor back verbatim as `after` to fetch the next page. if data["has_more"]: print(f"Next page cursor: {data['next_cursor']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const params = new URLSearchParams(); params.append('status', 'processing'); params.append('status', 'pending'); params.append('order', 'desc'); params.append('limit', '20'); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/inputs/progress?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); data.data.forEach(({ input, latest_progress, step }) => { const pct = latest_progress?.metrics?.percent_complete ?? null; console.log(` ${input.id} [${input.status}] step=${step} progress=${pct}`); }); if (data.has_more) { console.log(`Next page cursor: ${data.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "data": [ { "input": { "id": "inp_abc123def456", "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "port_name": "worker.inference", "file_id": "file_abc123", "data": { "ref": "https://storage.example.com/files/tep_inference.csv", "filename": "tep_inference.csv", "file_type": "text/csv", "file_extension": ".csv", "num_bytes": 245760, "metadata": {} }, "status": "processing", "error_message": null, "created_at": "2026-04-14T10:00:00Z", "completed_at": null }, "latest_progress": { "id": 502, "kind": "inference", "step": 5, "metrics": { "percent_complete": 50, "items_processed": 5, "items_total": 10 }, "payload": {}, "input_id": "inp_abc123def456", "index": 0, "message": "Processing input 5 of 10", "created_at": "2026-04-14T10:06:00Z" }, "step": null } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 400 - Invalid Request theme={"system"} { "code": "...", "message": "...", "error_uid": "err_abc123" } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` The cursor is a snapshot of the position it was issued at, so an input that changes status between two page requests is neither skipped nor repeated. # List Outputs Source: https://docs.archetypeai.app/api-reference/batch/io/list-outputs GET /batch/jobs/{id}/outputs Retrieve a cursor-paginated list of outputs for a specific job Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of output files produced by a job, newest first. You can filter by port name or input ID to find specific results. ## Request The unique job identifier Filter outputs by port name Filter outputs associated with a specific input Page size, between `1` and `1000`. Clamped server-side. Forward cursor: return outputs produced before the output with this ID. Pass the previous page's `next_cursor`. Mutually exclusive with `before` — sending both returns `400`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Backward cursor: return outputs produced after the output with this ID. Pass the current page's `prev_cursor`. Mutually exclusive with `after`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response The job identifier Array of output objects, newest first (`created_at` descending) in both cursor directions, each containing: * `id` — Unique output identifier * `job_id` — Parent job identifier * `port_name` — Output port name * `input_id` — Associated input ID (if applicable) * `input_file_id` — `file_id` of the source input (if applicable) * `data` — Data reference (`DataRef`) with required `ref` (presigned download URL) and `filename`, plus optional `file_type`, `file_extension`, `num_bytes`, `metadata`, `file_tags`, `file_attributes` * `expires_at` — Expiration timestamp for the presigned download URL (re-fetch after this time) * `created_at` — Creation timestamp `true` when more outputs exist beyond this page in the direction of travel. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/outputs?port_name=worker.results&limit=10" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/outputs", headers={"Authorization": f"Bearer {api_key}"}, params={ "port_name": "worker.results", "limit": 10 } ) data = response.json() for output in data["data"]: print(f" {output['id']}: {output['data']['filename']}") print(f" Download: {output['data']['ref']}") # Pass the cursor back verbatim as `after` to fetch the next page. if data["has_more"]: print(f"Next page cursor: {data['next_cursor']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const params = new URLSearchParams({ port_name: 'worker.results', limit: '10' }); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/outputs?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); data.data.forEach(output => { console.log(` ${output.id}: ${output.data.filename}`); console.log(` Download: ${output.data.ref}`); }); if (data.has_more) { console.log(`Next page cursor: ${data.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "data": [ { "id": "out_abc123def456", "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "port_name": "worker.results", "input_id": "inp_abc123def456", "input_file_id": "file_abc123", "data": { "ref": "https://storage.example.com/outputs/result1.json?X-Amz-Signature=...", "filename": "result1.json", "file_type": "application/json", "file_extension": ".json", "num_bytes": 1024, "metadata": {} }, "expires_at": "2026-04-14T11:00:00Z", "created_at": "2026-04-14T10:10:00Z" } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 400 - Invalid Request theme={"system"} { "code": "...", "message": "...", "error_uid": "err_abc123" } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` Output download URLs are presigned and expire at the time indicated by `expires_at`. Re-fetch the outputs list to get fresh URLs after expiration. # Validate Prospective Inputs Source: https://docs.archetypeai.app/api-reference/batch/io/validate-inputs POST /batch/jobs/inputs/validation Validate the inputs for a prospective job without creating a job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Validates a prospective job's file inputs against the pipeline's input-port validations, without creating a job. Used by the Developer Console to give immediate per-file feedback at job-creation time. The validation performed by this endpoint is intended primarily to provide basic guardrails against starting a job with invalid inputs. It is not guaranteed to catch more than basic errors in the format of the input files, and may in fact do no validation at all, especially for files uploaded before platform version 1.1.5. This endpoint always returns HTTP status `200` once the pipeline and ports are valid; each input item is reported `valid: true`/`false` (with a message). Only file items on ports that declare a validation are actually resolved/checked. Checkpoints are not validated by this endpoint. They are accepted for request parameter compatibility with **Create Job**. They are simply reported to be valid, as are files on non-validated ports. ## Request This endpoint accepts the same [request parameters](/api-reference/batch/jobs/create-job#request) as the [Create Job](/api-reference/batch/jobs/create-job) endpoint. This is intentional; you can set up the parameters for **Create Job**, then call this endpoint first with the same parameters. If the validation succeeds, you can then immediately call **Create Job** with the same parameter block. ## Response The per-item validation outcome, keyed by port exactly like the request `inputs`. Each value is an array of result items echoing the item's identity plus whether it is valid and, if not, why. Items on ports without a validation — and all checkpoint items — are always `valid: true`. For a file item: * `kind` (string, required) — always `file` * `file_id` (string, required) * `valid` (boolean, required) * `error` (string | `null`) For a checkpoint item: * `kind` (string, required) — always `checkpoint` * `checkpoint_id` (string, required) * `valid` (boolean, required) * `error` (string | `null`) ## Validations The validations performed depend on the job type and input formats. For example, a machine state classification job may ensure that an input CSV file actually has columns matching the names given in the job configuration, and an activity detection job may ensure that a JSON input file contains JSON objects with the fields expected by the job. The exact set of validations run by this endpoint may change over time. ## Examples ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/batch/jobs/inputs/validation \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "workflow_key": "my-workflow-key", "inputs": { "worker.data": [ {"kind": "file", "file_id": "fil_2abc3def4ghi5jkl6mno7pqr"}, {"kind": "file", "file_id": "fil_3xyz4abc5def6ghi7jkl8mno"} ] }, "parameters": { "worker": { "parallelism": 1, "config": { "reader_config": { "data_columns": ["c1", "c2"] } } } } }' ``` ```python Python theme={"system"} import os import requests api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/batch/jobs/inputs/validation", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "workflow_key": "my-workflow", "inputs": { "worker.data": [ {"kind": "file", "file_id": "fil_2abc3def4ghi5jkl6mno7pqr"}, {"kind": "file", "file_id": "fil_3xyz4abc5def6ghi7jkl8mno"}, ], }, "parameters": { "worker": { "parallelism": 1, "config": { "reader_config": { "data_columns": ["c1", "c2"], }, }, } }, }, ) report = response.json() for port, items in report["inputs"].items(): for item in items: print(f"{port} {item['file_id']}: valid={item['valid']} {item.get('error') or ''}") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/batch/jobs/inputs/validation', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ workflow_key: 'my-workflow', inputs: { 'worker.data': [ { kind: 'file', file_id: 'fil_2abc3def4ghi5jkl6mno7pqr' }, { kind: 'file', file_id: 'fil_3xyz4abc5def6ghi7jkl8mno' } ] }, parameters: { worker: { parallelism: 1, config: { reader_config: { data_columns: ['c1', 'c2'] } } } } }) }); const report = await response.json(); console.log(report.inputs); ``` **Response — `200 OK`** ```json theme={"system"} { "inputs": { "worker.data": [ { "kind": "file", "file_id": "fil_2abc3def4ghi5jkl6mno7pqr", "valid": true, "error": null }, { "kind": "file", "file_id": "fil_3xyz4abc5def6ghi7jkl8mno", "valid": false, "error": "..." } ] } } ``` A checkpoint item is echoed by `checkpoint_id` instead, and is always valid: ```json theme={"system"} { "inputs": { "worker.checkpoint": [ { "kind": "checkpoint", "checkpoint_id": "ckp_2abc3def4ghi5jkl6mno7pqr", "valid": true, "error": null } ] } } ``` ## Error responses An invalid pipeline or port selection is rejected with `400`; per-file failures are reported in the `200` body instead. ```json 400 - Invalid request (pipeline/ports) theme={"system"} { "code": "INVALID_REQUEST", "message": "...", "suggestion": "...", "error_uid": "err_abc123" } ``` The `suggestion` field may be `null`. # Cancel Job Source: https://docs.archetypeai.app/api-reference/batch/jobs/cancel-job POST /batch/jobs/{id}/cancel Cancel a running or pending job Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint cancels a job whose status is currently `PENDING`, `RUNNING`, or `PREEMPTED`. Cancelled jobs cannot be resumed. To pause a job temporarily, use the [Pause Job](/api-reference/batch/jobs/pause-job) endpoint instead. ## Request The unique job identifier ## Response The ID of the cancelled job Updated job status (`CANCELLED`) Timestamp when the job was cancelled ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/cancel \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.post( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/cancel", headers={"Authorization": f"Bearer {api_key}"} ) result = response.json() print(f"Job {result['id']} — Status: {result['status']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/cancel`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const result = await response.json(); console.log(`Job ${result.id} — Status: ${result.status}`); ``` ```json 200 - Success theme={"system"} { "id": "job_2abc3def4ghi5jkl6mno7pqr", "status": "CANCELLED", "cancelled_at": "2026-04-14T10:10:00Z" } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 409 - Invalid State Transition theme={"system"} { "code": "CONFLICT", "message": "Cannot cancel job in COMPLETED state", "error_uid": "err_def456" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` Only jobs in `PENDING` or `RUNNING` status can be cancelled. Attempting to cancel a job that has already completed, failed, or been cancelled will return a `409 Conflict` error. # Create Job Source: https://docs.archetypeai.app/api-reference/batch/jobs/create-job POST /batch/jobs Create a new batch or training job Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint creates a new job with the specified pipeline configuration and optional input files. The job is placed into the queue and will be processed when resources are available. Inputs are organized by **port name**. The available ports depend on the pipeline — call [Get Pipeline Schema](/api-reference/batch/registry/pipelines/get-pipeline-schema) first if you don't know them. The two batch pipelines deployed on the platform today are: * `machine-state-classification` — time-series sensor classification via an Omega encoder + KNN. Input ports: `worker.inference` (CSV files to classify), `worker.n_shots` (labeled CSV example files with `metadata.class`). Output port: `worker.results`. * `activity-detection` — Newton C language model over a JSONL prompt file. Input port: `worker.data` (one JSONL file, each line an `InferenceRecord`). Output port: `worker.result`. ## Request A human-readable name for the job **Deprecated; kept for backward compatibility.** The type of pipeline to run. One of: `batch`, `training`. **Deprecated; kept for backward compatibility: use `workflow_key` instead.** The key identifying the pipeline to use from the registry (e.g. `machine-state-classification`, `activity-detection`) Key of the workflow to run. One of `workflow_key` or the deprecated `pipeline_key` parameter must be provided. If both are provided, they must be equal. [v1.1.7+](/release-notes/1.1.x#v1-1-7) Specific pipeline version to use. If omitted, the latest published version is used. Input files organized by port name. Each key is a port name (see the pipeline schema) and the value is an array of input file objects: * `file_id` (string, required) — The file ID returned from the Files API * `metadata` (object) — Optional per-input metadata. For n-shot ports this carries the class label (`{"class": "..."}`). Pipeline parameters organized by component name (e.g. `worker`). Each value is an object with: * `parallelism` (integer) — Number of parallel workers for this component * `config` (object) — Free-form configuration passed to the container. The accepted shape is defined by the pipeline's `user_config_schema` — fetch it via [Get Pipeline Schema](/api-reference/batch/registry/pipelines/get-pipeline-schema). ## Response Unique job identifier (TypeID, `job_` prefix) Organization identifier Job name Pipeline type (`batch` or `training`) Pipeline key. The value is the same as `workflow_key`. This property is retained for backward compatibility. Key of the workflow this job runs. The value is the same as `pipeline_key`, which is retained for backward compatibility. [v1.1.8+](/release-notes/1.1.x#v1-1-8) Pipeline version used Initial job status (typically `PENDING`) Omitted for any job whose status is not `COMPLETED`. [v1.1.5+](/release-notes/1.1.x#v1-1-5) Resolved job parameters (user-supplied values merged onto the pipeline's `default_config`) Number of times the job has been retried (always `0` on create) Number of times the job has been preempted (always `0` on create) Position in the queue at admission time. Omitted from the response when not queued (e.g. terminal-state jobs). Total queue depth at admission time. Omitted from the response when not queued. Per-status counts of tracked inputs (`pending`, `processing`, `completed`, `failed`). **Omitted from this response** — populated only on read paths like `GET /batch/jobs` and `GET /batch/jobs/{id}`. Creation timestamp in RFC 3339 format Last update timestamp Start timestamp, or `null` if not yet started Completion timestamp, or `null` Failure timestamp, or `null` Cancellation timestamp, or `null` Error details, or `null` ## Examples The two batch pipelines deployed on the platform take very different request bodies. Switch tabs to compare. Classify time-series sensor data using n-shot example files. Inputs split across two ports — `worker.inference` for the CSVs to classify and `worker.n_shots` for the labeled example files (class declared via `metadata.class`). ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/batch/jobs \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "tep-classification", "workflow_key": "machine-state-classification", "inputs": { "worker.inference": [ {"file_id": "tep_inference.csv"} ], "worker.n_shots": [ {"file_id": "tep_normal.csv", "metadata": {"class": "normal"}}, {"file_id": "tep_fault.csv", "metadata": {"class": "fault"}} ] }, "parameters": { "worker": { "parallelism": 1, "config": { "model_type": "omega_1_4_base", "batch_size": 32, "reader_config": { "data_columns": ["xmeas_1", "xmeas_2", "xmv_11"], "timestamp_column": "timestamp", "window_size": 64, "step_size": 1 }, "classifier_config": { "n_neighbors": 5, "metric": "euclidean", "weights": "uniform", "normalize_embeddings": false }, "flush_every_n_iteration": 150 } } } }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/batch/jobs", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "name": "tep-classification", "workflow_key": "machine-state-classification", "inputs": { "worker.inference": [ {"file_id": "tep_inference.csv"}, ], "worker.n_shots": [ {"file_id": "tep_normal.csv", "metadata": {"class": "normal"}}, {"file_id": "tep_fault.csv", "metadata": {"class": "fault"}}, ], }, "parameters": { "worker": { "parallelism": 1, "config": { "model_type": "omega_1_4_base", "batch_size": 32, "reader_config": { "data_columns": ["xmeas_1", "xmeas_2", "xmv_11"], "timestamp_column": "timestamp", "window_size": 64, "step_size": 1, }, "classifier_config": { "n_neighbors": 5, "metric": "euclidean", "weights": "uniform", "normalize_embeddings": False, }, "flush_every_n_iteration": 150, }, } }, }, ) job = response.json() print(f"Job created: {job['id']} — Status: {job['status']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/batch/jobs', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'tep-classification', workflow_key: 'machine-state-classification', inputs: { 'worker.inference': [ { file_id: 'tep_inference.csv' } ], 'worker.n_shots': [ { file_id: 'tep_normal.csv', metadata: { class: 'normal' } }, { file_id: 'tep_fault.csv', metadata: { class: 'fault' } } ] }, parameters: { worker: { parallelism: 1, config: { model_type: 'omega_1_4_base', batch_size: 32, reader_config: { data_columns: ['xmeas_1', 'xmeas_2', 'xmv_11'], timestamp_column: 'timestamp', window_size: 64, step_size: 1 }, classifier_config: { n_neighbors: 5, metric: 'euclidean', weights: 'uniform', normalize_embeddings: false }, flush_every_n_iteration: 150 } } } }) }); const job = await response.json(); console.log(`Job created: ${job.id} — Status: ${job.status}`); ``` **Response — `201 Created`** ```json theme={"system"} { "id": "job_2abc3def4ghi5jkl6mno7pqr", "org_id": "org_1abc2def3ghi4jkl", "name": "tep-classification", "pipeline_type": "batch", "pipeline_key": "machine-state-classification", "pipeline_version": "1.1.1", "status": "PENDING", "parameters": { "worker": { "parallelism": 1, "config": { "model_type": "omega_1_4_base", "batch_size": 32, "reader_config": { "data_columns": ["xmeas_1", "xmeas_2", "xmv_11"], "timestamp_column": "timestamp", "window_size": 64, "step_size": 1 }, "classifier_config": { "n_neighbors": 5, "metric": "euclidean", "weights": "uniform", "normalize_embeddings": false }, "flush_every_n_iteration": 150 } } }, "retry_count": 0, "preemption_count": 0, "created_at": "2026-04-14T10:00:00Z", "updated_at": "2026-04-14T10:00:00Z", "started_at": null, "completed_at": null, "failed_at": null, "cancelled_at": null, "error": null } ``` Run the Newton C language model over a JSONL prompt file. Single input port `worker.data` containing one JSONL file; each line is an `InferenceRecord` (`system?`, `instruction?`, `prompt?`, optional `inputs[]` carrying text/image/video evidence as inline base64). Output is one JSON line per record: `{"line_index": N, "prediction": "..."}`. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/batch/jobs \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "narrative-generation", "workflow_key": "activity-detection", "inputs": { "worker.data": [{"file_id": "my_prompts.jsonl"}] }, "parameters": { "worker": { "parallelism": 1, "config": { "generation": { "max_new_tokens": 1024, "do_sample": true, "temperature": 0.7, "top_p": 0.8, "top_k": 20, "repetition_penalty": 1 } } } } }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/batch/jobs", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "name": "narrative-generation", "workflow_key": "activity-detection", "inputs": { "worker.data": [{"file_id": "my_prompts.jsonl"}], }, "parameters": { "worker": { "parallelism": 1, "config": { "generation": { "max_new_tokens": 1024, "do_sample": True, "temperature": 0.7, "top_p": 0.8, "top_k": 20, "repetition_penalty": 1, } }, } }, }, ) job = response.json() print(f"Job created: {job['id']} — Status: {job['status']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/batch/jobs', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'narrative-generation', workflow_key: 'activity-detection', inputs: { 'worker.data': [{ file_id: 'my_prompts.jsonl' }] }, parameters: { worker: { parallelism: 1, config: { generation: { max_new_tokens: 1024, do_sample: true, temperature: 0.7, top_p: 0.8, top_k: 20, repetition_penalty: 1 } } } } }) }); const job = await response.json(); console.log(`Job created: ${job.id} — Status: ${job.status}`); ``` **Response — `201 Created`** ```json theme={"system"} { "id": "job_3xyz4abc5def6ghi7jkl8mno", "org_id": "org_1abc2def3ghi4jkl", "name": "narrative-generation", "pipeline_type": "batch", "pipeline_key": "activity-detection", "pipeline_version": "1.1.1", "status": "PENDING", "parameters": { "worker": { "parallelism": 1, "config": { "generation": { "max_new_tokens": 1024, "do_sample": true, "temperature": 0.7, "top_p": 0.8, "top_k": 20, "repetition_penalty": 1 } } } }, "retry_count": 0, "preemption_count": 0, "created_at": "2026-04-14T10:00:00Z", "updated_at": "2026-04-14T10:00:00Z", "started_at": null, "completed_at": null, "failed_at": null, "cancelled_at": null, "error": null } ``` ## Error responses ```json 400 - Invalid Request theme={"system"} { "code": "INVALID_REQUEST", "message": "workflow_key 'nonexistent-pipeline' not found in registry", "error_uid": "err_abc123", "suggestion": "Check available pipelines with GET /batch/registry/pipelines" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "error_uid": "err_abc123", "message": "Pipeline '{workflow_key}' has no active versions." } ``` # Delete Job Source: https://docs.archetypeai.app/api-reference/batch/jobs/delete-job DELETE /batch/jobs/{id} Permanently delete a job and its associated data Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint permanently deletes a job and all of its associated data. This action cannot be undone. ## Request The unique job identifier ## Response The ID of the deleted job Whether the job was successfully deleted ```bash cURL theme={"system"} curl -X DELETE https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.delete( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}", headers={"Authorization": f"Bearer {api_key}"} ) result = response.json() if result["deleted"]: print(f"Job {result['id']} deleted successfully") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const result = await response.json(); if (result.deleted) { console.log(`Job ${result.id} deleted successfully`); } ``` ```json 200 - Success theme={"system"} { "id": "job_2abc3def4ghi5jkl6mno7pqr", "deleted": true } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` Deleting a job is permanent and cannot be undone. All associated inputs, outputs, events, and progress data will also be removed. # Get Job Source: https://docs.archetypeai.app/api-reference/batch/jobs/get-job GET /batch/jobs/{id} Retrieve details of a specific job by ID Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns the full details of a specific job, including its current status, parameters, and timestamps. ## Request The unique job identifier ## Response Unique job identifier Organization identifier Job name Pipeline type (`batch` or `training`) Pipeline key. The value is the same as `workflow_key`. This property is retained for backward compatibility. Key of the workflow this job runs. The value is the same as `pipeline_key`, which is retained for backward compatibility. [v1.1.8+](/release-notes/1.1.x#v1-1-8) Pipeline version used Current job status: `PENDING`, `ADMITTED`, `RUNNING`, `PAUSED`, `COMPLETED`, `INTERRUPTED`, `FAILED`, `PREEMPTED`, or `CANCELLED` If and only if the job's `status` is `COMPLETED`, this property's value indicates *how* the job completed. It is set once upon completion and is never set for a job which is not completed; for incomplete jobs, this value is always omitted. [v1.1.5+](/release-notes/1.1.x#v1-1-5) For completed jobs, the following values are possible: | Value | Description | | - | - | | `SUCCESS` | None of the job's inputs failed. | | `PARTIAL` | At least one of the job's inputs failed, but the job still produced at least one artifact (either a `job_outputs` entry or a `checkpoints` entry). | | `FAILED` | At least one input failed, and the job produced no artifacts at all (no outputs and no checkpoints). | Job parameters Number of times the job has been retried Number of times the job has been preempted Current position in queue (null if not queued) Total queue depth (null if not queued) Per-status counts of tracked (non-`reference`) inputs, with integer fields shown in the table below. Populated on read paths so list views can render progress badges without N+1 fetches; `null` on write-path responses (create, retry, cancel). | Property | Description | | - | - | | `completed` | The number of inputs that have reached the `COMPLETED` state. | | `failed` | The number of inputs that have reached the `FAILED` state. | | `pending` | The number of inputs in the `PENDING` state. | | `processed_bytes` | The number of bytes that have been processed so far. This is the sum of `input_bytes` for all inputs being processed plus the sum of the file sizes completed so far plus the sum of the file sizes for failed inputs. This property is only present when `total_bytes` is known and every processing input is reporting `input_bytes`. Otherwise this is absent. | | `processing` | The number of inputs currently being processed. | | `total_bytes` | The total file size across all tracked inputs. Present only when every tracked input has a known size; otherwise, this is absent. | Creation timestamp Last update timestamp Start timestamp (null if not yet started) Completion timestamp (null if not completed) Failure timestamp (null if not failed) Cancellation timestamp (null if not cancelled) Error details (null if no error) ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}", headers={"Authorization": f"Bearer {api_key}"} ) job = response.json() print(f"Job: {job['name']} — Status: {job['status']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const job = await response.json(); console.log(`Job: ${job.name} — Status: ${job.status}`); ``` ```json 200 - Success theme={"system"} { "id": "job_2abc3def4ghi5jkl6mno7pqr", "org_id": "org_1abc2def3ghi4jkl", "name": "tep-classification", "pipeline_type": "batch", "pipeline_key": "machine-state-classification", "pipeline_version": "1.1.1", "status": "COMPLETED", "outcome" "SUCCESS", "parameters": { "worker": { "parallelism": 1, "config": { "model_type": "omega_1_4_base", "batch_size": 32, "reader_config": { "data_columns": ["xmeas_1", "xmeas_2", "xmv_11"], "timestamp_column": "timestamp", "window_size": 64, "step_size": 1 }, "classifier_config": { "n_neighbors": 5, "metric": "euclidean", "weights": "uniform", "normalize_embeddings": false } } } }, "retry_count": 0, "preemption_count": 0, "queue_position": null, "queue_depth": null, "input_progress": { "pending": 0, "processing": 0, "completed": 1, "failed": 0, "processed_bytes": 511733, "total_bytes": 105332974 }, "created_at": "2026-04-14T10:00:00Z", "updated_at": "2026-04-14T10:15:00Z", "started_at": "2026-04-14T10:02:00Z", "completed_at": "2026-04-14T10:15:00Z", "failed_at": null, "cancelled_at": null, "error": null } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # Get Queue Depths Source: https://docs.archetypeai.app/api-reference/batch/jobs/get-queue-depths GET /batch/jobs/queue Retrieve global queue depths grouped by pipeline type Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns the current queue depths for all pipeline types. Use this to monitor how many jobs are waiting to be processed. ## Response Array of queue depth entries, each containing: * `pipeline_type` — Pipeline type (`batch` or `training`) * `depth` — Number of jobs currently in the queue for this pipeline type ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/batch/jobs/queue \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.5/batch/jobs/queue", headers={"Authorization": f"Bearer {api_key}"} ) data = response.json() for queue in data["queues"]: print(f"{queue['pipeline_type']}: {queue['depth']} jobs queued") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/batch/jobs/queue', { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); data.queues.forEach(queue => { console.log(`${queue.pipeline_type}: ${queue.depth} jobs queued`); }); ``` ```json 200 - Success theme={"system"} { "queues": [ { "pipeline_type": "batch", "depth": 12 }, { "pipeline_type": "training", "depth": 3 } ] } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # List Jobs Source: https://docs.archetypeai.app/api-reference/batch/jobs/list-jobs GET /batch/jobs Retrieve a cursor-paginated list of jobs with optional filters Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of jobs. You can filter by pipeline type, status, or a free-text search query. The list is ordered on the field identified by `sort` (`created_at` by default), in the direction specified by `order`. Ties are broken on `created_at`, then `id`. The page is in sort order whether it was reached with `after` or `before`. Cursors are opaque and bound to the `sort` they were issued under; a cursor from another sort returns an HTTP `400` error. ## Request Filter jobs by pipeline type (e.g., `batch`, `training`) Filter jobs by status (e.g., `PENDING`, `RUNNING`, `PAUSED`, `COMPLETED`, `FAILED`, `INTERRUPTED`, `CANCELLED`). Unknown values return an HTTP `400` error. Optional filter on the job outcome: `SUCCESS`, `PARTIAL`, or `FAILED`. These are AND-combined with the other filters. Only `COMPLETED` jobs have an `outcome`, so a non-empty value for this parameter implicitly limits results to completed jobs. [v1.1.5+](/release-notes/1.1.x#v1-1-5) Free-text search query to filter jobs. Specifies the field on which the returned list is ordered. Ties are broken on `created_at`, then `id`, so pages are stable. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Must be one of the following: | Value | Description | | - | - | | `created_at` | Sort by the job's creation timestamp. **Default value.** | | `completed_at` | Sort by the job's completion timestamp. Unfinished jobs sort as the earliest `completed_at` (last under `desc`). | | `status` | Sort by lifecycle position, not by the raw status value, in this order: `PENDING`, `ADMITTED`, `RUNNING`, `PAUSED`, `INTERRUPTED`, `PREEMPTED`, `COMPLETED`, `FAILED`, `CANCELLED` | Specifies whether sorting is performed in ascending order (`asc`) or descending order (`desc`). When sorting by `created_at` or `completed_at`, this defaults to `desc`. When sorting by `status`, this defaults to `asc`. A cursor marks a position in the list and stays valid under either direction. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Sort field: `created_at` (the default), `completed_at`, or `status`. `status` orders by lifecycle position — `PENDING`, `ADMITTED`, `RUNNING`, `PAUSED`, `INTERRUPTED`, `PREEMPTED`, `COMPLETED`, `FAILED`, `CANCELLED` — not by the raw status value. Jobs that haven't finished sort as the earliest `completed_at`, which places them last under `desc`. Ties are broken on `created_at` then `id`, so pages are stable. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Sort direction: `asc` or `desc`. When omitted, each sort field applies its own default: `desc` for `created_at` and `completed_at`, `asc` for `status`. A cursor marks a position in the list and stays valid under either direction. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Page size, between `1` and `1000`. Clamped server-side. Forward cursor: return the jobs that follow this page's last job in the sort order. This value is opaque and doesn't correspond to any identifier you can rely upon. Instead, pass the previous page's `next_cursor` back verbatim. A cursor is bound to the `sort` it was issued under; sending it with a different `sort` returns an HTTP `400` error. This parameter is mutually exclusive with `before`; sending both returns an HTTP `400` error. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Backward cursor: return the jobs that precede this page's first job in the sort order. Just like `after`, this parameter's value is opaque; pass the current page's `prev_cursor` back verbatim. This parameter is mutually exclusive with `after`; specifying both returns an HTTP `400` error. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response Array of job objects, in the requested `sort` and `order` (newest first by default) in both cursor directions, each containing: * `id` — Unique job identifier * `org_id` — Organization identifier * `name` — Job name * `pipeline_type` — Pipeline type (`batch` or `training`) * `pipeline_key` — Pipeline key; this value is the same as `workflow_key` and is retained for backward compatibility * `workflow_key` — Workflow key; this value is the same as `pipeline_key`, which is retained for backward compatibility [v1.1.8+](/release-notes/1.1.x#v1-1-8) * `pipeline_version` — Pipeline version * `status` — Current job status * `outcome` — Job outcome (`SUCCESS`, `PARTIAL`, or `FAILED`). Omitted for jobs whose `status` isn't `COMPLETED` [v1.1.5+](/release-notes/1.1.x#v1-1-5) * `parameters` — Job parameters * `retry_count` — Number of retries * `preemption_count` — Number of preemptions * `queue_position` — Current position in queue (if queued) * `queue_depth` — Total queue depth (if queued) * `input_progress` — Per-status counts of tracked inputs (`pending`, `processing`, `completed`, `failed`, `processed_bytes`, `total_bytes`); populated on this list endpoint, `null` on write-path responses (see the [`input_progress` property](/api-reference/batch/jobs/get-job#param-input-progress) returned by the [Get Job](/api-reference/batch/jobs/get-job) endpoint) * `created_at` — Creation timestamp * `updated_at` — Last update timestamp * `started_at` — Start timestamp (if started) * `completed_at` — Completion timestamp (if completed) * `failed_at` — Failure timestamp (if failed) * `cancelled_at` — Cancellation timestamp (if cancelled) * `error` — Error details (if failed) `true` when more jobs exist beyond this page in the direction of travel. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/jobs?sort=status&order=asc" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.5/batch/jobs", headers={"Authorization": f"Bearer {api_key}"}, params={ "pipeline_type": "batch", "status": "RUNNING", "limit": 10 } ) data = response.json() for job in data["data"]: print(f" {job['id']}: {job['name']} — {job['status']}") # Pass the cursor back verbatim as `after` to fetch the next page. if data["has_more"]: print(f"Next page cursor: {data['next_cursor']}") ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ pipeline_type: 'batch', status: 'RUNNING', limit: '10' }); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); data.data.forEach(job => { console.log(` ${job.id}: ${job.name} — ${job.status}`); }); if (data.has_more) { console.log(`Next page cursor: ${data.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "data": [ { "id": "job_2abc3def4ghi5jkl6mno7pqr", "org_id": "org_1abc2def3ghi4jkl", "name": "tep-classification", "pipeline_type": "batch", "pipeline_key": "machine-state-classification", "pipeline_version": "1.1.1", "status": "RUNNING", "parameters": {}, "retry_count": 0, "preemption_count": 0, "queue_position": null, "queue_depth": null, "input_progress": { "pending": 0, "processing": 1, "completed": 2, "failed": 0, "processed_bytes": 40551733, "total_bytes": 105332974 }, "created_at": "2026-04-14T10:00:00Z", "updated_at": "2026-04-14T10:05:00Z", "started_at": "2026-04-14T10:02:00Z", "completed_at": null, "failed_at": null, "cancelled_at": null, "error": null } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 400 - Invalid Request theme={"system"} { "code": "...", "message": "...", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # Pause job Source: https://docs.archetypeai.app/api-reference/batch/jobs/pause-job POST /batch/jobs/{id}/pause Pause an ongoing batch job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint pauses a job identified by its job ID. Per the job status lifecycle, a job in the `PENDING`, `ADMITTED`, or `RUNNING` state can transition to `PAUSED`. A paused job can later be returned to `PENDING` with the [Resume Job](/api-reference/batch/jobs/resume-job) endpoint. On success the endpoint returns the job ID, its new status, and the time at which it was paused. ## Request Job identifier. A TypeID-encoded identifier with the `job_` prefix. ## Response On success, returns the paused job record. The identifier of the paused job (a TypeID-encoded `JobId`). The job's status after the transition: `PAUSED`. The date and time at which the job was paused. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/batch/jobs/job-2512078e5c9ce4d312a6681e771542/pause \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job-2512078e5c9ce4d312a6681e771542" response = requests.post( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/pause", headers={"Authorization": f"Bearer {api_key}"} ) result = response.json() print(f"Job {result['id']} status: {result['status']} (paused at {result['paused_at']})") ``` ```javascript JavaScript theme={"system"} const jobId = 'job-2512078e5c9ce4d312a6681e771542'; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/pause`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const result = await response.json(); console.log(`Job ${result.id} status: ${result.status} (paused at ${result.paused_at})`); ``` ```json 200 - Job paused theme={"system"} { "id": "job-2512078e5c9ce4d312a6681e771542", "status": "PAUSED", "paused_at": "2025-12-07T18:37:42.576972Z" } ``` ```json 404 - Job not found theme={"system"} { "code": "job_not_found", "message": "Job {id} not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 409 - Invalid state transition theme={"system"} { "code": "invalid_state_transition", "message": "Cannot pause job in {status} state; only PENDING, ADMITTED, or RUNNING jobs can be paused.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # Resume Job Source: https://docs.archetypeai.app/api-reference/batch/jobs/resume-job POST /v0.5/batch/jobs/{id}/resume Resume a paused or interrupted job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint resumes a job identified by its job ID. Per the job status lifecycle, a job in the `PAUSED` or `INTERRUPTED` state transitions back to `PENDING` when resumed. On success the endpoint returns the job ID and its new status. ## Request Job identifier. A TypeID-encoded identifier with the `job_` prefix. ## Response On success, returns the resumed job record. The identifier of the resumed job (a TypeID-encoded `JobId`). The job's status after the transition: `PENDING`. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/batch/jobs/job-2512078e5c9ce4d312a6681e771542/resume \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job-2512078e5c9ce4d312a6681e771542" response = requests.post( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/resume", headers={"Authorization": f"Bearer {api_key}"} ) result = response.json() print(f"Job {result['id']} status: {result['status']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job-2512078e5c9ce4d312a6681e771542'; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/resume`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const result = await response.json(); console.log(`Job ${result.id} status: ${result.status}`); ``` ```json 201 - Job resumed theme={"system"} { "id": "job-2512078e5c9ce4d312a6681e771542", "status": "PENDING" } ``` ```json 404 - Job not found theme={"system"} { "code": "job_not_found", "message": "Job {id} not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 409 - Invalid state transition theme={"system"} { "code": "invalid_state_transition", "message": "Cannot resume job in {status} state; only PAUSED or INTERRUPTED jobs can be resumed.", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # Retry Job Source: https://docs.archetypeai.app/api-reference/batch/jobs/retry-job POST /batch/jobs/{id}/retry Retry a failed or cancelled job Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. This endpoint is no longer available as of Archetype Platform v1.1.5. Calling it results in a 501 redirect to the [Resume Job](/api-reference/batch/jobs/resume-job) endpoint. The Retry Job endpoint will be re-implemented in a future release. ## Overview This endpoint retries a job that is in `FAILED` or `CANCELLED` status. The job is re-queued with `PENDING` status and its retry count is incremented. ## Request The unique job identifier ## Response The job identifier Updated job status (`PENDING`) Updated retry count ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/retry \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.post( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/retry", headers={"Authorization": f"Bearer {api_key}"} ) result = response.json() print(f"Job {result['id']} retried — Status: {result['status']}, Retry #{result['retry_count']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/retry`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const result = await response.json(); console.log(`Job ${result.id} retried — Status: ${result.status}, Retry #${result.retry_count}`); ``` ```json 501 - Not Implemented theme={"system"} { "detail": "Retry is currently disabled. The endpoint is retained (it exists in the API), but returns a clear 501 directing users to `/resume`. A different retry implementation is planned for later." } ``` Only jobs in `FAILED` or `CANCELLED` status can be retried. Attempting to retry a job in any other state will return a `409 Conflict` error. # List Job Progress Source: https://docs.archetypeai.app/api-reference/batch/progress/list-job-progress GET /batch/jobs/{id}/progress Retrieve cursor-paginated progress entries for a specific job Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of progress entries reported during job execution, newest first. Progress entries provide real-time metrics and status updates as the job processes inputs. ## Request The unique job identifier Filter progress entries by kind Filter progress entries associated with a specific input Page size, between `1` and `1000`. Clamped server-side. Forward cursor: return entries recorded before the entry with this ID. Pass the previous page's `next_cursor`. Mutually exclusive with `before` — sending both returns `400`. A malformed cursor also returns `400`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Backward cursor: return entries recorded after the entry with this ID. Pass the current page's `prev_cursor`. Mutually exclusive with `after`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response The job identifier Array of progress entry objects, newest first (`created_at` descending) in both cursor directions, each containing: * `id` — Unique progress entry identifier * `kind` — Type of progress entry * `step` — Step number within the processing sequence. Numbered over the whole filtered set, so it stays consistent across pages * `message` — Optional human-readable progress message * `metrics` — Metrics data (e.g., percentage complete, items processed) * `payload` — Additional progress-specific data * `input_id` — Associated input ID (if applicable) * `index` — Index within the input (if applicable) * `created_at` — Progress entry timestamp `true` when more entries exist beyond this page in the direction of travel. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor for the next page in the same direction — pass it as `after` when paging forward, or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/jobs/job_2abc3def4ghi5jkl6mno7pqr/progress?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "job_2abc3def4ghi5jkl6mno7pqr" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/jobs/{job_id}/progress", headers={"Authorization": f"Bearer {api_key}"}, params={"limit": 20} ) data = response.json() for entry in data["data"]: print(f" Step {entry['step']}: {entry.get('message', '')} — {entry['metrics']}") # Pass the cursor back verbatim as `after` to fetch the next page. if data["has_more"]: print(f"Next page cursor: {data['next_cursor']}") ``` ```javascript JavaScript theme={"system"} const jobId = 'job_2abc3def4ghi5jkl6mno7pqr'; const params = new URLSearchParams({ limit: '20' }); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/jobs/${jobId}/progress?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); data.data.forEach(entry => { console.log(` Step ${entry.step}: ${entry.message || ''}`); }); if (data.has_more) { console.log(`Next page cursor: ${data.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "job_id": "job_2abc3def4ghi5jkl6mno7pqr", "data": [ { "id": 501, "kind": "inference", "step": 1, "message": "Processing input 1 of 10", "metrics": { "percent_complete": 10, "items_processed": 1, "items_total": 10 }, "payload": {}, "input_id": "inp_abc123def456", "index": 0, "created_at": "2026-04-14T10:03:00Z" }, { "id": 502, "kind": "inference", "step": 2, "message": "Processing input 5 of 10", "metrics": { "percent_complete": 50, "items_processed": 5, "items_total": 10 }, "payload": {}, "input_id": null, "index": null, "created_at": "2026-04-14T10:06:00Z" } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 400 - Invalid Request theme={"system"} { "code": "...", "message": "...", "error_uid": "err_abc123" } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Job not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # Get Pipeline Source: https://docs.archetypeai.app/api-reference/batch/registry/pipelines/get-pipeline GET /batch/registry/pipelines/{id} Retrieve details of a specific pipeline from the registry Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns the full details of a specific pipeline, including its components, configuration schema, input/output port definitions, and graph edges. ## Request The unique pipeline identifier ## Response Unique pipeline identifier Pipeline key Pipeline version Human-readable pipeline name Pipeline description Pipeline type (`batch` or `training`) Map of component names to component IDs Default configuration per component, each with `parallelism` and `config` fields JSON Schema for the full pipeline configuration User-facing JSON Schema for configurable parameters Pipeline graph edges, each with `from`, `output`, `to`, and `input` fields describing component connections Input port definitions, each with: * `name` — Display name * `description` — Human-readable description * `mode` — `plain_file_list` (a simple list of inputs) or `n_shot_file_list` (labeled few-shot example files where each item carries `metadata.class`) * `distribute` — `scatter` (fan inputs across workers) or `replicate` (every worker receives the full list) * `required` — Whether the port must be supplied * `tracked` — Whether files attached to this port participate in per-input lifecycle tracking (`pending → processing → completed/failed`). `false` for reference ports like n-shot examples — those inputs land in the terminal `reference` status and never transition. Output port definitions, each with `name` and `description` fields Retry policy configuration Visibility level: `platform` (all orgs) or `org` (owning org only) Owning organization identifier Registry status: `draft`, `published`, `deactivated`, or `deleted` Creation timestamp Last update timestamp ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines/ppl_abc123def456 \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") pipeline_id = "ppl_abc123def456" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines/{pipeline_id}", headers={"Authorization": f"Bearer {api_key}"} ) pipeline = response.json() print(f"Pipeline: {pipeline['name']} ({pipeline['pipeline_key']} v{pipeline['pipeline_version']})") print(f"Components: {list(pipeline['components'].keys())}") ``` ```javascript JavaScript theme={"system"} const pipelineId = 'ppl_abc123def456'; const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines/${pipelineId}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const pipeline = await response.json(); console.log(`Pipeline: ${pipeline.name} (${pipeline.pipeline_key} v${pipeline.pipeline_version})`); console.log(`Components: ${Object.keys(pipeline.components).join(', ')}`); ``` ```json 200 - Success theme={"system"} { "id": "ppl_abc123def456", "pipeline_key": "machine-state-classification", "pipeline_version": "1.1.1", "name": "Machine State Classification", "description": "Identify labeled states in time series sensor data", "pipeline_type": "batch", "components": { "worker": "cmp_xyz789" }, "default_config": { "worker": { "parallelism": 1, "config": { "model_type": "omega_1_4_base", "batch_size": 32, "classifier_config": { "n_neighbors": 5, "metric": "euclidean", "weights": "uniform", "normalize_embeddings": false } } } }, "config_schema": {}, "user_config_schema": {}, "edges": [], "inputs": { "worker.inference": { "name": "Input files", "description": "CSV files for machine-state classification", "mode": "plain_file_list", "distribute": "scatter", "required": true, "tracked": true }, "worker.n_shots": { "name": "N-Shot example files", "description": "Labeled few-shot training files (class declared via input metadata)", "mode": "n_shot_file_list", "distribute": "replicate", "required": true, "tracked": false } }, "outputs": { "worker.results": { "name": "Output files", "description": "Machine-state classification results" } }, "retry_policy": {}, "visibility": "platform", "org_id": "org_1abc2def3ghi4jkl", "status": "published", "created_at": "2026-03-01T00:00:00Z", "updated_at": "2026-04-01T00:00:00Z" } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Pipeline not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # Get Pipeline Schema Source: https://docs.archetypeai.app/api-reference/batch/registry/pipelines/get-pipeline-schema GET /batch/registry/pipelines/{id}/schema Retrieve the configuration schema for a specific pipeline Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns the configuration schema for a specific pipeline, including the user-facing JSON Schema, full config schema, and input/output port definitions. Use this to understand what parameters a pipeline accepts before creating a job. ## Request The unique pipeline identifier ## Response Pipeline identifier Pipeline key Pipeline version User-facing JSON Schema describing the configurable parameters for this pipeline (pretty-printed JSON) Full JSON Schema for the pipeline configuration Input port definitions, each with `name`, `description`, `mode` (`plain_file_list` or `n_shot_file_list`), `distribute` (`scatter` or `replicate`), `required` (bool), and `tracked` (bool — `false` for reference/n-shot ports whose inputs land in the terminal `reference` status). Output port definitions, each with `name` and `description` fields ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines/ppl_abc123def456/schema \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") pipeline_id = "ppl_abc123def456" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines/{pipeline_id}/schema", headers={"Authorization": f"Bearer {api_key}"} ) schema = response.json() print(f"Pipeline: {schema['pipeline_key']} v{schema['pipeline_version']}") print(f"Inputs: {list(schema['inputs'].keys())}") print(f"Outputs: {list(schema['outputs'].keys())}") print(f"User schema: {schema['user_schema']}") ``` ```javascript JavaScript theme={"system"} const pipelineId = 'ppl_abc123def456'; const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines/${pipelineId}/schema`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const schema = await response.json(); console.log(`Pipeline: ${schema.pipeline_key} v${schema.pipeline_version}`); console.log('Inputs:', Object.keys(schema.inputs)); console.log('Outputs:', Object.keys(schema.outputs)); console.log('User schema:', JSON.stringify(schema.user_schema, null, 2)); ``` ```json 200 - Success theme={"system"} { "id": "ppl_abc123def456", "pipeline_key": "machine-state-classification", "pipeline_version": "1.1.1", "user_schema": { "type": "object", "properties": { "model_type": { "type": "string", "description": "Omega model variant used to generate embeddings.", "enum": ["omega_1_4_base", "omega_1_3_surface", "omega_1_3_power_drive"], "default": "omega_1_4_base" }, "batch_size": { "type": "integer", "description": "Number of windows processed together in a single batch.", "default": 32, "minimum": 1 }, "classifier_config": { "type": "object", "properties": { "n_neighbors": {"type": "integer", "minimum": 3, "default": 5}, "metric": {"type": "string", "enum": ["euclidean", "cosine", "manhattan"], "default": "euclidean"}, "weights": {"type": "string", "enum": ["uniform", "distance"], "default": "uniform"}, "normalize_embeddings": {"type": "boolean", "default": false} } } } }, "config_schema": {}, "inputs": { "worker.inference": { "name": "Input files", "description": "CSV files for machine-state classification", "mode": "plain_file_list", "distribute": "scatter", "required": true, "tracked": true }, "worker.n_shots": { "name": "N-Shot example files", "description": "Labeled few-shot training files (class declared via input metadata)", "mode": "n_shot_file_list", "distribute": "replicate", "required": true, "tracked": false } }, "outputs": { "worker.results": { "name": "Output files", "description": "Machine-state classification results" } } } ``` ```json 404 - Not Found theme={"system"} { "code": "NOT_FOUND", "message": "Pipeline not found", "error_uid": "err_abc123" } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` Use the `user_schema` field to understand what parameters you can pass in the `config` field when creating a job. This schema describes the user-configurable options for each pipeline component. # List Pipelines Source: https://docs.archetypeai.app/api-reference/batch/registry/pipelines/list-pipelines GET /batch/registry/pipelines Retrieve a cursor-paginated list of pipelines from the registry Requires [version 1.1.0](/release-notes/1.1.x#v1-1-0) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of pipelines available in the registry. You can filter by pipeline type, visibility, and status. Starting in [version 1.1.11](/release-notes/1.1.x#v1-1-11), this endpoint now pages with cursors instead of an offset. The `offset` query parameter has been replaced by the mutually exclusive `after` and `before` cursors, and the `total` and `offset` response fields have been replaced by `has_more` and `next_cursor`. ## Request Filter by pipeline type: `batch` or `training` Filter by visibility: `platform` (visible to all orgs) or `org` (visible only to owning org) Filter by registry status: `draft`, `published`, `deactivated`, or `deleted` Maximum number of pipelines to return. Minimum `1`, maximum `1000`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Forward cursor: return pipelines older than the pipeline with this ID. Pass the `next_cursor` of the previous page. Mutually exclusive with `before`; specifying both causes an HTTP `400` response. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Backward cursor: return pipelines newer than the pipeline with this ID. Pass the `prev_cursor` of the current page. Mutually exclusive with `after`; specifying both causes an HTTP `400` response. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response The page is newest first in both cursor directions: results are ordered by `created_at` descending, with `id` descending as the tiebreak. Maximum number of items returned True when more results exist beyond this page in the direction of travel. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor for the next page in the same direction — pass it as `after` when paging forward (the default), or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. Array of pipeline objects, each containing: * `id` — Unique pipeline identifier * `pipeline_key` — Pipeline key * `pipeline_version` — Pipeline version * `name` — Human-readable pipeline name * `description` — Pipeline description * `pipeline_type` — Pipeline type (`batch` or `training`) * `components` — Map of component names to component IDs * `default_config` — Default configuration per component * `config_schema` — JSON Schema for pipeline configuration * `user_config_schema` — User-facing JSON Schema * `edges` — Pipeline graph edges connecting components * `inputs` — Map of input port name to port definition. Each port has `name`, `description`, `mode` (`plain_file_list` or `n_shot_file_list`), `distribute` (`scatter` or `replicate`), `required` (bool), and `tracked` (bool — whether files on this port participate in per-input lifecycle tracking; `false` for reference/n-shot ports) * `outputs` — Map of output port name to port definition (`name`, `description`) * `retry_policy` — Retry policy configuration * `visibility` — Visibility level (`platform` or `org`) * `org_id` — Owning organization ID * `status` — Registry status * `created_at` — Creation timestamp * `updated_at` — Last update timestamp ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines?pipeline_type=batch&status=published" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") cursor = None while True: params = { "pipeline_type": "batch", "status": "published", "limit": 50 } if cursor: params["after"] = cursor response = requests.get( "https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines", headers={"Authorization": f"Bearer {api_key}"}, params=params ) page = response.json() for pipeline in page["pipelines"]: print(f" {pipeline['pipeline_key']} v{pipeline['pipeline_version']}: {pipeline['name']}") if not page["has_more"]: break cursor = page["next_cursor"] ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ pipeline_type: 'batch', status: 'published', limit: '50' }); const response = await fetch(`https://api.u1.archetypeai.app/v0.5/batch/registry/pipelines?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); data.pipelines.forEach(pipeline => { console.log(` ${pipeline.pipeline_key} v${pipeline.pipeline_version}: ${pipeline.name}`); }); if (data.has_more) { // Pass next_cursor back as `after` to fetch the following page. console.log(`More pipelines available; next cursor: ${data.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "limit": 50, "has_more": false, "next_cursor": null, "prev_cursor": null, "pipelines": [ { "id": "ppl_abc123def456", "pipeline_key": "machine-state-classification", "pipeline_version": "1.1.1", "name": "Machine State Classification", "description": "Identify labeled states in time series sensor data", "pipeline_type": "batch", "components": { "worker": "cmp_xyz789" }, "default_config": { "worker": { "parallelism": 1, "config": { "model_type": "omega_1_4_base", "batch_size": 32 } } }, "config_schema": {}, "user_config_schema": {}, "edges": [], "inputs": { "worker.inference": { "name": "Input files", "description": "CSV files for machine-state classification", "mode": "plain_file_list", "distribute": "scatter", "required": true, "tracked": true }, "worker.n_shots": { "name": "N-Shot example files", "description": "Labeled few-shot training files (class declared via input metadata)", "mode": "n_shot_file_list", "distribute": "replicate", "required": true, "tracked": false } }, "outputs": { "worker.results": { "name": "Output files", "description": "Machine-state classification results" } }, "retry_policy": {}, "visibility": "platform", "org_id": "org_1abc2def3ghi4jkl", "status": "published", "created_at": "2026-03-01T00:00:00Z", "updated_at": "2026-04-01T00:00:00Z" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "detail": "Invalid access with key: api_key_not_found" } ``` # Error Handling Source: https://docs.archetypeai.app/api-reference/errors Understanding and handling API errors The Archetype AI APIs use conventional HTTP response codes to indicate success or failure, and return a structured JSON body for every error. This page describes the response shape, how to map HTTP status codes to outcomes, and patterns for retrying transient errors. For the canonical list of error `code` values, see [Error Codes](/support/error-codes). ## Error response format Most endpoints (Files, Batch Processing, Query, and the data-plane services) return errors in a **plural `errors` array** envelope: ```json theme={"system"} { "errors": [ { "code": "invalid_file_type", "message": "Unsupported file type: application/octet-stream", "suggestion": "Supported types: image/jpeg, image/png, video/mp4, text/csv, text/plain, application/json", "error_uid": "err-bfa600db-c703-4061-ad9c-c14628b3554c" } ] } ``` Machine-readable error code for programmatic handling. See [Error Codes](/support/error-codes) for the canonical list. Codes are typically lowercase snake\_case (e.g. `invalid_file_type`, `upload_not_found`), though a few legacy endpoints emit uppercase (e.g. `NOT_FOUND`). Human-readable description of what went wrong. Optional hint for how to resolve or mitigate the error. Per-error UUID prefixed with `err-`. Include this when reporting issues to support — it lets the platform team find the corresponding server logs. A response may carry **more than one error** in the array (for example, a request with both a missing parameter and an invalid value). Always iterate the array rather than reading `errors[0]` exclusively. **Legacy envelope:** A handful of older endpoints (notably some authentication failures) still return the FastAPI-style envelope `{"detail": ""}` with no `errors` array, `error_uid`, or `suggestion`. Treat any 4xx/5xx response with neither `errors` nor `detail` as an unknown shape and log the raw body. ## HTTP Status Codes Request succeeded Resource successfully created Request succeeded, no content to return Invalid request parameters or malformed request body Missing or invalid API key Valid credentials but insufficient permissions Requested resource does not exist Request conflicts with current state (e.g. cancelling a job that already completed, completing an upload that's already completed) Request body exceeds size limits. For `POST /v0.5/files` this is 512 MB; for larger uploads use the [cloud upload API](/core-concepts/files/cloud-upload) (up to 250 GB). Rate limit exceeded Unexpected server error. Include the `error_uid` from the response body when reporting. Gateway or proxy error. Server temporarily at capacity; retry with backoff. If uploading multiple large files at once (or a large number of small ones), this may be due to too many concurrent uploads or the server's memory budget being exceeded. Wait a suitable backoff period and try the upload again. Upstream service timeout. ## Error codes The canonical list of error codes lives on [Error Codes](/support/error-codes). Each entry there describes the code, the meaning, and which API surface (Files, Lens, Batch, etc.) emits it. Common patterns you'll see in practice: * **`invalid_*`** — request validation failed (`invalid_file_type`, `invalid_upload_parts`, `invalid_request`). The `message` and `suggestion` together tell you which field is wrong. * **`*_not_found`** — the resource doesn't exist or has been deleted (`upload_not_found`, `file_not_found`, `NOT_FOUND` for some legacy batch endpoints). Verify the id and that the resource hasn't been cleaned up. * **`*_already_completed` / state conflicts** — a 409 telling you the target is already in a terminal state. Often safe to treat as success in idempotent client code (e.g. cancelling an already-cancelled job). * **`unauthorized_request`** — bad or missing bearer token. Verify the `Authorization: Bearer ` header. * **`capacity_reached`, `server_at_capacity`** — back-pressure from the server. Retry with exponential backoff. ## Retry Strategies Retry transient failures (`429`, `500`, `502`, `503`, `504`) with **exponential backoff plus jitter**. Don't retry other 4xx responses — they indicate a client-side problem (bad request, missing resource, conflict) that won't change by waiting. ```python theme={"system"} import time import random import requests TRANSIENT_STATUSES = {429, 500, 502, 503, 504} def make_request_with_retry(url, headers, max_retries=3): for attempt in range(max_retries): response = requests.get(url, headers=headers) if response.ok: return response.json() # Pull whatever identifying info we can out of the body. Most endpoints # use the plural `errors` array; some legacy paths use `{"detail": ...}`. code = None error_uid = None try: body = response.json() if isinstance(body.get("errors"), list) and body["errors"]: code = body["errors"][0].get("code") error_uid = body["errors"][0].get("error_uid") elif "detail" in body: code = "detail" # legacy envelope except ValueError: pass if response.status_code not in TRANSIENT_STATUSES: # 4xx other than 429 — don't retry, surface the error. response.raise_for_status() wait_time = (2 ** attempt) + random.uniform(0, 1) print( f"Transient {response.status_code} (code={code}, " f"error_uid={error_uid}). Retrying in {wait_time:.2f}s..." ) time.sleep(wait_time) raise Exception(f"Max retries ({max_retries}) exceeded") # Usage try: data = make_request_with_retry( "https://api.u1.archetypeai.app/v0.5/lens/info", {"Authorization": "Bearer YOUR_API_KEY"}, ) print(data) except Exception as e: print(f"Request failed after retries: {e}") ``` Rate limiting today is scoped to the login endpoint and returns the legacy `{"detail": "Too many login attempts. Please try again in N minutes."}` envelope without a `Retry-After` header. Other Newton endpoints do not currently rate-limit at the API surface, so 429s on those paths are not expected. ## Error logging When you log API errors, capture the **status code**, the primary `error_uid`, and the request URL — `error_uid` is the field that lets the platform team correlate your report to server logs. * Iterate the full `errors` array, not just `errors[0]` — multi-error responses do occur. * Log the raw response body when JSON parsing fails (gateway / proxy errors can return HTML). * Include the request method and URL so a single log line is enough context to reproduce. ```python theme={"system"} import logging import requests logger = logging.getLogger(__name__) def log_api_error(response: requests.Response, method: str, url: str) -> None: try: body = response.json() errors = body.get("errors") or [] except ValueError: body, errors = None, [] primary = errors[0] if errors else {} logger.error( "Newton API error", extra={ "status_code": response.status_code, "error_code": primary.get("code"), "error_uid": primary.get("error_uid"), "request_method": method, "request_url": url, "response_body": body if body is not None else response.text, }, ) # Usage response = requests.get(url, headers=headers) if not response.ok: log_api_error(response, "GET", url) response.raise_for_status() ``` ## Getting help View current system status and incidents Get help from our technical support team at [support@archetypeai.dev](mailto:support@archetypeai.dev) When contacting support, please include: * The `error_uid` from the response body * The HTTP status code and the full `errors` array * The request URL, method, and (sanitized) headers * Timestamp of the failed request * Your organization ID * Minimal steps to reproduce # Abort Upload Source: https://docs.archetypeai.app/api-reference/files/abort-upload POST /files/uploads/{upload_id}/abort Abort an in-progress direct-to-cloud upload and clean up its resources Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Abort an in-progress direct-to-cloud upload. The server invalidates the upload, releases any reserved storage, and discards any checkpointed `part_token`s. Aborting an already-completed upload returns `409`. Use this endpoint when you can't or don't want to finish an upload — for example, when the source file is no longer available or the client crashed mid-upload. ## Path Parameters Upload identifier returned by [Initiate Upload](./initiate-upload) ## Response The response body is empty when the abort succeeds. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/files/uploads/upl_1mehceg8cn80qsekh46143whrx/abort \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") upload_id = "upl_1mehceg8cn80qsekh46143whrx" response = requests.post( f"https://api.u1.archetypeai.app/v0.5/files/uploads/{upload_id}/abort", headers={"Authorization": f"Bearer {api_key}"}, ) if response.ok: print(f"Upload aborted: {upload_id}") else: print(f"Error: {response.status_code} {response.text}") ``` ```javascript JavaScript theme={"system"} const uploadId = "upl_1mehceg8cn80qsekh46143whrx"; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/files/uploads/${uploadId}/abort`, { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, }, } ); if (response.ok) { console.log(`Upload aborted: ${uploadId}`); } else { console.error(`Error: ${response.status} ${await response.text()}`); } ``` ```text 200 - Success theme={"system"} (empty body) ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Upload not found theme={"system"} { "errors": [ { "code": "upload_not_found", "message": "No upload with the given upload_id was found for the organization.", "suggestion": "Verify the upload_id and that the upload has not already been completed or aborted.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Upload already completed theme={"system"} { "errors": [ { "code": "upload_already_completed", "message": "Upload has already been completed and cannot be aborted.", "suggestion": "Delete the resulting file via /files/delete/{file_id} if it should not be kept.", "error_uid": "err-xxxxxxxx" } ] } ``` # About the Files API Source: https://docs.archetypeai.app/api-reference/files/about An API to upload and manage the data files on which you wish to run inference jobs or agents. The Files API is used to upload data to the Archetype platform for tasks like data summarization or model fine tuning. The API supports uploading, downloading, and managing files. See [the introduction to the Files API](/core-concepts/files/files) for more information. # Checkpoint Upload Parts Source: https://docs.archetypeai.app/api-reference/files/checkpoint-parts POST /files/uploads/{upload_id}/parts/checkpoint Persist part_tokens for completed parts so they can be skipped on resume Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Checkpoint a subset of an upload's completed parts. The server stores each `part_token` (the `ETag` returned from a successful part `PUT`) so that: * A later [Initiate Upload](./initiate-upload) call with `resume_if_started=true` skips the checkpointed parts and only returns presigned URLs for the remaining ones. * Checkpointed parts do not need to be re-supplied on the [Complete Upload](./complete-upload) call. Use this endpoint to make incremental progress durable when uploading a large file in many parts. Direct-to-cloud file uploads support files up to 250GB. ## Path Parameters Upload identifier returned by [Initiate Upload](./initiate-upload) ## Request Body Completed parts to checkpoint 1-based part index (matches the `part_number` returned by [Initiate Upload](./initiate-upload)) The `ETag` value returned by the part's `PUT` request ## Response Number of parts that were newly checkpointed (equal to the number of parts in the request after validation) ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/files/uploads/upl_1mehceg8cn80qsekh46143whrx/parts/checkpoint \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "parts": [ { "part_number": 1, "part_token": "\"e1b3a4cd87f3...\"" }, { "part_number": 2, "part_token": "\"a2c8f7b9e081...\"" }, { "part_number": 3, "part_token": "\"d40fa2c81b9e...\"" } ] }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") upload_id = "upl_1mehceg8cn80qsekh46143whrx" # part_tokens are the ETag header values returned from each PUT to the # presigned URL; collect them as you upload parts. parts = [ {"part_number": 1, "part_token": '"e1b3a4cd87f3..."'}, {"part_number": 2, "part_token": '"a2c8f7b9e081..."'}, {"part_number": 3, "part_token": '"d40fa2c81b9e..."'}, ] response = requests.post( f"https://api.u1.archetypeai.app/v0.5/files/uploads/{upload_id}/parts/checkpoint", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={"parts": parts}, ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const uploadId = "upl_1mehceg8cn80qsekh46143whrx"; const parts = [ { part_number: 1, part_token: '"e1b3a4cd87f3..."' }, { part_number: 2, part_token: '"a2c8f7b9e081..."' }, { part_number: 3, part_token: '"d40fa2c81b9e..."' }, ]; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/files/uploads/${uploadId}/parts/checkpoint`, { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ parts }), } ); console.log(await response.json()); ``` ```json 200 - Success theme={"system"} { "num_checkpointed": 3 } ``` ```json 400 - Invalid request theme={"system"} { "errors": [ { "code": "invalid_upload_parts", "message": "Parts list is empty or contains duplicate or out-of-range part numbers.", "suggestion": "Send a non-empty list of unique part numbers within [1, num_parts].", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Upload not found theme={"system"} { "errors": [ { "code": "upload_not_found", "message": "No upload with the given upload_id was found for the organization.", "suggestion": "Verify the upload_id and that the upload has not been completed or aborted.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Upload already completed theme={"system"} { "errors": [ { "code": "upload_already_completed", "message": "Upload has already been completed; checkpoint is not allowed.", "suggestion": "Begin a new upload via /uploads/initiate.", "error_uid": "err-xxxxxxxx" } ] } ``` # Complete Upload Source: https://docs.archetypeai.app/api-reference/files/complete-upload POST /files/uploads/{upload_id}/complete Finalize a direct-to-cloud upload after all parts have been uploaded Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Finalize a direct-to-cloud upload after the client has `PUT` every part to its presigned URL. The server validates the supplied `part_token`s, assembles the final file, and registers it with the organization. Parts already submitted via [Checkpoint Upload Parts](./checkpoint-parts) do not need to be repeated here — only supply tokens for parts not yet checkpointed. Direct-to-cloud file uploads support files up to 250GB. ## Path Parameters Upload identifier returned by [Initiate Upload](./initiate-upload) ## Request Body Completed parts that have not already been checkpointed. Pass an empty array when every part of the upload has been [checkpointed](./checkpoint-parts). 1-based part index (matches the `part_number` returned by [Initiate Upload](./initiate-upload)) The `ETag` value returned by the part's `PUT` request, including its surrounding quotes Optional whole-file checksum, base64-encoded. When provided, the server queries the storage backend for the checksum it computed over the full object and compares; a mismatch marks the file as corrupt and returns an error. Omit to skip verification entirely. The encoding and byte length must match the algorithm returned by [Initiate Upload](./initiate-upload) (e.g. `crc32c` → 4 raw bytes → 8 base64 characters with `=` padding). Sending a checksum when `integrity_algorithm: none` is returned is an error. ## Response Internal unique identifier of the completed file Name of the completed file Total size of the completed file in bytes Lifecycle status of the file. After a successful upload, the status is `Registered`. Other values are: `Unknown`, `Uploading`, `Ingested`, `Deleting`, `Deleted`, and `Corrupt`. The format of the status string returned for direct-to-cloud uploads is different from the `file_status` string returned by the [Get File Metadata](/api-reference/files/get-metadata) endpoint. Type-specific attributes for the file. Shape depends on the file type — see [Get File Metadata](./get-metadata) for the variants. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/files/uploads/upl_1mehceg8cn80qsekh46143whrx/complete \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "parts": [ { "part_number": 4, "part_token": "\"f912ab83e0d1...\"" }, { "part_number": 5, "part_token": "\"203fa182b97c...\"" } ] }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") upload_id = "upl_1mehceg8cn80qsekh46143whrx" # Only include parts that were NOT previously checkpointed remaining_parts = [ {"part_number": 4, "part_token": '"f912ab83e0d1..."'}, {"part_number": 5, "part_token": '"203fa182b97c..."'}, ] response = requests.post( f"https://api.u1.archetypeai.app/v0.5/files/uploads/{upload_id}/complete", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={"parts": remaining_parts}, ) result = response.json() print(f"file_uid: {result['file_uid']} status: {result['file_status']}") ``` ```javascript JavaScript theme={"system"} const uploadId = "upl_1mehceg8cn80qsekh46143whrx"; const remainingParts = [ { part_number: 4, part_token: '"f912ab83e0d1..."' }, { part_number: 5, part_token: '"203fa182b97c..."' }, ]; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/files/uploads/${uploadId}/complete`, { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ parts: remainingParts }), } ); const result = await response.json(); console.log(`file_uid: ${result.file_uid} status: ${result.file_status}`); ``` ```json 200 - Success theme={"system"} { "file_uid": "fil_5hx819ysp38n2rt1f5fv0wsxgh", "file_name": "training-data.parquet", "num_bytes": 1073741824, "file_status": "Registered", "file_attributes": { "metadata_status": "not_extracted" } } ``` ```json 400 - Validation error theme={"system"} { "errors": [ { "code": "size_mismatch", "message": "Combined size of submitted parts does not match the upload's declared num_bytes.", "suggestion": "Verify each part_token corresponds to the matching part_number and that all parts were uploaded.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Upload not found theme={"system"} { "errors": [ { "code": "upload_not_found", "message": "No upload with the given upload_id was found for the organization.", "suggestion": "Verify the upload_id and that the upload has not been aborted.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Upload already completed theme={"system"} { "errors": [ { "code": "upload_already_completed", "message": "Upload has already been completed.", "suggestion": "Use the file_id from the original completion response to operate on the file.", "error_uid": "err-xxxxxxxx" } ] } ``` # Delete File Source: https://docs.archetypeai.app/api-reference/files/delete-file DELETE /files/delete/{file_id} Delete a file from the authenticated organization Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint deletes a file from the authenticated organization. The file is removed from the available files list and its contents are scheduled for deletion from storage. ## Path Parameters Identifier of the file to delete (returned by [Upload File](./upload) or [Complete Upload](./complete-upload)) ## Response Whether the deletion was successful. Check this field to detect errors. Identifier of the file that was deleted Internal unique identifier of the deleted file ```bash cURL theme={"system"} curl -X DELETE https://api.u1.archetypeai.app/v0.5/files/delete/file-abc123 \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") file_id = "file-abc123" response = requests.delete( f"https://api.u1.archetypeai.app/v0.5/files/delete/{file_id}", headers={"Authorization": f"Bearer {api_key}"}, ) result = response.json() if result.get("is_valid"): print(f"Deleted: {result['file_id']}") else: print(f"Errors: {result.get('errors')}") ``` ```javascript JavaScript theme={"system"} const fileId = "file-abc123"; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/files/delete/${fileId}`, { method: "DELETE", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, }, } ); const result = await response.json(); if (result.is_valid) { console.log(`Deleted: ${result.file_id}`); } else { console.error("Errors:", result.errors); } ``` ```json 200 - Success theme={"system"} { "is_valid": true, "file_id": "file-abc123", "file_uid": "8f2c1e5a-7b3d-4d9e-9c1a-2f5b7d8e4a6c" } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - File not found theme={"system"} { "errors": [ { "code": "file_not_found", "message": "No file with the given file_id was found for the organization.", "suggestion": "Verify the file_id and that the file has not already been deleted.", "error_uid": "err-xxxxxxxx" } ] } ``` # Download File Source: https://docs.archetypeai.app/api-reference/files/download-file GET /files/download/{file_id} Download the raw bytes of a previously uploaded file Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint streams the raw contents of a previously uploaded file. The response body is `application/octet-stream` — the file as it was uploaded. The file must be in a downloadable state. Files that are still uploading, deleted, or corrupt will return `400`. ## Path Parameters Identifier of the file to download ## Response The response body is the raw file bytes with `Content-Type: application/octet-stream`. ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/files/download/file-abc123 \ -H "Authorization: Bearer $ATAI_API_KEY" \ -o downloaded_file.csv ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") file_id = "file-abc123" response = requests.get( f"https://api.u1.archetypeai.app/v0.5/files/download/{file_id}", headers={"Authorization": f"Bearer {api_key}"}, stream=True, ) response.raise_for_status() with open("downloaded_file.csv", "wb") as fh: for chunk in response.iter_content(chunk_size=1 << 20): fh.write(chunk) print(f"Downloaded {file_id}") ``` ```javascript JavaScript theme={"system"} import fs from "node:fs"; import { Readable } from "node:stream"; const fileId = "file-abc123"; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/files/download/${fileId}`, { headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, }, } ); if (!response.ok) { throw new Error(`Download failed: ${response.status}`); } const out = fs.createWriteStream("downloaded_file.csv"); Readable.fromWeb(response.body).pipe(out); ``` ```text 200 - Success theme={"system"} ``` ```json 400 - File not downloadable theme={"system"} { "errors": [ { "code": "file_not_downloadable", "message": "File exists but is not in a downloadable state (status: Uploading).", "suggestion": "Wait for the file to reach the Registered status before downloading.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - File not found theme={"system"} { "errors": [ { "code": "file_not_found", "message": "No file with the given file_id was found for the organization.", "suggestion": "Verify the file_id and that the file has not been deleted.", "error_uid": "err-xxxxxxxx" } ] } ``` # Generate Upload Part URLs Source: https://docs.archetypeai.app/api-reference/files/generate-part-urls POST /files/uploads/{upload_id}/parts/urls Request fresh presigned URLs for specific parts of an in-progress upload Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Generate presigned URLs for specific parts of an in-progress upload. Use this when a presigned URL returned from [Initiate Upload](./initiate-upload) is about to expire and the part has not yet been uploaded. For each requested part, the response may contain either a freshly generated URL or a previously issued one that is not close to expiration; `expires_at` always reflects the URL actually returned. The response's `parts` array has the same length and order as the request's `part_numbers`. Duplicate part numbers in the request produce duplicate entries in the response that share a single presigned URL. Part numbers are 1-based — the first part of an upload is `1`, not `0`. ## Path Parameters Upload identifier returned by [Initiate Upload](./initiate-upload) ## Request Body 1-based part numbers to generate presigned URLs for. Each entry must be in range for the upload (`1 ≤ part_number ≤ num_parts`). ## Response One descriptor per entry in `part_numbers`, in the same order 1-based part index Presigned URL the client should `PUT` the part bytes to Byte offset into the file where this part begins Length of the part in bytes ISO 8601 timestamp at which the presigned URL expires ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/files/uploads/upl_1mehceg8cn80qsekh46143whrx/parts/urls \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "part_numbers": [43, 44, 45] }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") upload_id = "upl_1mehceg8cn80qsekh46143whrx" response = requests.post( f"https://api.u1.archetypeai.app/v0.5/files/uploads/{upload_id}/parts/urls", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={"part_numbers": [43, 44, 45]}, ) for part in response.json()["parts"]: print(f"part {part['part_number']}: expires {part['expires_at']}") ``` ```javascript JavaScript theme={"system"} const uploadId = "upl_1mehceg8cn80qsekh46143whrx"; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/files/uploads/${uploadId}/parts/urls`, { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ part_numbers: [43, 44, 45] }), } ); const { parts } = await response.json(); for (const p of parts) { console.log(`part ${p.part_number}: expires ${p.expires_at}`); } ``` ```json 200 - Success theme={"system"} { "parts": [ { "part_number": 43, "url": "https://storage.example.com/upload/upl_1mehceg8cn80qsekh46143whrx/43?X-Amz-Signature=...", "offset": 352321536, "length": 8388608, "expires_at": "2026-04-28T16:18:42Z" }, { "part_number": 44, "url": "https://storage.example.com/upload/upl_1mehceg8cn80qsekh46143whrx/44?X-Amz-Signature=...", "offset": 360710144, "length": 8388608, "expires_at": "2026-04-28T16:18:42Z" }, { "part_number": 45, "url": "https://storage.example.com/upload/upl_1mehceg8cn80qsekh46143whrx/45?X-Amz-Signature=...", "offset": 369098752, "length": 8388608, "expires_at": "2026-04-28T16:18:42Z" } ] } ``` ```json 400 - Invalid request theme={"system"} { "errors": [ { "code": "invalid_upload_parts", "message": "Part numbers must be non-empty and within [1, num_parts].", "suggestion": "Check the parts/part_numbers array in your request", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Upload not found theme={"system"} { "errors": [ { "code": "upload_not_found", "message": "No upload with the given upload_id was found for the organization.", "suggestion": "Verify the upload_id and that the upload has not been completed or aborted.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Upload already completed theme={"system"} { "errors": [ { "code": "upload_already_completed", "message": "Upload has already been completed; no further URLs can be generated.", "suggestion": "Use the file_id returned by /complete to operate on the file.", "error_uid": "err-xxxxxxxx" } ] } ``` # List Files Metadata Source: https://docs.archetypeai.app/api-reference/files/get-all-metadata GET /files/metadata List metadata for all files in the authenticated organization Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint returns a cursor-paginated list of metadata records for files belonging to your organization. The list is ordered on the property identified by the `sort` property, in the direction specified by `order`. For example, if `sort` is `num_bytes` and `order` is `desc`, the list is sorted in reverse order by file size (largest file first). The default sort order is by creation timestamp (`sort` set to `created_at`), in newest file first ordering. Ties are broken by the `file_uid` property; this ensures that the same request returns the same page when no files have changed. When paging, be sure to keep `sort` and `order` the same. A page holds up to `limit` files (default 100, at most 1000). To read the next page, pass the previous page's `next_cursor` as `after`; to step back, pass its `prev_cursor` as `before`. `has_more` refers to the direction being travelled. Cursors are opaque tokens tied to the `sort` they were minted under and must not be constructed by the client. Sending both `after` and `before`, or a cursor that doesn't fit the current `sort`, returns an HTTP `400` error. ## Query Parameters Page size, between `1` and `1000`. Values outside that range are clamped. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Opaque cursor from a previous page's `next_cursor` (or its `prev_cursor` after paging backward): returns the rows past it in the requested order. Mutually exclusive with `before`; a cursor minted under a different `sort` is rejected with an HTTP `400` error. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Opaque cursor from a previous page's `prev_cursor` (or its `next_cursor` after paging backward): returns the rows before it in the requested order. Mutually exclusive with `after`. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Zero-based index of the shard to return. Use together with `max_items_per_shard` to page through results. Specify `-1` to retrieve all files. This parameter was removed in version [v1.1.12](/release-notes/1.1.x#v1-1-12) of the Archetype platform. Maximum number of metadata records per shard. Specify `-1` for the maximum allowed number of records per shard. The maximum number of records per shard is 1000. This parameter was removed in version [v1.1.12](/release-notes/1.1.x#v1-1-12) of the Archetype platform. Filter results to a comma-delineated list of up to 50 MIME file types (e.g. `image/png`, `text/csv,application/json`). Omit to return files of all types. [v1.1.2+](/release-notes/1.1.x#v1-1-2) Perform a case-insensitive substring match against the names of files, and return only those files that match. If this string is empty or not specified, no search is performed. [v1.1.3+](/release-notes/1.1.x#v1-1-3) Specifies the field on which the returned list is ordered. Ties are broken using the `file_uid` property to ensure that returned pages are the same if no file changes have occurred. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Must be one of the following: | Value | Description | | - | - | | `created_at` | Sort by the time and date at which the file was created. **Default value.** | | `file_id` | Sort by the file's ID | | `file_status` | Sort by the file's lifecycle status, in this order: uploading, registered, ingested, corrupt | | `num_bytes` | Sort by the size of the file in bytes. | When paging through files, do not change the value of `sort`. Specifies whether sorting is performed in ascending order (`asc`) or descending order (`desc`). [v1.1.11+](/release-notes/1.1.x#v1-1-11) When sorting by `created_at` or `num_bytes`, this defaults to `desc`. When sorting by `file_status` or `file_id`, this defaults to `asc`. When paging through files, do not change the value of `order`. ## Response Returns one page of file metadata records, along with the cursors to move off it. When the page is past the end of the file list, `data` is empty and `has_more` is `false`. The files on this page, in the requested `sort` and `order` whether the page was reached with `after` or `before`. Render them as returned. Each record has the same shape as the response from [Get File Metadata](./get-metadata). Whether more files exist in the direction this page was fetched. Cursor continuing in the direction of travel: pass it as `after` on a forward page, or as `before` when this request itself used `before`. `null` when `has_more` is `false`. Cursor stepping back the way this page was reached: pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor (the first page). An HTTP `400` error is returned for an invalid `sort` or `order`, when both `after` and `before` are given, for a malformed cursor or one minted under another `sort`, or when `file_type` lists more than 50 MIME types. ```bash cURL - First Page theme={"system"} curl https://api.u1.archetypeai.app/v0.5/files/metadata \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Next Page theme={"system"} # Pass the previous page's next_cursor back verbatim as `after`. curl "https://api.u1.archetypeai.app/v0.5/files/metadata?limit=10&after=" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.5/files/metadata", headers={"Authorization": f"Bearer {api_key}"}, params={"limit": 100}, ) page = response.json() for file in page["data"]: print(f"{file['file_id']} {file['file_status']} {file['num_bytes']} bytes") # Pass the cursor back verbatim as `after` to fetch the next page. if page["has_more"]: print(f"Next page cursor: {page['next_cursor']}") ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ limit: "100", }); const response = await fetch( `https://api.u1.archetypeai.app/v0.5/files/metadata?${params}`, { headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, }, } ); const page = await response.json(); for (const f of page.data) { console.log(`${f.file_id} ${f.file_status} ${f.num_bytes} bytes`); } // Pass the cursor back verbatim as `after` to fetch the next page. if (page.has_more) { console.log(`Next page cursor: ${page.next_cursor}`); } ``` ```json 200 - Success theme={"system"} { "data": [ { "file_id": "file-abc123", "file_uid": "8f2c1e5a-7b3d-4d9e-9c1a-2f5b7d8e4a6c", "is_valid": true, "file_type": "image/png", "num_bytes": 482931, "file_status": "FILE_STATUS_INGESTED", "file_attributes": { "width": 1920, "height": 1080, "num_channels": 3, "channel_bands": ["R", "G", "B"] }, "ingested": true, "file_index": 0, "file_tags": {} }, { "file_id": "file-def456", "file_uid": "1d4f9b2e-3a8c-4e1d-bb02-7d6c9f0a3b51", "is_valid": true, "file_type": "text/csv", "num_bytes": 12483910, "file_status": "FILE_STATUS_INGESTED", "file_attributes": { "num_rows": 50000, "num_columns": 24, "column_headers": ["timestamp", "value", "label"] }, "ingested": true, "file_index": 1, "file_tags": {} } ], "has_more": true, "next_cursor": "", "prev_cursor": null } ``` ```json 400 - Invalid cursor theme={"system"} { "errors": [ { "code": "", "message": "...", "suggestion": null, "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` # Get Files Info Source: https://docs.archetypeai.app/api-reference/files/get-info GET /files/info Retrieve aggregated file statistics for the authenticated organization Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint returns aggregated statistics about all files belonging to your organization, including total file count, total bytes, and ingestion progress. ## Response Total number of files in the organization Combined size of all files in the organization, in bytes Number of files that have completed ingestion Unix timestamp of the last update to the file statistics ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/files/info \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.5/files/info", headers={"Authorization": f"Bearer {api_key}"} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const response = await fetch( "https://api.u1.archetypeai.app/v0.5/files/info", { headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, }, } ); const data = await response.json(); console.log(data); ``` ```json 200 - Success theme={"system"} { "num_files": 142, "num_bytes": 4831785472, "num_ingested": 138, "last_updated": 1745803938.214 } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` # Get File Metadata Source: https://docs.archetypeai.app/api-reference/files/get-metadata GET /files/metadata/{file_id} Retrieve metadata for a specific file Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint returns the full metadata record for a specific file in the authenticated organization, including file status, size, and type-specific attributes (image dimensions, tabular shape, etc.). ## Path Parameters Identifier of the file whose metadata to fetch ## Response Identifier of the file Internal unique identifier of the file Whether the metadata record is valid MIME type of the file (e.g. `image/png`, `text/csv`) Size of the file in bytes The date and time at which the file was created, in [RFC 3339](https://datatracker.ietf.org/doc/html/rfc3339) format. For direct-to-cloud uploads this is when the upload was *started*. [v1.1.11+](/release-notes/1.1.x#v1-1-11) To sort by creation timestamp, specify `sort=created_at` on the [List Files Metadata](/api-reference/files/get-all-metadata) endpoint. Lifecycle status of the file. One of: * `FILE_STATUS_UNKNOWN` * `FILE_STATUS_REGISTERED` * `FILE_STATUS_INGESTING` * `FILE_STATUS_INGESTED` * `FILE_STATUS_IN_MEMORY` * `FILE_STATUS_IN_COLD_STORAGE` * `FILE_STATUS_CORRUPT` Whether the file has completed ingestion Index of this file within the organization's file list Key/value tags attached to the file (empty object if no tags) Type-specific attributes for the file. The shape varies by file type: Image width in pixels Image height in pixels Number of color channels Channel band labels (e.g. `["R", "G", "B"]`) Number of columns Column header names Number of rows. Only present when the platform was able to extract row counts at upload time — large files and direct-to-cloud uploads typically omit this field. `not_extracted` — file was too large for inline metadata extraction. Contact platform maintainers if you need metadata for this file. ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/files/metadata/test_image.jpg \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") file_id = "file-abc123" response = requests.get( "https://api.u1.archetypeai.app/v0.5/files/metadata/test_image.jpg", headers={"Authorization": f"Bearer {api_key}"} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const fileId = "file-abc123"; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/files/metadata/${fileId}`, { headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, }, } ); const metadata = await response.json(); console.log(metadata); ``` ```json 200 - Success (image) theme={"system"} { "file_id": "file-abc123", "file_uid": "8f2c1e5a-7b3d-4d9e-9c1a-2f5b7d8e4a6c", "is_valid": true, "file_type": "image/png", "num_bytes": 482931, "file_status": "FILE_STATUS_INGESTED", "file_attributes": { "width": 1920, "height": 1080, "num_channels": 3, "channel_bands": ["R", "G", "B"] }, "ingested": true, "file_index": 0, "file_tags": {} } ``` ```json 200 - Success (tabular) theme={"system"} { "file_id": "file-def456", "file_uid": "1d4f9b2e-3a8c-4e1d-bb02-7d6c9f0a3b51", "is_valid": true, "file_type": "text/csv", "num_bytes": 12483910, "file_status": "FILE_STATUS_INGESTED", "file_attributes": { "num_rows": 50000, "num_columns": 24, "column_headers": ["timestamp", "value", "label"] }, "ingested": true, "file_index": 1, "file_tags": {} } ``` ```json 200 - Success (metadata not extracted) theme={"system"} { "file_id": "file-large-789", "file_uid": "9a0b1c2d-3e4f-5061-7283-94a5b6c7d8e9", "is_valid": true, "file_type": "video/mp4", "num_bytes": 4831785472, "file_status": "FILE_STATUS_INGESTED", "file_attributes": { "metadata_status": "not_extracted" }, "ingested": true, "file_index": 2, "file_tags": {} } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - File not found theme={"system"} { "errors": [ { "code": "file_not_found", "message": "No file with the given file_id was found for the organization.", "suggestion": "Verify the file_id and that the file has not been deleted.", "error_uid": "err-xxxxxxxx" } ] } ``` # Initiate Upload Source: https://docs.archetypeai.app/api-reference/files/initiate-upload POST /files/uploads/initiate Begin a direct-to-cloud upload and receive presigned URLs for the file parts Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Begin a direct-to-cloud upload of a file. The server records the file metadata, splits the upload into parts, and returns presigned URLs that the client uploads each part to. Direct-to-cloud file uploads support files up to **250 GB**. However, [Lenses](/core-concepts/lenses/overview) and the Lens API do not support files larger than 512 MB. The full direct-to-cloud upload flow is: 1. **Initiate** the upload (this endpoint) — receive `upload_id` and presigned `parts`. 2. **PUT** each part's bytes directly to its presigned `url`. Capture the `ETag` response header from each PUT — that is the part's `part_token`. 3. Optionally, **[checkpoint](./checkpoint-parts)** completed parts so they can be skipped on resume. 4. Optionally, **[generate fresh URLs](./generate-part-urls)** for parts whose presigned URLs are about to expire. 5. **[Complete](./complete-upload)** the upload, supplying a `part_token` for each non-checkpointed part. If something goes wrong, **[abort](./abort-upload)** the upload to release server-side resources. **Part numbers are 1-based.** The first part returned by this endpoint has `part_number: 1`, not `0`. Using `part_number: 0` in any subsequent call (`/parts/urls`, `/parts/checkpoint`, `/complete`) is rejected with `400 invalid_upload_parts`. ## Request Body Name of the file being uploaded MIME type of the file (e.g. `image/png`, `text/csv`) Total size of the file in bytes When `true`, if a matching in-progress upload for this filename already exists for the organization, the server reuses it and returns only the parts that have not been checkpointed. "Matching" requires the existing record's `file_type` and `num_bytes` to equal the request's; a mismatch fails with `409`. If no in-progress upload exists, behavior is identical to `resume_if_started=false`. ## Response Server-generated identifier for the upload. Use it in subsequent calls to checkpoint, generate URLs, complete, or abort. Internal unique identifier that will be assigned to the completed file Name of the file being uploaded Total size of the file in bytes Number of parts the file has been split into Size in bytes used to split the file into parts. May be omitted for some upload backends. Whole-file checksum algorithm supported by the storage backend. One of `crc32c` or `none`. If `crc32c`, the client may compute a CRC32C over the full file and pass it as `integrity_checksum` on [Complete Upload](./complete-upload) for server-side verification. If `none`, the backend does not support checksum verification — clients should not send one. `true` when the response reuses an existing in-progress upload (because the request specified `resume_if_started=true` and a matching record was found). `false` for a freshly created upload. When `true`, `parts` contains only the not-yet-checkpointed subset. Presigned descriptors for each part of the upload 1-based part index. The first part is `1`. Presigned URL the client should `PUT` the part bytes to Byte offset into the file where this part begins Length of the part in bytes ISO 8601 timestamp at which the presigned URL expires ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/files/uploads/initiate \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "filename": "training-data.parquet", "file_type": "application/x-parquet", "num_bytes": 1073741824, "resume_if_started": false }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/files/uploads/initiate", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json={ "filename": "training-data.parquet", "file_type": "application/x-parquet", "num_bytes": 1_073_741_824, "resume_if_started": False, }, ) result = response.json() print(f"upload_id: {result['upload_id']}") print(f"num_parts: {result['num_parts']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( "https://api.u1.archetypeai.app/v0.5/files/uploads/initiate", { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ filename: "training-data.parquet", file_type: "application/x-parquet", num_bytes: 1_073_741_824, resume_if_started: false, }), } ); const result = await response.json(); console.log(`upload_id: ${result.upload_id}`); console.log(`num_parts: ${result.num_parts}`); ``` ```json 200 - Success theme={"system"} { "upload_id": "upl_1mehceg8cn80qsekh46143whrx", "file_uid": "fil_5hx819ysp38n2rt1f5fv0wsxgh", "file_name": "training-data.parquet", "total_bytes": 1073741824, "num_parts": 128, "part_size": 8388608, "integrity_algorithm": "crc32c", "is_resume": false, "parts": [ { "part_number": 1, "url": "https://storage.example.com/upload/upl_1mehceg8cn80qsekh46143whrx/1?X-Amz-Signature=...", "offset": 0, "length": 8388608, "expires_at": "2026-04-28T15:32:18Z" }, { "part_number": 2, "url": "https://storage.example.com/upload/upl_1mehceg8cn80qsekh46143whrx/2?X-Amz-Signature=...", "offset": 8388608, "length": 8388608, "expires_at": "2026-04-28T15:32:18Z" } ] } ``` ```json 400 - Invalid request theme={"system"} { "errors": [ { "code": "invalid_request", "message": "num_bytes must be greater than zero.", "suggestion": "Specify the total file size in bytes and retry.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - Resume mismatch theme={"system"} { "errors": [ { "code": "resume_mismatch", "message": "An in-progress upload exists for this filename but file_type or num_bytes do not match.", "suggestion": "Abort the existing upload or retry with the original file_type and num_bytes.", "error_uid": "err-xxxxxxxx" } ] } ``` # Upload File Source: https://docs.archetypeai.app/api-reference/files/upload POST /files Upload a file via streaming multipart/form-data Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. **File Upload Note:** The interactive playground doesn't support file uploads due to browser limitations. Use the cURL examples below to test file uploads. ## Overview Upload a file to the Newton Platform for processing. The request body is `multipart/form-data` and the file contents are streamed to reduce memory usage. The simple upload endpoint accepts files up to **512 MB**. For files above this — or for any case where you need resumable uploads — use the [direct-to-cloud upload workflow](/core-concepts/files/cloud-upload) instead, which supports up to **250 GB**. The Developer Console UI caps its uploads through this endpoint at **255 MB**; client integrations can go up to the full 512 MB. ## Request The request must be sent as `multipart/form-data` with the file contents in a form field. The exact form-field name depends on the client; most HTTP clients (e.g. `curl -F`, `requests` `files=`) will use the file's name as the field name. ### Required Header * `Authorization: Bearer YOUR_API_KEY` * `Content-Type: multipart/form-data` (automatically set by cURL's `-F` flag) ### Supported File Types The server's `Content-Type` validator accepts: * **Images:** `image/jpeg`, `image/png` * **Video:** `video/mp4` * **Text & data:** `text/plain`, `text/csv`, `application/json` **JSONL (`application/x-ndjson`) is rejected by this endpoint** despite appearing in the server's "supported types" error message. Use the [direct-to-cloud multipart flow](/core-concepts/files/cloud-upload) for JSONL — `initiate` accepts it as the `file_type`. **Maximum size:** 512 MB ## Response Whether the upload was successful. Check this field to detect errors. The filename of the uploaded file. Use this to download, delete, or fetch metadata for the file. Internal unique identifier for the uploaded file ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/files \ -H "Authorization: Bearer $ATAI_API_KEY" \ -F "file=@/path/to/local/file.csv" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") with open("/path/to/local/file.csv", "rb") as fh: response = requests.post( "https://api.u1.archetypeai.app/v0.5/files", headers={"Authorization": f"Bearer {api_key}"}, files={"file": ("file.csv", fh, "text/csv")}, ) result = response.json() if result.get("is_valid"): print(f"Uploaded: {result['file_id']}") else: print(f"Errors: {result.get('errors')}") ``` ```javascript JavaScript theme={"system"} import fs from "node:fs"; const form = new FormData(); form.append("file", new Blob([fs.readFileSync("/path/to/local/file.csv")]), "file.csv"); const response = await fetch("https://api.u1.archetypeai.app/v0.5/files", { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, }, body: form, }); const result = await response.json(); if (result.is_valid) { console.log(`Uploaded: ${result.file_id}`); } else { console.error("Errors:", result.errors); } ``` ```json 200 - Success theme={"system"} { "is_valid": true, "file_id": "file-abc123", "file_uid": "8f2c1e5a-7b3d-4d9e-9c1a-2f5b7d8e4a6c" } ``` ```json 400 - Bad request theme={"system"} { "errors": [ { "code": "invalid_request", "message": "Multipart form is missing a file field.", "suggestion": "Include the file contents in a form field of the multipart request body.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - File already exists theme={"system"} { "errors": [ { "code": "file_already_exists", "message": "A file with this name already exists for the organization.", "suggestion": "Delete the existing file first or upload with a different filename.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 503 - Server at capacity theme={"system"} { "errors": [ { "code": "server_at_capacity", "message": "Server is at capacity. Retry later.", "suggestion": "Retry the request after a short delay using exponential backoff.", "error_uid": "err-xxxxxxxx" } ] } ``` **Quick Test:** Navigate to your file's directory and run: ```bash theme={"system"} curl -X POST  https://api.u1.archetypeai.app/v0.5/files \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "file=@test_image.jpg" ``` **Getting Full Metadata:** This endpoint returns a minimal response. To get complete file information including size, dimensions, and timestamps, use the [Get File Metadata](/api-reference/files/get-metadata) endpoint. ## Next Steps 1. **Get file details:** ```bash theme={"system"} curl  https://api.u1.archetypeai.app/v0.5/files/metadata/YOUR_FILE_ID \ -H "Authorization: Bearer YOUR_API_KEY" ``` 2. **List all files:** ```bash theme={"system"} curl  https://api.u1.archetypeai.app/v0.5/files/metadata \ -H "Authorization: Bearer YOUR_API_KEY" ``` 3. **Get storage summary:** ```bash theme={"system"} curl  https://api.u1.archetypeai.app/v0.5/files/info \ -H "Authorization: Bearer YOUR_API_KEY" ``` # Upload Base64 File Source: https://docs.archetypeai.app/api-reference/files/upload-base64 POST /files/base64 Upload a file with base64-encoded contents via streaming multipart/form-data Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. **File Upload Note:** The interactive playground doesn't support file uploads due to browser limitations. Use the cURL examples below to test file uploads. ## Overview Upload a file whose contents have been Base64-encoded. The request body is `multipart/form-data`; the server decodes the Base64 payload as it streams. Use this endpoint when the source environment cannot transmit raw binary contents (for example, embedding a small file in a JSON-bearing channel that has been wrapped in a multipart form). For files larger than the simple-upload cap, or any case that needs resumable uploads, use the [direct-to-cloud multipart flow](/core-concepts/files/cloud-upload) (up to 250 GB) instead. ## Request The request must be sent as `multipart/form-data` with a form field containing the base64-encoded file contents. The server decodes the contents on the fly. ### Supported File Types The server's `Content-Type` validator accepts: * **Images:** `image/jpeg`, `image/png` * **Video:** `video/mp4` * **Text & data:** `text/plain`, `text/csv`, `application/json` JSONL (`application/x-ndjson`) is not accepted by this endpoint — use the [direct-to-cloud upload](/core-concepts/files/cloud-upload) for JSONL. **Maximum size:** 512 MB (after Base64 encoding). The Developer Console UI caps its uploads through this endpoint at 255 MB. ## Response Whether the upload was successful. Check this field to detect errors. Filename of the uploaded file. Use this to download, delete, or fetch metadata for the file. Internal unique identifier for the uploaded file. ```bash cURL theme={"system"} # Encode the file first base64 -i /path/to/local/file.csv -o /tmp/file.b64 curl -X POST https://api.u1.archetypeai.app/v0.5/files/base64 \ -H "Authorization: Bearer $ATAI_API_KEY" \ -F "file=@/tmp/file.b64;filename=file.csv" ``` ```python Python theme={"system"} import base64 import io import requests import os api_key = os.environ.get("ATAI_API_KEY") with open("/path/to/local/file.csv", "rb") as fh: encoded = base64.b64encode(fh.read()) response = requests.post( "https://api.u1.archetypeai.app/v0.5/files/base64", headers={"Authorization": f"Bearer {api_key}"}, files={"file": ("file.csv", io.BytesIO(encoded), "text/csv")}, ) result = response.json() if result.get("is_valid"): print(f"Uploaded: {result['file_id']}") else: print(f"Errors: {result.get('errors')}") ``` ```javascript JavaScript theme={"system"} import fs from "node:fs"; const encoded = fs.readFileSync("/path/to/local/file.csv").toString("base64"); const form = new FormData(); form.append("file", new Blob([encoded]), "file.csv"); const response = await fetch( "https://api.u1.archetypeai.app/v0.5/files/base64", { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, }, body: form, } ); const result = await response.json(); if (result.is_valid) { console.log(`Uploaded: ${result.file_id}`); } else { console.error("Errors:", result.errors); } ``` ```json 200 - Success theme={"system"} { "is_valid": true, "file_id": "file-abc123", "file_uid": "8f2c1e5a-7b3d-4d9e-9c1a-2f5b7d8e4a6c" } ``` ```json 400 - Bad request theme={"system"} { "errors": [ { "code": "invalid_base64", "message": "File contents are not valid base64.", "suggestion": "Ensure the form field contains correctly base64-encoded data.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 409 - File already exists theme={"system"} { "errors": [ { "code": "file_already_exists", "message": "A file with this name already exists for the organization.", "suggestion": "Delete the existing file first or upload with a different filename.", "error_uid": "err-xxxxxxxx" } ] } ``` # About the Fine-Tuning Service API Source: https://docs.archetypeai.app/api-reference/fine-tuning/about An API to upload and manage the data files on which you wish to run inference jobs or agents. Fine-tuning is a process by which you train one of Archetype's models with a data set specifically designed to optimize the model's performance for your use case. This API supports creating, managing, and retrieving results from fine-tuning jobs. For more information about fine tuning, see this [introduction to fine-tuning](/core-concepts/customization/fine-tuning). # Cancel Fine-tuning Job Source: https://docs.archetypeai.app/api-reference/fine-tuning/cancel-job POST /fine_tuning/jobs/{id}/cancel Cancel a fine-tuning job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Cancel a fine-tuning job. Force-stops the run (worker pods are killed without a final checkpoint) and tears down its resources. A cancelled job cannot be resumed; use the [Pause Job](/api-reference/fine-tuning/pause-job) endpoint for a graceful, resumable stop instead. ## Request A TypeID-encoded identifier with the `FineTuningJobId` prefix, which identifies the fine-tuning job. ## Response Returns a description of the fine-tuning job after cancellation. The object type. Always `fine_tuning.job`. A unique identifier for the fine-tuning job. The human-readable name supplied when the job was created. The base model being fine-tuned. The Unix timestamp (in seconds) at which the job was created. The organization that owns the job. The job's current lifecycle stage. One of `PENDING`, `ADMITTED`, `RUNNING`, `COMPLETED`, `FAILED`, `PREEMPTED`, `CANCELLED`, `PAUSED`, `INTERRUPTED`. To determine whether a `COMPLETED` job was fully or partially successful, or produced no output, see the value of the `outcome` property. Always `null` for cancelled jobs. This property does not take on a value until and unless the job's `status` is `COMPLETED`. [v1.1.5+](/release-notes/1.1.x#v1-1-5) Identifiers of the files used to train the model. Identifiers of the files used to evaluate the model during training. Failure detail when the job has failed, as the platform error envelope (a list of `{code, message, suggestion, error_uid}`). Empty while the job is queued/running or on success. See [Error Handling](/api-reference/errors) for information about handling platform errors. The checkpoint the job was started from, or `null` if it trained from the base model. The name of the model produced by the job. This is available once training has succeeded but is `null` until then. The Unix timestamp (in seconds) at which the job finished, or `null` if it is not yet complete. For a `COMPLETED` job, this string indicates whether it succeeded fully (`SUCCESS`), partially (`PARTIAL`), or produced nothing (`FAILED`); `null` for any non-completed `status`. Seed. The random seed used for the job. The suffix supplied on the request, applied to the fine-tuned model's name. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/your-job-id/cancel \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "your-job-id" response = requests.post( f"https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/{job_id}/cancel", headers={"Authorization": f"Bearer {api_key}"} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const jobId = 'your-job-id'; const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/${jobId}/cancel`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - Fine-tuning job cancelled theme={"system"} { "object": "fine_tuning.job", "id": "your-job-id", "name": "my-tune", "model": "newton", "created_at": 1765201323, "org_id": "your-org", "status": "CANCELLED", "checkpoint_id": null, "fine_tuned_model": null, "finished_at": 1765201999, "outcome": null, "seed": 42, "user_provided_suffix": "v2", "training_files": ["fil_..."], "validation_files": ["fil_..."], "errors": [] } ``` ```json 404 - Not found theme={"system"} { "code": "not_found", "message": "Not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 409 - Invalid state transition theme={"system"} { "code": "invalid_state_transition", "message": "Invalid state transition", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # Create Fine-tuning Job Source: https://docs.archetypeai.app/api-reference/fine-tuning/create-job POST /fine_tuning/jobs Create a fine-tuning job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Submits a fine-tuning job for the selected model. The request body varies by `model`; see the request schema for the per-model methods, hyperparameters, and accepted file formats. Poll the returned job for its status, using the [Get Job](/api-reference/fine-tuning/get-job) endpoint. ## Request Describes the new fine-tuning job. The exact shape of the input parameters depends on the `model` you specify. The base model to fine-tune. One of `newton` or `omega`. A human-readable name for the fine-tuning job. This is used to identify the job in listings and results. Optional string which is appended to the name of the resulting fine-tuned model to help tell it apart from other fine-tunes. Optional random seed controlling reproducibility. The same seed with the same inputs produces the same results where possible. Omit this parameter to use a random seed. Optional checkpoint (`ckp_...`) to warm-start from; omit to train from the base model. Options can be sourced using the [List Checkpoint Options](/api-reference/fine-tuning/list-checkpoint-options) endpoint. The fine-tuning method to use along with its settings. The available methods depend on the selected `model`. The method type. Must be `lora`, which specifies to use low-rank adaptation (LoRA) fine-tuning. Settings for low-rank adaptation (LoRA) fine-tuning. How many training examples are grouped together before the model's weights are updated. Larger batches update the weights less often but make each update steadier. Defaults to `"auto"` to choose an optimal value. Scales the base learning rate. Lower values take smaller, more cautious steps that can help avoid overfitting; higher values learn faster but may become unstable. Defaults to `"auto"` to choose an optimal value. How many times the entire training dataset is passed through. More epochs give the model more chances to learn, at the cost of longer training and a greater chance of overfitting. Defaults to `"auto"` to choose an optimal value. The method type: `head`, for head-only fine-tuning. Settings for head-only fine-tuning. The batch size, indicating how many training examples are grouped together before the model's weights are updated. Defaults to `"auto"` to choose an optimal value. How many times the entire training dataset is passed through. Defaults to `"auto"` to choose an optimal value. Names of the CSV data columns to use as input features, or `"auto"` to use all columns. The number of rows to advance between consecutive windows. `"auto"` lets the worker choose. The window size, specifying the number of consecutive rows in each input window. `"auto"` lets the worker choose. The files used to train the model. The file type; must be `plain`, indicating a plain data file. The file ID of a previously uploaded file which contains the data. The file's data format. Newton files must be provided in JSON Lines format (`jsonl`). The file type; must be `n_shot`, indicating the file is an N-shot labelled example file. The file ID of a previously uploaded file containing the data. The class label that the examples in this file represent. The file's data format. Omega files must be provided in CSV format (`csv`). An optional array of files used to evaluate the model during training; metrics on these files help you spot overfitting. Uses the same per-model file shapes as `training_files`. ## Response Returns a description of the new fine-tuning job. The object type. Always `fine_tuning.job`. A unique ID for the fine-tuning job. The human-readable name supplied when the job was created. The base model being fine-tuned. The Unix timestamp (in seconds) at which the job was created. The organization that owns the job. The job's current lifecycle stage. Mirrors the underlying Jobs Orchestration Service job status. A job that finished processing is `COMPLETED` regardless of whether some inputs failed; inspect `outcome` for that information. One of `PENDING`, `ADMITTED`, `RUNNING`, `COMPLETED`, `FAILED`, `PREEMPTED`, `CANCELLED`, `PAUSED`, `INTERRUPTED`. Always `null` for newly-created jobs. This property does not take on a value until the job's `status` is `COMPLETED`. [v1.1.5+](/release-notes/1.1.x#v1-1-5) An array of file IDs indicating the files used to train the model. An array of file IDs indicating the files used to evaluate the model during training. When the job has failed, this array describes the error(s) which occurred, as the platform error envelope (a list of `{code, message, suggestion, error_uid}`). Empty while the job is queued/running or on success. See [Error Handling](/api-reference/errors) for more information about handling platform errors. The checkpoint the job was started from, or `null` if it trained from the base model. Name of the finely-tuned model produced by the job, available once training has succeeded; `null` until then. The Unix timestamp (in seconds) at which the job finished, or `null` if it is not yet complete. For a `COMPLETED` job, this indicates whether it succeeded fully (`SUCCESS`), partially (`PARTIAL`), or produced nothing (`FAILED`). This is `null` for any non-completed status. The random seed used for the job. The suffix supplied on the request, applied to the fine-tuned model's name. ```bash cURL - Newton (LoRA) theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "newton", "name": "my-tune", "suffix": "v2", "seed": 42, "method": {"type": "lora", "lora": {"hyperparameters": {"n_epochs": 3}}}, "training_files": [{"type": "plain", "file_id": "fil_..."}], "validation_files": [{"type": "plain", "file_id": "fil_..."}] }' ``` ```bash cURL - Omega (head) theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "omega", "name": "my-tune", "method": {"type": "head", "head": {"hyperparameters": {}}}, "training_files": [{"type": "n_shot", "file_id": "fil_...", "label": "cat"}] }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "model": "newton", "name": "my-tune", "suffix": "v2", "seed": 42, "method": {"type": "lora", "lora": {"hyperparameters": {"n_epochs": 3}}}, "training_files": [{"type": "plain", "file_id": "fil_..."}], "validation_files": [{"type": "plain", "file_id": "fil_..."}] } ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'newton', name: 'my-tune', suffix: 'v2', seed: 42, method: { type: 'lora', lora: { hyperparameters: { n_epochs: 3 } } }, training_files: [{ type: 'plain', file_id: 'fil_...' }], validation_files: [{ type: 'plain', file_id: 'fil_...' }] }) }); const data = await response.json(); console.log(data); ``` ```json 201 - Fine-tuning job created theme={"system"} { "object": "fine_tuning.job", "id": "your-job-id", "name": "my-tune", "model": "newton", "created_at": 1765201323, "org_id": "your-org", "status": "PENDING", "checkpoint_id": null, "fine_tuned_model": null, "finished_at": null, "outcome": null, "seed": 42, "user_provided_suffix": "v2", "training_files": ["fil_..."], "validation_files": ["fil_..."], "errors": [] } ``` ```json 400 - Invalid request theme={"system"} { "code": "invalid_request", "message": "Invalid request", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 501 - Model not yet supported theme={"system"} { "code": "model_not_supported", "message": "Model not yet supported", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # Get Fine-tuning Job Details Source: https://docs.archetypeai.app/api-reference/fine-tuning/get-job GET /fine_tuning/jobs/{id} Get a fine-tuning job by ID Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Returns details about a fine-tuning job, given its TypeID-encoded ID. ## Request The fine-tuning job ID for which to return details. This is a TypeID-encoded identifier with the `FineTuningJobId` prefix. ## Response Returns a description of the specified fine-tuning job. The object type. Always `fine_tuning.job`. The unique identifier of the fine-tuning job. The human-readable name supplied when the job was created. The name of the base model being fine-tuned. The Unix timestamp (in seconds) at which the job was created. The organization that owns the job. The job's current lifecycle stage. One of `PENDING`, `ADMITTED`, `RUNNING`, `COMPLETED`, `FAILED`, `PREEMPTED`, `CANCELLED`, `PAUSED`, `INTERRUPTED`. If and only if the job's `status` is `COMPLETED`, this property's value indicates *how* the job completed. It is set once upon completion and is never set for a job which is not completed; for incomplete jobs, this value is always omitted. [v1.1.5+](/release-notes/1.1.x#v1-1-5) For completed jobs, the following values are possible: | Value | Description | | - | - | | `SUCCESS` | None of the job's inputs failed. | | `PARTIAL` | At least one of the job's inputs failed, but the job still produced at least one artifact (either a `job_outputs` entry or a `checkpoints` entry). | | `FAILED` | At least one input failed, and the job produced no artifacts at all (no outputs and no checkpoints). | Identifiers of the files used to train the model. Identifiers of the files used to evaluate the model during training. Failure detail when the job has failed, as the platform error envelope (a list of `{code, message, suggestion, error_uid}`). Empty while the job is queued/running or on success. The ID of checkpoint the job was started from, or `null` if it trained from the base model. Name of the model produced by the job. This is available once training has succeeded, but is `null` until then. The Unix timestamp (in seconds) at which the job finished, or `null` if it is not yet complete. For a `COMPLETED` job, this indicates whether it succeeded fully (`SUCCESS`), partially (`PARTIAL`), or produced nothing (`FAILED`); `null` for any non-completed status. The random seed used for the job. The suffix supplied on the request, applied to the fine-tuned model's name. ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/your-job-id \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "your-job-id" response = requests.get( f"https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/{job_id}", headers={"Authorization": f"Bearer {api_key}"} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const jobId = 'your-job-id'; const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/${jobId}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - Fine-tuning job theme={"system"} { "object": "fine_tuning.job", "id": "your-job-id", "name": "my-tune", "model": "newton", "created_at": 1765201323, "org_id": "your-org", "status": "RUNNING", "checkpoint_id": null, "fine_tuned_model": null, "finished_at": null, "outcome": null, "seed": 42, "user_provided_suffix": "v2", "training_files": ["fil_..."], "validation_files": ["fil_..."], "errors": [] } ``` ```json 404 - Not found theme={"system"} { "code": "not_found", "message": "Not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # List Checkpoint Options Source: https://docs.archetypeai.app/api-reference/fine-tuning/list-checkpoint-options GET /fine_tuning/checkpoints List checkpoints available to warm-start a new fine-tuning job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Lists checkpoints available to warm-start a new fine-tuning job. This returns the organization's checkpoints, optionally filtered to a model family. The results are cursor-paginated and are sorted newest first. To list only checkpoints for a specific job, use the [List Job Checkpoints](/api-reference/fine-tuning/list-job-checkpoints) endpoint. This endpoint is used by the Fine-Tuning dashboard to build the list of checkpoints from which to start a job. ## Request Filters checkpoints to include only those of the specified model, e.g. `newton`. Omit to list all of the org's checkpoints. Forward cursor: return checkpoints older than the one with this ID. Pass the `next_cursor` of the previous page. Mutually exclusive with `before`. Backward cursor: return checkpoints newer than the one with this ID. Pass the `prev_cursor` of the current page. Mutually exclusive with `after`. The maximum number of options to return. Minimum `1`, maximum `1000`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response Returns a page of checkpoint options. The object type of a list response. Always `list`. The selectable checkpoint options. A page of checkpoint options that match the specified options. The checkpoint's identifier. This is the value to submit as `checkpoint_id` when using the [Create Job](/api-reference/fine-tuning/create-job) endpoint. The human-readable registry name. The base model variant the checkpoint was produced from. This is parsed from the registry name, such as `newton/c:2.5.1-8b-base`, and is `null` if not parseable. A warm-start only loads cleanly from a checkpoint of the same base. Training step at which the checkpoint was produced. Structured metrics captured with the checkpoint (e.g. loss). This is useful for ranking options. The Unix timestamp (seconds) at which the checkpoint was produced. Whether or not more options exist beyond this page. Cursor to continue in the direction of travel — pass it as `after` when paging forward (the default), or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.6/fine_tuning/checkpoints?model=newton&limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.6/fine_tuning/checkpoints", headers={"Authorization": f"Bearer {api_key}"}, params={"model": "newton", "limit": 20} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ model: 'newton', limit: '20' }); const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/checkpoints?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - Selectable checkpoints theme={"system"} { "object": "list", "data": [ { "id": "ckp_...", "name": "newton/c:2.5.1-8b-base", "base_model": "newton/c:2.5.1-8b-base", "step": 1000, "metrics": { "loss": 0.123 }, "created_at": 1765201323 } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` # List Job Checkpoints Source: https://docs.archetypeai.app/api-reference/fine-tuning/list-job-checkpoints GET /fine_tuning/jobs/{id}/checkpoints Get a cursor-paginated list of checkpoints produced by the job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Returns a list of checkpoints produced by the job. The list is cursor-paginated, and is in reverse chronological order (newest-first). ## Request The fine-tuning job ID of the job for which to list checkpoints. This is a TypeID-encoded identifier with the `FineTuningJobId` prefix. Forward cursor: return items older than the item with this ID. Pass the `next_cursor` of the previous page. Do not supply both this value and a value for `before`. Backward cursor: return items newer than the item with this ID. Pass the `prev_cursor` of the current page. Mutually exclusive with `after`. The maximum number of items to return. Minimum `1`, maximum `1000`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response Returns a page of checkpoints. The object type of a list response. Always `list`. The checkpoints produced by the training job. Checkpoint identifier. The Unix timestamp (in seconds) at which the checkpoint was produced. The training step at which the checkpoint was produced. The structured metrics captured with the checkpoint. `true` if more checkpoints exist beyond this page. Cursor to continue in the direction of travel — pass it as `after` when paging forward (the default), or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/your-job-id/checkpoints?limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "your-job-id" response = requests.get( f"https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/{job_id}/checkpoints", headers={"Authorization": f"Bearer {api_key}"}, params={"limit": 20} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const jobId = 'your-job-id'; const params = new URLSearchParams({ limit: '20' }); const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/${jobId}/checkpoints?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - Checkpoints theme={"system"} { "object": "list", "data": [ { "id": "ckp_...", "created_at": 1765201323, "step": 1000, "metrics": { "loss": 0.123 } } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 404 - Not found theme={"system"} { "code": "not_found", "message": "Not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # List Job Events Source: https://docs.archetypeai.app/api-reference/fine-tuning/list-job-events GET /fine_tuning/jobs/{id}/events List job-level events for the specified job, cursor-paginated, in chronological order Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Returns a cursor-paginated list of job-level (lifecycle) events for the specified job, with the newest event first. To get a list of all job events, including those from workers, use the [List Job Logs](/api-reference/fine-tuning/list-job-logs) endpoint. ## Request The fine-tuning job ID of the job for which to list events. This is a TypeID-encoded identifier with the `FineTuningJobId` prefix. Filter by severity. Permitted values include `INFO`, `WARN`, `ERROR`, `SUCCESS`, `FAILED`. Case-insensitive search matched against the event message and type. Forward cursor: return events older than the event with this ID. Pass the `next_cursor` of the previous page. Do not supply a value for both this and `before`. Backward cursor: return events newer than the event with this ID. Pass the `prev_cursor` of the current page. Mutually exclusive with `after`. The maximum number of events to return. Minimum `1`, maximum `1000`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response Returns a page of events. The object type of a list response. Always `list`. The contents of the page of events emitted for the job. The event ID. Pass as the `after` cursor to page. The Unix timestamp (in seconds) at which the event was created. Severity. One of `INFO`, `WARN`, `ERROR`, `SUCCESS`, `FAILED`. The event type. Worker index that emitted the event; `null` for job-level events. Human-readable message, if any. `true` if more events exist beyond this page. Cursor to continue in the direction of travel — pass it as `after` when paging forward (the default), or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/your-job-id/events?level=INFO&limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "your-job-id" response = requests.get( f"https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/{job_id}/events", headers={"Authorization": f"Bearer {api_key}"}, params={"level": "INFO", "limit": 20} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const jobId = 'your-job-id'; const params = new URLSearchParams({ level: 'INFO', limit: '20' }); const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/${jobId}/events?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - Job-level events theme={"system"} { "object": "list", "data": [ { "id": "your-event-id", "created_at": 1765201323, "level": "INFO", "type": "job.started", "index": null, "message": "Training started." } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 400 - Invalid cursor theme={"system"} { "code": "invalid_cursor", "message": "Invalid cursor", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 404 - Not found theme={"system"} { "code": "not_found", "message": "Not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # List Job Logs Source: https://docs.archetypeai.app/api-reference/fine-tuning/list-job-logs GET /fine_tuning/jobs/{id}/logs Returns all events for the job, cursor-paginated, newest first Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Returns a cursor-paginated list of events for the job, with the newest event listed first. Unlike [List Job Events](/api-reference/fine-tuning/list-job-events), this endpoint returns all job events, including events from workers. ## Request The fine-tuning job ID. This is a TypeID-encoded identifier with the `FineTuningJobId` prefix. Filter by severity, e.g. `INFO`, `WARN`, `ERROR`, `SUCCESS`, `FAILED`. Case-insensitive search matched against the event message and type. Forward cursor: return events older than the event with this ID. Pass the `next_cursor` of the previous page. Mutually exclusive with `before`. Backward cursor: return events newer than the event with this ID. Pass the `prev_cursor` of the current page. Mutually exclusive with `after`. The maximum number of events to return. Minimum `1`, maximum `1000`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response Returns a page of events. The object type of a list response. Always `list`. The events emitted for the job. Describes a single event. The event ID. Pass as the `after` cursor to page. The Unix timestamp (in seconds) at which the event was created. The event's severity. One of `INFO`, `WARN`, `ERROR`, `SUCCESS`, `FAILED`. The event type. The worker index that emitted the event; `null` for job-level events. The human-readable message, if any. Whether or not more events exist beyond this page. Cursor to continue in the direction of travel — pass it as `after` when paging forward (the default), or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/your-job-id/logs?level=INFO&limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "your-job-id" response = requests.get( f"https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/{job_id}/logs", headers={"Authorization": f"Bearer {api_key}"}, params={"level": "INFO", "limit": 20} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const jobId = 'your-job-id'; const params = new URLSearchParams({ level: 'INFO', limit: '20' }); const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/${jobId}/logs?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - All events theme={"system"} { "object": "list", "data": [ { "id": "your-event-id", "created_at": 1765201323, "level": "INFO", "type": "worker.log", "index": 0, "message": "step 1000 | loss 0.123" } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 400 - Invalid cursor theme={"system"} { "code": "invalid_cursor", "message": "Invalid cursor", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 404 - Not found theme={"system"} { "code": "not_found", "message": "Not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # List Job Metrics Source: https://docs.archetypeai.app/api-reference/fine-tuning/list-job-metrics GET /fine_tuning/jobs/{id}/metrics Get per-step training and evaluation metrics for the job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Returns per-step training and evaluation metrics for the job (e.g. the loss curve). This list is cursor-paginated and is sorted newest-first. You can filter the list to a single series using the `kind` parameter. ## Request The fine-tuning job ID for whicch to return metrics. This is a TypeID-encoded identifier with the `FineTuningJobId` prefix. Filters the results to a single series: `train` (per-step), `eval` (held-out passes), or `train_summary` (end-of-run aggregate). Omit this parameter to return all metrics. Forward cursor: return points older than the one with this ID. Pass the `next_cursor` of the previous page. Mutually exclusive with `before`. Backward cursor: return points newer than the one with this ID. Pass the `prev_cursor` of the current page. Mutually exclusive with `after`. The maximum number of points to return. Minimum `1`, maximum `1000`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response Returns a page of metric datapoints. The object type of a list response. Always `list`. The training/evaluation metric datapoints. Each datapoint is represented by a `FineTuningMetric` record. A single fine-tuning metric. A unique datapoint ID. Pass as the `after` cursor to page. The Unix timestamp (in seconds) at which the datapoint was created. The series this datapoint belongs to: `train` / `eval` / `train_summary`. The training step at which the datapoint was logged. The metrics logged at this step (e.g. `loss`, `learning_rate`, `eval_loss`). Whether or not more datapoints exist beyond this page. Cursor to continue in the direction of travel — pass it as `after` when paging forward (the default), or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor. ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/your-job-id/metrics?kind=train&limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "your-job-id" response = requests.get( f"https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/{job_id}/metrics", headers={"Authorization": f"Bearer {api_key}"}, params={"kind": "train", "limit": 20} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const jobId = 'your-job-id'; const params = new URLSearchParams({ kind: 'train', limit: '20' }); const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/${jobId}/metrics?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - Training metrics theme={"system"} { "object": "list", "data": [ { "id": "your-metric-id", "created_at": 1765201323, "kind": "train", "step": 1000, "metrics": { "loss": 0.123, "learning_rate": 0.0001 } } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` ```json 400 - Invalid cursor theme={"system"} { "code": "invalid_cursor", "message": "Invalid cursor", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 404 - Not found theme={"system"} { "code": "not_found", "message": "Not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # List Fine-tuning Jobs Source: https://docs.archetypeai.app/api-reference/fine-tuning/list-jobs GET /fine_tuning/jobs Retrieve a cursor-paginated, sortable list of fine-tuning jobs Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Returns a cursor-paginated list of fine-tuning jobs. You can filter by `model`, `method`, `status`, `outcome`, or a free-text search using the `q` parameter. The list is ordered on the field identified by `sort` (`created_at` by default), in the direction specified by `order`. Ties are broken on `created_at`, then `id`. The page is in sort order whether it was reached with `after` or `before`. Cursors are opaque and bound to the `sort` they were issued under; a cursor from another sort returns an HTTP `400` error. An invalid filter, sort, order, or cursor also returns an HTTP `400` error. ## Request Filter by model, e.g. `newton`. Filter by training method, e.g. `lora` or `head`. Filter by lifecycle status, e.g. `PENDING`, `RUNNING`, `PAUSED`, `COMPLETED`, `FAILED`, `INTERRUPTED`, `CANCELLED`. Filter by completion outcome (`SUCCESS`/`PARTIAL`/`FAILED`). Only completed jobs carry an outcome, so specifying a value for this parameter implicitly limits results to completed jobs. [v1.1.5+](/release-notes/1.1.x#v1-1-5) Case-insensitive search matched against the job name, suffix, and produced model name. Specifies the field on which the returned list is ordered. Ties are broken on `created_at`, then `id`, so pages are stable. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Must be one of the following: | Value | Description | | - | - | | `created_at` | Sort by the job's creation timestamp. **Default value.** | | `finished_at` | Sort by the job's finish timestamp. Jobs with a null `finished_at` sort as the earliest (last under `desc`). | | `status` | Sort by lifecycle position, not by the raw status value, in this order: `PENDING`, `ADMITTED`, `RUNNING`, `PAUSED`, `INTERRUPTED`, `PREEMPTED`, `COMPLETED`, `FAILED`, `CANCELLED` | Specifies whether sorting is performed in ascending order (`asc`) or descending order (`desc`). When sorting by `created_at` or `finished_at`, this defaults to `desc`. When sorting by `status`, this defaults to `asc`. A cursor marks a position in the list and stays valid under either direction. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Forward cursor: return the jobs that follow this page's last job in the sort order. This value is opaque; pass the previous page's `next_cursor`. A cursor is bound to the `sort` it was issued under; using it with a different `sort` returns an HTTP `400` error. Mutually exclusive with `before`; sending both returns an HTTP `400` error. [v1.1.12+](/release-notes/1.1.x#v1-1-12) Backward cursor: return the jobs that precede this page's first job in the sort order. This value is opaque; pass the current page's `prev_cursor`. Mutually exclusive with `after`; sending both returns an HTTP `400` error. [v1.1.12+](/release-notes/1.1.x#v1-1-12) The maximum number of jobs to return. Minimum `1`, maximum `1000`. [v1.1.11+](/release-notes/1.1.x#v1-1-11) ## Response Returns a page of fine-tuning jobs. The object type. Always `list`. An array of the jobs for this page, sorted by the column specified by `sort`, in the ordering specified by `order` (newest first by default) in both cursor directions. Each item is a fine-tuning job object. The description of a single fine-tuning job. The object type. Always `fine_tuning.job`. The unique identifier of the fine-tuning job. The human-readable name supplied when the job was created. The base model being fine-tuned. The Unix timestamp (in seconds) at which the job was created. The organization that owns the job. The job's current lifecycle stage. One of `PENDING`, `ADMITTED`, `RUNNING`, `COMPLETED`, `FAILED`, `PREEMPTED`, `CANCELLED`, `PAUSED`, `INTERRUPTED`. If and only if the job's `status` is `COMPLETED`, this property's value indicates *how* the job completed. It is set once upon completion and is never set for a job which is not completed; for incomplete jobs, this value is always omitted. [v1.1.5+](/release-notes/1.1.x#v1-1-5) For completed jobs, the following values are possible: | Value | Description | | - | - | | `SUCCESS` | None of the job's inputs failed. | | `PARTIAL` | At least one of the job's inputs failed, but the job still produced at least one artifact (either a `job_outputs` entry or a `checkpoints` entry). | | `FAILED` | At least one input failed, and the job produced no artifacts at all (no outputs and no checkpoints). | Identifiers of the training files used to train the model. Identifiers of the files used to evaluate the model during training. When the job has failed, this array lists the error(s) that occcurred, as the platform error envelope (a list of `{code, message, suggestion, error_uid}`). Empty while the job is queued/running or on success. The ID of the checkpoint the job was started from, or `null` if it trained from the base model. Name of the model produced by the job. This is only available once training has succeeded; until then, this value is `null`. The Unix timestamp (in seconds) at which the job finished, or `null` if it is not yet complete. For a `COMPLETED` job, this value indicates whether it succeeded fully (`SUCCESS`), partially (`PARTIAL`), or produced nothing (`FAILED`). For any job that hasn't completed, this value is `null`. The random seed used for the job. The suffix supplied on the request, applied to the fine-tuned model's name. Whether more jobs exist beyond this page in the direction of travel. Cursor to continue in the direction of travel — pass it as `after` when paging forward (the default), or as `before` when the request used `before`. `null` when `has_more` is false. [v1.1.11+](/release-notes/1.1.x#v1-1-11) Cursor to step back the way this page was reached — pass it as `before` after a forward page, or as `after` after a backward one. `null` when the request carried no cursor (the first page has nothing to step back to). [v1.1.12+](/release-notes/1.1.x#v1-1-12) ```bash cURL theme={"system"} curl "https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs?model=newton&status=RUNNING&limit=20" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs", headers={"Authorization": f"Bearer {api_key}"}, params={"model": "newton", "status": "RUNNING", "limit": 20} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const params = new URLSearchParams({ model: 'newton', status: 'RUNNING', limit: '20' }); const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs?${params}`, { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - A page of fine-tuning jobs theme={"system"} { "object": "list", "data": [ { "object": "fine_tuning.job", "id": "your-job-id", "name": "my-tune", "model": "newton", "created_at": 1765201323, "org_id": "your-org", "status": "RUNNING", "checkpoint_id": null, "fine_tuned_model": null, "finished_at": null, "outcome": null, "seed": 42, "user_provided_suffix": "v2", "training_files": ["fil_..."], "validation_files": ["fil_..."], "errors": [] } ], "has_more": false, "next_cursor": null, "prev_cursor": null } ``` # Pause Fine-tuning Job Source: https://docs.archetypeai.app/api-reference/fine-tuning/pause-job POST /fine_tuning/jobs/{id}/pause Pause a fine-tuning job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Pauses a fine-tuning job, stopping the run; use [Resume Job](/api-reference/fine-tuning/resume-job) to continue it. To cancel a job and tear down its resources without the ability to resume the job, use the [Cancel Job](/api-reference/fine-tuning/cancel-job) endpoint instead. ## Request The fine-tuning job ID of the job to pause. This is a TypeID-encoded identifier with the `FineTuningJobId` prefix. ## Response Returns a description of the fine-tuning job's state after pausing. The object type. Always `fine_tuning.job`. Unique identifier of the fine-tuning job. The human-readable name supplied when the job was created. The base model being fine-tuned. The Unix timestamp (in seconds) at which the job was created. The organization that owns the job. The job's current lifecycle stage. One of `PENDING`, `ADMITTED`, `RUNNING`, `COMPLETED`, `FAILED`, `PREEMPTED`, `CANCELLED`, `PAUSED`, `INTERRUPTED`. Always `null` for paused jobs. This property does not take on a value until the job's `status` is `COMPLETED`. [v1.1.5+](/release-notes/1.1.x#v1-1-5) Identifiers of the files used to train the model. Identifiers of the files used to evaluate the model during training. Failure details if the job has failed, as the platform error envelope (a list of `{code, message, suggestion, error_uid}`). Empty while the job is queued, the job is running, or when the job has successfully completed. The checkpoint ID of the checkpoint from which the job was started, or `null` if it trained from the base model. Name of the model produced by the job. This is available once training has succeeded, and is `null` until then. The Unix timestamp (in seconds) at which the job finished, or `null` if it is not yet complete. For a `COMPLETED` job, this specifies whether it succeeded fully (`SUCCESS`), partially (`PARTIAL`), or produced nothing (`FAILED`). If the job hasn't yet completed, this is `null`. The random seed used for the job. The suffix supplied on the request, applied to the fine-tuned model's name. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/your-job-id/pause \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "your-job-id" response = requests.post( f"https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/{job_id}/pause", headers={"Authorization": f"Bearer {api_key}"} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const jobId = 'your-job-id'; const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/${jobId}/pause`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - Fine-tuning job paused theme={"system"} { "object": "fine_tuning.job", "id": "your-job-id", "name": "my-tune", "model": "newton", "created_at": 1765201323, "org_id": "your-org", "status": "PAUSED", "checkpoint_id": null, "fine_tuned_model": null, "finished_at": null, "outcome": null, "seed": 42, "user_provided_suffix": "v2", "training_files": ["fil_..."], "validation_files": ["fil_..."], "errors": [] } ``` ```json 404 - Not found theme={"system"} { "code": "not_found", "message": "Not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 409 - Invalid state transition theme={"system"} { "code": "invalid_state_transition", "message": "Invalid state transition", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # Resume Fine-tuning Job Source: https://docs.archetypeai.app/api-reference/fine-tuning/resume-job POST /fine_tuning/jobs/{id}/resume Resume a paused or failed fine-tuning job Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Resumes a paused or failed fine-tuning job, continuing from the most recent checkpoint. ## Request The ID of the fine-tuning job to resume. This is a TypeID-encoded identifier with the `FineTuningJobId` prefix. ## Response Returns a description of the fine-tuning job after resuming it. The object type. Always `fine_tuning.job`. The unique identifier of the fine-tuning job. The human-readable name supplied when the job was created. The base model being fine-tuned. The Unix timestamp (in seconds) at which the job was created. The organization that owns the job. The job's current lifecycle stage. One of `PENDING`, `ADMITTED`, `RUNNING`, `COMPLETED`, `FAILED`, `PREEMPTED`, `CANCELLED`, `PAUSED`, `INTERRUPTED`. Always `null` for resumed jobs. This property does not take on a value until the job's `status` is `COMPLETED`. [v1.1.5+](/release-notes/1.1.x#v1-1-5) Identifiers of the files used to train the model. Identifiers of the files used to evaluate the model during training. Failure details when the job has failed, as the platform error envelope (a list of `{code, message, suggestion, error_uid}`). Empty while the job is queued or running, or on success. The checkpoint ID of the checkpoint from which the job was started (**not** the checkpoint from which the job was resumed), or `null` if it trained from the base model. The name of the model produced by the job, available once training has succeeded; `null` until then. The Unix timestamp (in seconds) at which the job finished, or `null` if it is not yet complete. For a `COMPLETED` job, this indicates whether it succeeded fully (`SUCCESS`), partially (`PARTIAL`), or produced nothing (`FAILED`). This is `null` for any non-completed status. The random seed used for the job. The suffix supplied on the request, applied to the fine-tuned model's name. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/your-job-id/resume \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") job_id = "your-job-id" response = requests.post( f"https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/{job_id}/resume", headers={"Authorization": f"Bearer {api_key}"} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const jobId = 'your-job-id'; const response = await fetch( `https://api.u1.archetypeai.app/v0.6/fine_tuning/jobs/${jobId}/resume`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } } ); const data = await response.json(); console.log(data); ``` ```json 200 - Fine-tuning job resumed theme={"system"} { "object": "fine_tuning.job", "id": "your-job-id", "name": "my-tune", "model": "newton", "created_at": 1765201323, "org_id": "your-org", "status": "PENDING", "checkpoint_id": "ckp_...", "fine_tuned_model": null, "finished_at": null, "outcome": null, "seed": 42, "user_provided_suffix": "v2", "training_files": ["fil_..."], "validation_files": ["fil_..."], "errors": [] } ``` ```json 404 - Not found theme={"system"} { "code": "not_found", "message": "Not found", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` ```json 409 - Invalid state transition theme={"system"} { "code": "invalid_state_transition", "message": "Invalid state transition", "suggestion": null, "error_uid": "err-xxxxxxxx" } ``` # Overview Source: https://docs.archetypeai.app/api-reference/introduction Complete reference for APIs ## Base URL All API requests should be made to: ``` https://api.u1.archetypeai.app/v0.5 ``` ## Authentication All API requests require authentication using your API key: ```bash theme={"system"} Authorization: Bearer YOUR_API_KEY ``` Don't have an API key yet? [Request a free trial](https://forms.gle/yTu6xp7CCEvAYLqB9) to get access and register your interest in a hands-on workshop. ## Available APIs Create and manage lens sessions Upload and manage files ## Rate Limits API rate limits vary by plan. Contact [support@archetypeai.dev](mailto:support@archetypeai.dev) for details about your organization's limits. ## Error Handling All API errors follow a consistent format: ```json theme={"system"} { "error": { "code": "ERROR_CODE", "message": "Human-readable error message", "details": {} } } ``` # About the Lens API Source: https://docs.archetypeai.app/api-reference/lens/about An API to run and manage batch processing jobs against multiple files. A **Lens** is a software interface that allows developers to configure and interact with Newton. Lenses define how sensor data flows in and out of Newton and specify how Newton should interpret that data for a given use case. The Lens API creates and manages Lenses. The Lens API has been deprecated and should no longer be used. # Consume Session Events (SSE) Source: https://docs.archetypeai.app/api-reference/lens/consumer GET /lens/sessions/consumer/{session_id} Subscribe to a lens session’s Server-Sent Events stream to receive asynchronous inference results Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint opens a [Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) stream for an active lens session. Output processors of type `server_sent_events_writer` (used by the Activity Monitor lens and most cookbook lenses) write inference results, log messages, and stream status events to this channel. Lens sessions route outputs through **one of two channels**, never both: * **SSE consumer** (this endpoint) — for lenses whose `model_pipeline` includes a `server_sent_events_writer` output processor. * **WebSocket mailbox** — drained via [`session.read`](/api-reference/lens/websocket-events#session-read). If [`session.read`](/api-reference/lens/websocket-events#session-read) returns `event_data: null` while [`GET /lens/sessions/metadata`](/api-reference/lens/get-sessions-metadata) shows non-zero `num_outputs`, the lens is writing to the SSE consumer — use this endpoint. The official [`archetypeai` Python SDK](https://pypi.org/project/archetypeai/) exposes this endpoint as `lens.create_sse_consumer(session_id)`. ## Path Parameters Identifier of the active session whose output stream to subscribe to. Returned by [Create Lens Session](/api-reference/lens/create-session). ## Headers `Bearer YOUR_API_KEY` `text/event-stream` (recommended — signals SSE intent to the server and to intermediaries) Optional cursor. When set, the server resumes the stream after the event with the given `id`, so reconnecting clients do not miss or duplicate messages. Matches the standard SSE reconnection semantic. ## Response The response is an `text/event-stream` HTTP response. Each frame is a standard SSE record: ``` event: message id: data: {"type": "", ...} ``` The `data:` payload is JSON and always includes a `type` field identifying the event. The consumer emits three envelope event types in addition to lens-specific output events: First frame emitted after the connection is established. Carries the `session_id` of the stream and a server-assigned `reader_id` that identifies this consumer connection. ```json theme={"system"} { "type": "sse.stream.start", "event_data": { "session_id": "lsn-...", "reader_id": "" } } ``` Periodic keepalive frame used to hold the connection open through proxies and to surface session-side counters. `message_timeout` increments with each heartbeat — clients should ignore the payload contents but can use the frame as a liveness signal. ```json theme={"system"} { "type": "sse.stream.heartbeat", "event_data": { "session_id": "lsn-...", "session_status": "SESSION_STATUS_RUNNING", "num_messages": 0, "num_bytes": 0, "message_timeout": 5.0 } } ``` The server is closing the stream gracefully (for example, the session was destroyed). Clients should stop consuming after receiving this event. All other `type` values are lens-specific output events. Typical types emitted by `server_sent_events_writer` include `inference.result`, `log.info`, `frame.processed`, and `error`. The exact shape of the `data` payload depends on the lens's `model_pipeline` and the processor that produced the event. ```bash cURL theme={"system"} curl -N https://api.u1.archetypeai.app/v0.5/lens/sessions/consumer/lsn-250313c2177253cbaa7a73542edd90 \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Accept: text/event-stream" ``` ```python Python theme={"system"} import json import requests import os api_key = os.environ.get("ATAI_API_KEY") session_id = "lsn-250313c2177253cbaa7a73542edd90" with requests.get( f"https://api.u1.archetypeai.app/v0.5/lens/sessions/consumer/{session_id}", headers={ "Authorization": f"Bearer {api_key}", "Accept": "text/event-stream", }, stream=True, timeout=(10, None), ) as resp: resp.raise_for_status() for line in resp.iter_lines(decode_unicode=True): if not line or not line.startswith("data:"): continue payload = json.loads(line[len("data:"):].strip()) if payload.get("type") == "sse.stream.heartbeat": continue if payload.get("type") == "sse.stream.end": break print(payload) ``` ```python Python (SDK) theme={"system"} from archetypeai import ArchetypeAI client = ArchetypeAI() reader = client.lens.create_sse_consumer(session_id="lsn-250313c2177253cbaa7a73542edd90") for event in reader.read(block=True): print(event) ``` ```javascript JavaScript theme={"system"} // EventSource cannot set Authorization headers; use fetch with a streaming // reader instead. const sessionId = "lsn-250313c2177253cbaa7a73542edd90"; const response = await fetch( `https://api.u1.archetypeai.app/v0.5/lens/sessions/consumer/${sessionId}`, { headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, Accept: "text/event-stream", }, } ); const reader = response.body.getReader(); const decoder = new TextDecoder(); let buffer = ""; while (true) { const { value, done } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); let idx; while ((idx = buffer.indexOf("\n\n")) !== -1) { const frame = buffer.slice(0, idx); buffer = buffer.slice(idx + 2); const dataLine = frame.split("\n").find((l) => l.startsWith("data:")); if (!dataLine) continue; const payload = JSON.parse(dataLine.slice("data:".length).trim()); if (payload.type === "sse.stream.heartbeat") continue; if (payload.type === "sse.stream.end") return; console.log(payload); } } ``` ```text 200 - Success (excerpt) theme={"system"} event: message data: {"type": "sse.stream.start", "event_data": {"session_id": "lsn-...", "reader_id": "87e6d51c992557bc"}} event: message data: {"type": "sse.stream.heartbeat", "event_data": {"session_id": "lsn-...", "session_status": "SESSION_STATUS_RUNNING", "num_messages": 0, "num_bytes": 0, "message_timeout": 5.0}} event: message data: {"type": "inference.result", "timestamp": 1741843200.123, "data": {"result": "A construction worker wearing a hard hat and safety vest"}} event: message data: {"type": "sse.stream.end"} ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Session not found theme={"system"} { "errors": [ { "code": "session_not_found", "message": "No session with the given session_id was found for the organization.", "suggestion": "Verify the session_id and that the session has not been destroyed.", "error_uid": "err-xxxxxxxx" } ] } ``` ## Choosing Between SSE and `session.read` | | SSE consumer (this endpoint) | [`session.read`](/api-reference/lens/websocket-events#session-read) | | - | - | - | | **Transport** | HTTP `text/event-stream` | WebSocket event over `session_endpoint` | | **Pattern** | Server pushes events as they arrive | Client polls; server returns queued messages | | **Used by** | Lenses with `server_sent_events_writer` output processors | Lenses with mailbox-style output processors | | **Cursor / resume** | `Last-Event-ID` request header | `client_id` field in `event_data` | | **Heartbeats** | `sse.stream.heartbeat` envelope events | None (request/response pattern) | | **Graceful close** | `sse.stream.end` envelope event, then HTTP close | Close WebSocket | Inspect the lens's `model_pipeline` via [`GET /lens/metadata`](/api-reference/lens/get-metadata) to see which output processor (and therefore which channel) it uses. # Create Lens Session Source: https://docs.archetypeai.app/api-reference/lens/create-session POST /lens/sessions/create Create a new lens session for processing sensor data Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint creates and allocates a new lens session that can process sensor data streams. Each session is associated with a specific lens and returns a unique **session ID** and endpoint for real-time data streaming. ## Request The ID of the lens to use for this session. Get available lens IDs from `/lens/metadata` ## Response The response contains an `api_key` field that echoes back the caller's real API key. Treat this field as a secret — do not log, persist, or expose it in client-side code. Unique identifier for the created session. The lens ID associated with this session. Name of the lens associated with this session. Organization identifier the session belongs to. The caller's API key, echoed back for downstream WebSocket auth. **Sensitive — see warning above.** WebSocket URL for streaming data to/from the session. Initial status of the session (typically `LensSessionStatus.SESSION_STATUS_REGISTERED`). Maximum session lifetime in seconds (default `86400`, i.e. 24 hours of inactivity). Identifier of the backend runner hosting the session. Resolved lens configuration in use for this session. Unix timestamp when the session record was created. Unix timestamp of the last event processed by the session. Unix timestamp of the last update to the session record. Unix timestamp when the session began running. `null` until the runner starts. Unix timestamp when the session was destroyed. `null` while active. Identifier of the configured input stream, or `null` if none is set. Identifier of the configured output stream, or `null` if none is set. Number of active client connections to the session. Total number of events processed by the session. Number of state updates the session has emitted. Number of input frames/records the session has received. Number of outputs the session has produced. Tag of the runner node the session is bound to. Array of error messages if the request failed (check for this field to detect errors). ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/lens/sessions/create \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lens_id": "lns-fd669361822b07e2-237ab3ffd79199b0" }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/create", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "lens_id": "lns-fd669361822b07e2-237ab3ffd79199b0" } ) data = response.json() if "errors" in data: print(f"Error: {data['errors']}") else: print(f"Session created: {data['session_id']}") print(f"WebSocket endpoint: {data['session_endpoint']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/sessions/create', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ lens_id: 'lns-fd669361822b07e2-237ab3ffd79199b0' }) }); const data = await response.json(); if (data.errors) { console.error('Error:', data.errors); } else { console.log(`Session created: ${data.session_id}`); } ``` ```json 200 - Success theme={"system"} { "org_id": "your-org", "api_key": "", "session_id": "lsn-251207a89f948ed4e30d8f80aaba77", "lens_id": "lns-test-lens-b2ba0058", "lens_name": "Test Lens", "input_data_stream_id": null, "output_data_stream_id": null, "registration_timestamp": 1779428775.5983343, "last_event_timestamp": 1779428775.5983343, "last_update_timestamp": 1779428775.5983343, "session_start_timestamp": null, "session_destroyed_timestamp": null, "num_active_connections": 0, "num_updates": 0, "num_inputs": 0, "num_outputs": 0, "num_events": 0, "lens_config": { "model_pipeline": [ {"processor_name": "lens_noop_processor", "processor_config": {}} ] }, "session_status": "LensSessionStatus.SESSION_STATUS_REGISTERED", "session_runner": "lens_service:runner:lens-node-worker-node-abc123", "session_endpoint": "wss://api.u1.archetypeai.app/v0.5/lens/sessions/lsn-251207a89f948ed4e30d8f80aaba77", "node_tag": "default", "session_ttl_sec": 86400 } ``` ```json 400 - Missing lens_id theme={"system"} { "errors": [ "Invalid lens_id: None" ] } ``` ```json 400 - Non-existent or invalid lens_id theme={"system"} { "errors": [ "Invalid lens config" ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ## Important Notes * Sessions remain active until explicitly destroyed or timeout after no sensor activity * Always destroy sessions when done to free up resources * Check which sessions are running via /lens/sessions/metadata # Destroy Lens Session Source: https://docs.archetypeai.app/api-reference/lens/destroy-session POST /lens/sessions/destroy Destroy an active lens session and free up resources Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint destroys an active lens session, closing any open connections and freeing up resources. Always destroy sessions when you're done using them to avoid hitting concurrent session limits. ## Request The unique session ID to destroy. This is returned when creating a session. ## Response On success, returns the destroyed session record. Errors are returned with an HTTP 4xx status and an `errors` array (no `is_valid` field). The ID of the destroyed session. The lens ID the session was attached to. Final status of the session (typically `SESSION_STATUS_DESTROYED`). Identifier of the backend runner that hosted the session. WebSocket URL the session was reachable at. Unix timestamp of the last update to the session record. Total duration the session was active in seconds. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/lens/sessions/destroy \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "session_id": "lsn-250313c2177253cbaa7a73542edd90" }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/destroy", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "session_id": "lsn-250313c2177253cbaa7a73542edd90" } ) result = response.json() if result.get("is_valid") == False: print(f"Error: {result['errors']}") else: print(f"Session destroyed: {result['session_id']}") print(f"Duration: {result['session_duration_sec']} seconds") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/sessions/destroy', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ session_id: 'lsn-250313c2177253cbaa7a73542edd90' }) }); const result = await response.json(); if (result.is_valid === false) { console.error('Error:', result.errors); } else { console.log(`Session destroyed: ${result.session_id}`); } ``` ```json 200 - Success theme={"system"} { "session_id": "lsn-2512078e5c9ce4d312a6681e771542", "lens_id": "lns-test-lens-3de60a5c", "last_update_timestamp": 1765095462.576972, "session_status": "SESSION_STATUS_DESTROYED", "session_runner": "lens_service:runner:lens-node-worker-node-abc123", "session_endpoint": "wss://api.u1.archetypeai.app/v0.5/lens/sessions/lsn-2512078e5c9ce4d312a6681e771542", "session_duration_sec": 53.79125928878784 } ``` ```json 400 - Missing session_id theme={"system"} { "errors": [ "Missing session_id!" ] } ``` ```json 400 - Non-existent or already destroyed session theme={"system"} { "errors": [ "Invalid session_id: lsn-nonexistent-12345678" ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ## Best Practices **Always clean up sessions**: Implement proper cleanup in your code to ensure sessions are destroyed even if errors occur: ```python theme={"system"} try: # Create and use session session = create_session(lens_id) process_data(session) finally: # Always destroy the session destroy_session(session['session_id']) ``` Sessions that are not explicitly destroyed will: * Continue consuming your concurrent session quota * Timeout after 30 minutes of inactivity * May result in hitting rate limits for new session creation # Lens API Examples Source: https://docs.archetypeai.app/api-reference/lens/examples Complete examples for CSV streaming and RTSP camera integration Complete working examples for common use cases using the Lens Events API. **Prerequisites**: Set your API key as an environment variable: ```bash theme={"system"} export ATAI_API_KEY="your-api-key-here" ``` ## CSV File Streaming Example Stream data from a CSV file through a lens for time-series analysis. ### Step 1: Download Sample Data ```bash theme={"system"} # Download example CSV file curl -L -o ~/Downloads/jena-climate.zip \ https://www.kaggle.com/api/v1/datasets/download/mnassrib/jena-climate # Extract the CSV file unzip ~/Downloads/jena-climate.zip ``` ### Step 2: Upload CSV File ```python Python (files_api.py) theme={"system"} import requests import argparse def upload_csv_file(api_key, filename): """Upload a CSV file to the Newton platform.""" with open(filename, 'rb') as f: response = requests.post( 'https://api.u1.archetypeai.app/v0.5/files/upload', headers={'Authorization': f'Bearer {api_key}'}, files={'file': f}, data={ 'description': f'Climate data CSV: {filename}', 'tags': ['climate', 'time-series', 'example'] } ) if response.status_code == 200: file_data = response.json() print(f"✅ File uploaded successfully!") print(f" File ID: {file_data['file_id']}") print(f" Size: {file_data['size_bytes'] / 1024 / 1024:.2f} MB") return file_data['file_id'] else: print(f"❌ Upload failed: {response.status_code}") print(response.text) return None if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--api_key", required=True, help="Your Newton API key") parser.add_argument("--filename", required=True, help="CSV file to upload") args = parser.parse_args() file_id = upload_csv_file(args.api_key, args.filename) if file_id: print(f"\n🎯 Use this file_id in your lens streaming: {file_id}") ``` ```bash Usage theme={"system"} python files_api.py --api_key=$ATAI_API_KEY --filename=jena_climate_2009_2016.csv ``` ### Step 3: Stream CSV Through Lens ```python Python (lens_csv_stream.py) theme={"system"} import websocket import json import argparse import time import requests def create_lens_session(api_key, lens_id="lns-fd669361822b07e2-237ab3ffd79199b0"): """Create a new lens session.""" response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/create", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={"lens_id": lens_id} ) if response.status_code == 200: return response.json() else: raise Exception(f"Failed to create session: {response.text}") def send_and_receive_event(socket, event_data): """Send event and wait for response.""" socket.send_binary(json.dumps(event_data).encode()) response = json.loads(socket.recv()) return response def stream_csv_data(api_key, file_id, max_run_time_sec=60): """Stream CSV data through a Newton lens.""" print("🚀 Creating lens session...") session = create_lens_session(api_key) print(f" Session ID: {session['session_id']}") # Connect to WebSocket print("🔌 Connecting to WebSocket...") socket = websocket.create_connection( session['session_endpoint'], header={"Authorization": f"Bearer {api_key}"} ) print(" Connected!") try: # Validate session print("✅ Validating session...") response = send_and_receive_event(socket, {"type": "session.validate"}) if not response.get("valid"): raise Exception(f"Session validation failed: {response}") print(" Session is valid!") # Configure CSV input stream print(f"📊 Configuring CSV stream for file: {file_id}") event_message = { "type": "input_stream.set", "event_data": { "stream_type": "csv_file_reader", "stream_config": { "file_id": file_id } } } response = send_and_receive_event(socket, event_message) print(f" Stream configured: {response}") # Read streaming results print("📖 Reading streaming results...") client_id = f"csv_client_{int(time.time())}" start_time = time.time() while time.time() - start_time < max_run_time_sec: # Read any pending messages read_event = { "type": "session.read", "event_data": {"client_id": client_id} } response = send_and_receive_event(socket, read_event) # Process messages messages = response.get("messages", []) for message in messages: timestamp = message.get("timestamp", "unknown") msg_type = message.get("type", "unknown") data = message.get("data", {}) if msg_type == "inference.result": print(f"🔬 [{timestamp}] Analysis: {data.get('result', 'No result')}") elif msg_type == "log.info": print(f"ℹ️ [{timestamp}] Info: {data}") elif msg_type == "error": print(f"❌ [{timestamp}] Error: {data}") time.sleep(2) # Poll every 2 seconds print("⏰ Max runtime reached, stopping...") finally: # Clean up print("🧹 Cleaning up...") try: send_and_receive_event(socket, {"type": "session.destroy"}) print(" Session destroyed") except: pass socket.close() print(" WebSocket closed") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--api_key", required=True, help="Your Newton API key") parser.add_argument("--file_id", required=True, help="CSV file ID from upload") parser.add_argument("--max_run_time_sec", type=int, default=60, help="Max runtime in seconds") args = parser.parse_args() try: stream_csv_data(args.api_key, args.file_id, args.max_run_time_sec) except Exception as e: print(f"❌ Error: {e}") ``` ```bash Usage theme={"system"} python lens_csv_stream.py --api_key=$ATAI_API_KEY --file_id=jena_climate_2009_2016.csv --max_run_time_sec=120 ``` **What you should expect:** * `Creating lens session…` then `Connecting to WebSocket…` → both succeed in under 1s. * `Validating session…` → `Session is valid!` returns `{"type": "session.validate.response", "event_data": {"is_valid": true, "error_messages": []}}`. * `Configuring CSV stream…` → `Stream configured: {'type': 'input_stream.set.response', 'event_data': {'is_valid': true, 'error_messages': []}}`. * `Reading streaming results…` → the content depends entirely on the lens you connect the stream to. A lens whose pipeline matches the CSV's schema (column names, sampling rate) will emit `inference.result` messages over time; an incompatible lens will return `{"type": "session.read.response", "event_data": null}` on each poll. Confirm the lens's expected schema from [`GET /lens/metadata`](/api-reference/lens/get-metadata) before running. ## RTSP Camera Streaming Example Stream real-time video from an RTSP camera for live analysis. ```python Python (lens_rtsp_camera.py) theme={"system"} import websocket import json import argparse import time import requests import uuid def create_lens_session(api_key, lens_id="lns-fd669361822b07e2-237ab3ffd79199b0"): """Create a new lens session for video analysis.""" response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/create", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={"lens_id": lens_id} ) if response.status_code == 200: return response.json() else: raise Exception(f"Failed to create session: {response.text}") def send_and_receive_event(socket, event_data): """Send event and wait for response.""" socket.send_binary(json.dumps(event_data).encode()) response = json.loads(socket.recv()) return response def stream_rtsp_camera(api_key, rtsp_url, max_run_time_sec=60): """Stream RTSP camera feed through Newton for real-time analysis.""" print("🚀 Creating lens session for video analysis...") session = create_lens_session(api_key) print(f" Session ID: {session['session_id']}") # Connect to WebSocket print("🔌 Connecting to WebSocket...") socket = websocket.create_connection( session['session_endpoint'], header={"Authorization": f"Bearer {api_key}"} ) print(" Connected!") try: # Validate session print("✅ Validating session...") response = send_and_receive_event(socket, {"type": "session.validate"}) if not response.get("valid"): raise Exception(f"Session validation failed: {response}") print(" Session is valid!") # Configure RTSP input stream print(f"📹 Configuring RTSP stream: {rtsp_url}") event_message = { "type": "input_stream.set", "event_data": { "stream_type": "rtsp_video_streamer", "stream_config": { "rtsp_url": rtsp_url, "target_image_size": [360, 640], # [height, width] "target_frame_rate_hz": 0.2 # Process 1 frame every 5 seconds } } } response = send_and_receive_event(socket, event_message) print(f" RTSP stream configured: {response}") # Read streaming analysis results print("🔬 Reading real-time analysis...") client_id = str(uuid.uuid4())[:8] start_time = time.time() while time.time() - start_time < max_run_time_sec: # Read any pending messages read_event = { "type": "session.read", "event_data": {"client_id": client_id} } response = send_and_receive_event(socket, read_event) # Process messages messages = response.get("messages", []) for message in messages: timestamp = message.get("timestamp", "unknown") msg_type = message.get("type", "unknown") data = message.get("data", {}) if msg_type == "inference.result": result = data.get('result', 'No analysis') confidence = data.get('confidence', 0) processing_time = data.get('processing_time_ms', 0) print(f"🎥 [{timestamp}] Analysis: {result}") print(f" Confidence: {confidence:.2f}, Processing: {processing_time}ms") elif msg_type == "frame.processed": frame_num = data.get('frame_number', 0) print(f"🖼️ [{timestamp}] Frame {frame_num} processed") elif msg_type == "stream.status": status = data.get('status', 'unknown') print(f"📡 [{timestamp}] Stream status: {status}") elif msg_type == "log.info": print(f"ℹ️ [{timestamp}] {data}") elif msg_type == "error": print(f"❌ [{timestamp}] Error: {data}") if not messages: print("⏳ Waiting for video frames...") time.sleep(3) # Poll every 3 seconds print("⏰ Max runtime reached, stopping stream...") finally: # Clean up print("🧹 Cleaning up...") try: send_and_receive_event(socket, {"type": "session.destroy"}) print(" Session destroyed") except: pass socket.close() print(" WebSocket closed") if __name__ == "__main__": parser = argparse.ArgumentParser(description="Stream RTSP camera through Newton") parser.add_argument("--api_key", required=True, help="Your Newton API key") parser.add_argument("--rtsp_url", required=True, help="RTSP camera URL") parser.add_argument("--max_run_time_sec", type=int, default=60, help="Max runtime in seconds") args = parser.parse_args() try: stream_rtsp_camera(args.api_key, args.rtsp_url, args.max_run_time_sec) except Exception as e: print(f"❌ Error: {e}") ``` ```bash Usage theme={"system"} # Example with public traffic camera python lens_rtsp_camera.py \ --api_key=$ATAI_API_KEY \ --rtsp_url=rtsp://123456789.stream \ --max_run_time_sec=120 # Example with local camera python lens_rtsp_camera.py \ --api_key=$ATAI_API_KEY \ --rtsp_url=rtsp://192.168.1.100:554/stream \ --max_run_time_sec=300 ``` **What you should expect:** * Session creation, WebSocket connection, and `session.validate` all succeed (same envelope shapes as the CSV example above). * `RTSP stream configured: {'type': 'input_stream.set.response', 'event_data': {'is_valid': true, ...}}`. * `inference.result` payloads arrive on `session.read` polls — typical content is a short natural-language description of the latest frame batch (no `confidence` or `processing_time_ms` fields are guaranteed by the model). Frequency depends on the lens's `camera_buffer_size` and the `target_frame_rate_hz` you configured on the stream. * An unreachable RTSP URL surfaces as an error message in subsequent `session.read` polls rather than a synchronous error on `input_stream.set`. ## Direct Image Analysis Example Send individual images for immediate analysis without setting up streams. `model.query` only works against lenses whose pipeline includes a model-query processor (i.e. **not** the Activity Monitor — which uses `lens_camera_processor` and expects camera input). If your `model.query` returns `{"type": "model.query.response", "message": "Response timed out for query"}`, the lens is not configured to handle direct queries. Register a model-query lens first via [`POST /lens/register`](/api-reference/lens/lens-register) or use a streaming approach with `input_stream.set` instead. ```python Python (direct_image_analysis.py) theme={"system"} import websocket import json import base64 import argparse import requests def analyze_image_direct(api_key, image_path, focus="Describe what you see"): """Analyze a single image using direct model query.""" # Create session print("🚀 Creating lens session...") response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/create", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={"lens_id": "lns-fd669361822b07e2-237ab3ffd79199b0"} ) session = response.json() # Connect WebSocket print("🔌 Connecting to WebSocket...") socket = websocket.create_connection( session['session_endpoint'], header={"Authorization": f"Bearer {api_key}"} ) try: # Load and encode image print(f"📸 Loading image: {image_path}") with open(image_path, "rb") as img_handle: base64_img = base64.b64encode(img_handle.read()).decode("utf-8") # Send direct query print("🔬 Analyzing image...") event_message = { "type": "model.query", "event_data": { "model_version": "Newton::c2_4_7b_251215a172f6d7", "template_name": "image_qa_template_task", "instruction": "Answer the following question about the image:", "focus": focus, "max_new_tokens": 512, "data": [{ "type": "base64_img", "base64_img": base64_img }], "sensor_metadata": {} } } socket.send_binary(json.dumps(event_message).encode()) response = json.loads(socket.recv()) # Display results (model.query responses are wrapped in event_data) result_data = response.get('event_data') or {} print("\n🎯 Analysis Results:") print("=" * 50) print(f"Focus: {focus}") print(f"Result: {result_data.get('result', 'No result')}") print("=" * 50) return response finally: # Cleanup try: socket.send_binary(json.dumps({"type": "session.destroy"}).encode()) socket.recv() # Wait for destroy confirmation except: pass socket.close() def detect_objects_in_image(api_key, image_path, objects_to_find=["person", "car", "truck"]): """Detect specific objects in an image with bounding boxes.""" # Create session response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/create", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={"lens_id": "lns-fd669361822b07e2-237ab3ffd79199b0"} ) session = response.json() # Connect WebSocket socket = websocket.create_connection( session['session_endpoint'], header={"Authorization": f"Bearer {api_key}"} ) try: # Load and encode image with open(image_path, "rb") as img_handle: base64_img = base64.b64encode(img_handle.read()).decode("utf-8") # Object detection query objects_str = ",".join(objects_to_find) event_message = { "type": "model.query", "event_data": { "model_version": "Newton::c2_4_7b_251215a172f6d7", "template_name": "image_bbox_template_task", "instruction": "Localize all objects in the picture and build bounding box around them.", "focus": f"Input: [{objects_str}]", "max_new_tokens": 512, "data": [{ "type": "base64_img", "base64_img": base64_img }], "sensor_metadata": {} } } socket.send_binary(json.dumps(event_message).encode()) response = json.loads(socket.recv()) # Parse and display bounding boxes (model.query response is wrapped in event_data) print(f"\n🎯 Object Detection Results:") print("=" * 50) result = (response.get('event_data') or {}).get('result', '') if result: for line in result.split('\n'): if ':' in line: obj_name, bbox = line.split(':', 1) print(f"📦 {obj_name.strip()}: {bbox.strip()}") else: print("No objects detected") print("=" * 50) return response finally: # Cleanup try: socket.send_binary(json.dumps({"type": "session.destroy"}).encode()) socket.recv() except: pass socket.close() if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--api_key", required=True, help="Your Newton API key") parser.add_argument("--image_path", required=True, help="Path to image file") parser.add_argument("--mode", choices=["describe", "detect"], default="describe", help="Analysis mode: describe or detect objects") parser.add_argument("--focus", default="Describe what you see in detail", help="Focus question for description mode") parser.add_argument("--objects", nargs="+", default=["person", "car", "truck"], help="Objects to detect in detect mode") args = parser.parse_args() try: if args.mode == "describe": analyze_image_direct(args.api_key, args.image_path, args.focus) else: detect_objects_in_image(args.api_key, args.image_path, args.objects) except Exception as e: print(f"❌ Error: {e}") ``` ```bash Usage Examples theme={"system"} # Describe an image python direct_image_analysis.py \ --api_key=$ATAI_API_KEY \ --image_path=construction_site.jpg \ --mode=describe \ --focus="Describe the safety equipment visible" # Detect specific objects python direct_image_analysis.py \ --api_key=$ATAI_API_KEY \ --image_path=traffic_scene.jpg \ --mode=detect \ --objects person car truck bicycle ``` ## Repository and Additional Examples Complete example repository with more use cases Detailed WebSocket event documentation Upload files for CSV streaming Common issues and solutions ## Common Use Cases **Application**: Real-time security camera analysis **Setup**: RTSP camera stream with person/vehicle detection **Focus Examples**: * "Detect unauthorized personnel" * "Monitor for safety violations" * "Count people in restricted areas" **Application**: Manufacturing defect detection **Setup**: Direct image analysis of product photos **Focus Examples**: * "Identify product defects" * "Verify assembly completeness" * "Check packaging quality" **Application**: Climate and sensor data analysis **Setup**: CSV file streaming of sensor readings **Focus Examples**: * "Analyze temperature trends" * "Detect anomalous readings" * "Predict equipment failures" # Get Lens Info Source: https://docs.archetypeai.app/api-reference/lens/get-info GET /lens/info Retrieve high-level information about all lenses in your organization Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint returns summary information about all lenses available to your organization. ## Response Total number of lenses available to your organization Number of currently mounted (active) lenses Unix timestamp of the last update to lens information ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/lens/info \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.5/lens/info", headers={"Authorization": f"Bearer {api_key}"} ) print(response.json()) ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/info', { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const data = await response.json(); console.log(data); ``` ```json 200 - Success theme={"system"} { "num_lenses": 29, "num_mounted_lenses": 29, "last_updated": 1765201323.1954613 } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` # Get Lens Metadata Source: https://docs.archetypeai.app/api-reference/lens/get-metadata GET /lens/metadata Retrieve detailed metadata for all lenses available to your organization Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint returns detailed information about each lens available to your organization, including lens IDs, names, and configurations. ## Request Optional. Filter the response to a specific lens by ID. Optional. Shard index for pagination. Use `-1` to retrieve all lenses. Optional. Maximum items per shard. Use `-1` for no limit. ## Response Returns an array of lens objects, each containing: Unique identifier for the lens Human-readable name of the lens Current status of the lens (e.g., "LENS\_STATUS\_MOUNTED") Whether the lens can be modified or deleted Configuration object containing lens-specific settings and parameters ```bash cURL - All Lenses theme={"system"} curl https://api.u1.archetypeai.app/v0.5/lens/metadata \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Specific Lens theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/lens/metadata?lens_id=lns-test-lens-b2ba0058" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.5/lens/metadata", headers={"Authorization": f"Bearer {api_key}"} ) lenses = response.json() for lens in lenses: if lens: # Check for non-empty objects print(f"Lens: {lens.get('lens_name')} (ID: {lens.get('lens_id')})") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/metadata', { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const lenses = await response.json(); lenses.forEach(lens => { if (Object.keys(lens).length > 0) { console.log(`Lens: ${lens.lens_name} (ID: ${lens.lens_id})`); } }); ``` ```json 200 - Success theme={"system"} [ { "lens_id": "lns-test-lens-b2ba0058", "lens_name": "Test Lens", "lens_status": "LENS_STATUS_MOUNTED", "lens_modifiable": true, "lens_config": { "lens_name": "Test Lens" } }, { "lens_id": "lns-fd669361822b07e2-bc608aa3fdf8b4f9", "lens_name": "Activity Monitor", "lens_status": "LENS_STATUS_MOUNTED", "lens_modifiable": false, "lens_config": { "model_pipeline": [ { "processor_name": "lens_camera_processor", "processor_config": {} } ], "model_parameters": { "focus": "Describe the video.", "model_name": "Newton", "instruction": "Answer the following question about the video:", "max_replicas": 1, "min_replicas": 1, "model_version": "Newton::c2_3_7b_2508014e10af56", "max_new_tokens": 512, "camera_buffer_size": 5, "camera_buffer_step_size": 5 } } } ] ``` ```json 200 - Non-existent lens_id (empty object in array) theme={"system"} [ {} ] ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 422 - Invalid shard_index type theme={"system"} { "detail": [ { "type": "int_parsing", "loc": [ "query", "shard_index" ], "msg": "Input should be a valid integer, unable to parse string as an integer", "input": "abc" } ] } ``` # Get Sessions Info Source: https://docs.archetypeai.app/api-reference/lens/get-sessions-info GET /lens/sessions/info Get summary information about all lens sessions in your organization Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint returns high-level information about lens sessions across your organization, including counts of active and total sessions. ## Response Number of currently active (running) sessions Total number of sessions created (including destroyed ones) Unix timestamp of the last update to session information ```bash cURL theme={"system"} curl https://api.u1.archetypeai.app/v0.5/lens/sessions/info \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.5/lens/sessions/info", headers={"Authorization": f"Bearer {api_key}"} ) info = response.json() print(f"Active sessions: {info['num_active_sessions']}") print(f"Total sessions: {info['num_sessions']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/sessions/info', { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const info = await response.json(); console.log(`Active sessions: ${info.num_active_sessions}`); console.log(`Total sessions: ${info.num_sessions}`); ``` ```json 200 - Success theme={"system"} { "num_active_sessions": 0, "num_sessions": 0, "last_updated": 1765201367.1255276 } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` # Get Sessions Metadata Source: https://docs.archetypeai.app/api-reference/lens/get-sessions-metadata GET /lens/sessions/metadata Get detailed metadata for all active lens sessions Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint returns detailed information about each active lens session in your organization. ## Request Optional. Filter to a specific session by ID. Optional. Shard index for pagination. Use `-1` to retrieve all sessions. Optional. Maximum items per shard. Use `-1` for no limit. ## Response Returns an array of session objects, each containing: Unique identifier for the session The lens ID associated with this session Unix timestamp of the last activity on this session Current status of the session WebSocket endpoint for this session How long the session has been active in seconds Identifier of the backend runner hosting the session. Zero-based index of this session within the runner. ```bash cURL - All Sessions theme={"system"} curl https://api.u1.archetypeai.app/v0.5/lens/sessions/metadata \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash cURL - Specific Session theme={"system"} curl "https://api.u1.archetypeai.app/v0.5/lens/sessions/metadata?session_id=lsn-250313c2177253cbaa7a73542edd90" \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.get( "https://api.u1.archetypeai.app/v0.5/lens/sessions/metadata", headers={"Authorization": f"Bearer {api_key}"} ) sessions = response.json() if not sessions: print("No active sessions") else: for session in sessions: print(f"Session: {session['session_id']}") print(f" Status: {session['session_status']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/sessions/metadata', { headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}` } }); const sessions = await response.json(); if (sessions.length === 0) { console.log('No active sessions'); } else { sessions.forEach(session => { console.log(`Session: ${session.session_id}`); }); } ``` ```json 200 - Success (with sessions) theme={"system"} [ { "session_id": "lsn-250313c2177253cbaa7a73542edd90", "lens_id": "lns-fd669361822b07e2-237ab3ffd79199b1", "last_update_timestamp": 1741843135.1848276, "session_status": "SESSION_STATUS_RUNNING", "session_runner": "lens_service:runner:lens-node-worker-node-abc123", "session_endpoint": "wss://api.u1.archetypeai.app/v0.5/lens/sessions/lsn-250313c2177253cbaa7a73542edd90", "session_index": 0, "session_duration_sec": 2811.020206451416 } ] ``` ```json 200 - No active sessions theme={"system"} [] ``` ```json 200 - Non-existent session_id filter theme={"system"} [] ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 422 - Invalid shard_index type theme={"system"} { "detail": [ { "type": "int_parsing", "loc": [ "query", "shard_index" ], "msg": "Input should be a valid integer, unable to parse string as an integer", "input": "abc" } ] } ``` # Clone Lens Source: https://docs.archetypeai.app/api-reference/lens/lens-clone POST /lens/clone Creates a copy of a lens template Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint creates a copy of a lens template, registering the lens and returning the new lens\_id. Note that once a lens is cloned, any modifications to the original lens template will not be propagated to any cloned templates. ## Request The lens ID to clone. ## Response The ID of the new cloned lens. Name of the cloned lens. Status of the new lens. Whether the cloned lens can be modified. Configuration of the cloned lens, including `origin_lens_id` reference. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/lens/clone \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lens_id": "lns-test-lens-93812264" }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/clone", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "lens_id": "lns-test-lens-93812264" } ) data = response.json() # Check if clone was successful (should have lens_name) if data.get("lens_name"): print(f"Cloned lens ID: {data['lens_id']}") else: print("Clone may have failed - verify lens_id exists") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/clone', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ lens_id: 'lns-test-lens-93812264' }) }); const data = await response.json(); if (data.lens_name) { console.log(`Cloned lens ID: ${data.lens_id}`); } else { console.log('Clone may have failed - verify lens_id exists'); } ``` ```json 200 - Success theme={"system"} { "lens_id": "lns-test-lens-b2ba0058", "lens_name": "Test Lens", "lens_status": "LENS_STATUS_MOUNTED", "lens_modifiable": true, "lens_config": { "model_pipeline": [ { "processor_name": "lens_noop_processor", "processor_config": {} } ], "origin_lens_id": "lns-test-lens-c55bdf3b" } } ``` ```json 404 - Lens not found theme={"system"} { "errors": [ { "code": "lens_not_found", "message": "The specified lens was not found.", "suggestion": "Verify the lens identifier and ensure it exists before retrying.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 422 - Missing required field: lens_id theme={"system"} { "errors": [ { "code": "missing_lens_id", "message": "Missing required field: lens_id.", "suggestion": "Include the 'lens_id' field in the request payload.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` # Delete Lens Source: https://docs.archetypeai.app/api-reference/lens/lens-delete POST /lens/delete Deletes a lens template Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint deletes a lens template, removing it from the list of available lens templates. Note that deleting the lens template does not stop or delete any active lens sessions based on the template. ## Request The unique lens ID to delete. This is returned when the lens template is created. ## Response Whether the deletion was successful. Check this field to detect errors. The ID of the lens that was deleted (or attempted to delete). Array of error messages if the deletion failed. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/lens/delete \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lens_id": "lns-test-lens-85c01267" }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/delete", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "lens_id": "lns-test-lens-85c01267" } ) result = response.json() if result.get("is_valid") == False: print(f"Error deleting lens: {result['errors']}") else: print(f"Lens deleted: {result['lens_id']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/delete', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ lens_id: 'lns-test-lens-85c01267' }) }); const result = await response.json(); if (result.is_valid === false) { console.error('Error:', result.errors); } else { console.log(`Lens deleted: ${result.lens_id}`); } ``` ```json 200 - Success theme={"system"} { "is_valid": true, "lens_id": "lns-test-lens-85c01267", "errors": [] } ``` ```json 404 - Lens not found theme={"system"} { "errors": [ { "code": "lens_not_found", "message": "The specified lens was not found.", "suggestion": "Verify the lens identifier and ensure it exists before retrying.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 403 - Lens is non-modifiable theme={"system"} { "errors": [ { "code": "lens_not_modifiable", "message": "The specified lens is non-modifiable.", "suggestion": "Check whether the lens is modifiable before attempting modifications.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 500 - Missing lens_id field theme={"system"} Internal Server Error ``` # Modify Lens Source: https://docs.archetypeai.app/api-reference/lens/lens-modify POST /lens/modify Modifies an existing lens template Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint modifies an existing lens template, overwriting any previous settings of that template. Only lens templates that are modifiable can be modified. Developers can check if a lens template is modifiable via the `/lens/metadata` API (look for `lens_modifiable: true`). ## Request Body The ID of the lens to modify (must be a modifiable lens) Updated name for the lens Updated configuration for the lens Updated model pipeline configuration Updated model parameters ## Response ID of the modified lens Updated name of the lens Whether the lens can be further modified Current status of the lens Updated lens configuration ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/lens/modify \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lens_id": "lns-test-lens-b2ba0058", "lens_name": "Updated Lens Name" }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/modify", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "lens_id": "lns-test-lens-b2ba0058", "lens_name": "Updated Lens Name" } ) result = response.json() if result.get("lens_name"): print(f"Lens modified: {result['lens_id']}") else: print("Modification may have failed") ``` ```javascript JavaScript theme={"system"} const response = await fetch( "https://api.u1.archetypeai.app/v0.5/lens/modify", { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ lens_id: "lns-test-lens-b2ba0058", lens_name: "Updated Lens Name", }), } ); const result = await response.json(); if (result.lens_name) { console.log(`Lens modified: ${result.lens_id}`); } else { console.log("Modification may have failed"); } ``` ```json 200 - OK theme={"system"} { "lens_id": "lns-test-lens-b2ba0058", "lens_name": "Updated Lens Name", "lens_status": "LENS_STATUS_MOUNTED", "lens_modifiable": true, "lens_config": { "model_pipeline": [ { "processor_name": "lens_noop_processor", "processor_config": {} } ] } } ``` ```json 422 - Missing required field: lens_id theme={"system"} { "errors": [ { "code": "missing_lens_id", "message": "Missing required field: lens_id.", "suggestion": "Include the 'lens_id' field in the request payload.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 404 - Lens not found theme={"system"} { "errors": [ { "code": "lens_not_found", "message": "The specified lens was not found.", "suggestion": "Verify the lens identifier and ensure it exists before retrying.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 403 - Lens is non-modifiable theme={"system"} { "errors": [ { "code": "lens_not_modifiable", "message": "The specified lens is non-modifiable.", "suggestion": "Check whether the lens is modifiable before attempting modifications.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` # Register Lens Source: https://docs.archetypeai.app/api-reference/lens/lens-register POST /lens/register Register a new lens configuration that can be used to create sessions Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview Register a new lens by providing a configuration. The lens can be a minimal registration (just a name) or a full production lens with model pipeline and parameters. ## Request Body Configuration object for the lens Name for the lens Array of processor configurations for the lens Parameters for the model configuration ## Response Unique identifier for the registered lens (format: "lns-...") Name of the registered lens Whether the lens can be modified or deleted Current status of the lens ("LENS\_STATUS\_MOUNTED" or "LENS\_STATUS\_REGISTERED") If `false`, indicates an error occurred. Check `error_messages` for details. Array of error messages if registration failed ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/lens/register \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "lens_config": { "lens_name": "My Test Lens" } }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/register", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "lens_config": { "lens_name": "My Test Lens" } } ) data = response.json() if data.get("is_valid") == False: print(f"Error: {data.get('error_messages')}") else: print(f"Lens ID: {data['lens_id']}") ``` ```javascript JavaScript theme={"system"} const response = await fetch( "https://api.u1.archetypeai.app/v0.5/lens/register", { method: "POST", headers: { Authorization: `Bearer ${process.env.ATAI_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ lens_config: { lens_name: "My Test Lens", }, }), } ); const data = await response.json(); if (data.is_valid === false) { console.error("Error:", data.error_messages); } else { console.log(`Lens ID: ${data.lens_id}`); } ``` ```json 200 - OK theme={"system"} { "lens_id": "lns-test-lens-176520-e7885b3f", "lens_name": "My Test Lens", "lens_status": "LENS_STATUS_MOUNTED", "lens_modifiable": true, "lens_config": { "model_pipeline": [ { "processor_name": "lens_noop_processor", "processor_config": {} } ] } } ``` ```json 422 - Invalid JSON payload theme={"system"} { "errors": [ { "code": "invalid_json_payload", "message": "Invalid JSON payload.", "suggestion": "Ensure the request body contains valid JSON and is properly formatted.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 422 - Missing required field: lens_name theme={"system"} { "errors": [ { "code": "missing_lens_name", "message": "Missing required field: lens_name.", "suggestion": "Include the 'lens_name' field in the request payload.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` # Session Events Process Source: https://docs.archetypeai.app/api-reference/lens/sessions-events-process POST /lens/sessions/events/process Sends an event to an active session to process Requires [version 1.1.5](/release-notes/1.1.x#v1-1-5) or later of the Archetype platform. ## Overview This endpoint sends an event to an active session to process. ## Request The ID of the active session the event should be routed to. The event to route to the session. Must contain a `type` field. ## Response Response type. "error" indicates a processing error occurred. Event processing result or error details. ```bash cURL theme={"system"} curl -X POST https://api.u1.archetypeai.app/v0.5/lens/sessions/events/process \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "session_id": "lsn-250313c2177253cbaa7a73542edd90", "event": { "type": "image", "data": "base64_encoded_image_data" } }' ``` ```python Python theme={"system"} import requests import os api_key = os.environ.get("ATAI_API_KEY") response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/events/process", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" }, json={ "session_id": "lsn-250313c2177253cbaa7a73542edd90", "event": { "type": "image", "data": "base64_encoded_image_data" } } ) result = response.json() if result.get("type") == "error": print(f"Error: {result['event_data']['error_messages']}") elif not result: print("Empty response - check session_id and event parameters") else: print(f"Success: {result}") ``` ```javascript JavaScript theme={"system"} const response = await fetch('https://api.u1.archetypeai.app/v0.5/lens/sessions/events/process', { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.ATAI_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ session_id: 'lsn-250313c2177253cbaa7a73542edd90', event: { type: 'image', data: 'base64_encoded_image_data' } }) }); const result = await response.json(); if (result.type === 'error') { console.error('Error:', result.event_data.error_messages); } else if (Object.keys(result).length === 0) { console.log('Empty response - check session_id and event parameters'); } else { console.log('Success:', result); } ``` ```json 200 - Success theme={"system"} { "type": "success", "event_data": { "response": "Processing result..." } } ``` ```json 200 - Error: Unknown event type theme={"system"} { "type": "error", "event_data": { "is_valid": false, "error_messages": [ "Unknown event type: test" ] } } ``` ```json 200 - Error: Empty event payload theme={"system"} { "type": "error", "event_data": { "is_valid": false, "error_messages": [ "Event payload is empty!" ] } } ``` ```json 400 - Missing session_id theme={"system"} { "detail": "error" } ``` ```json 401 - Unauthorized theme={"system"} { "errors": [ { "code": "unauthorized_request", "message": "Unauthorized or invalid access.", "suggestion": "Provide valid authentication credentials and ensure they have the required permissions.", "error_uid": "err-xxxxxxxx" } ] } ``` ```json 500 - Invalid event format (non-object) theme={"system"} Internal Server Error ``` # Lens Events API (WebSocket) Source: https://docs.archetypeai.app/api-reference/lens/websocket-events Real-time control and data streaming for lens sessions via WebSocket The Lens Events API enables real-time control and data streaming for active lens sessions via WebSocket connections. This allows you to interact with Newton models, configure input streams, and receive real-time inference results. ## Connection Setup ### 1. Create a Lens Session First, create a lens session using the REST API: ```bash theme={"system"} curl https://api.u1.archetypeai.app/v0.5/lens/sessions/create \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"lens_id": "lns-fd669361822b07e2-bc608aa3fdf8b4f9"}' ``` The response includes a `session_endpoint` for WebSocket connection (see [Create Lens Session](/api-reference/lens/create-session) for the full response shape): ```json theme={"system"} { "session_id": "lsn-250313c2177253cbaa7a73542edd90", "lens_id": "lns-fd669361822b07e2-bc608aa3fdf8b4f9", "session_endpoint": "wss://api.u1.archetypeai.app/v0.5/lens/sessions/lsn-250313c2177253cbaa7a73542edd90", "session_status": "LensSessionStatus.SESSION_STATUS_REGISTERED" } ``` ### 2. Connect to WebSocket ```python Python theme={"system"} import websocket import json session_endpoint = "wss://api.u1.archetypeai.app/v0.5/lens/sessions/lsn-250313c2177253cbaa7a73542edd90" socket = websocket.create_connection( session_endpoint, header={"Authorization": f"Bearer {API_KEY}"} ) def send_and_receive_event(socket, event_data): socket.send_binary(json.dumps(event_data).encode()) response = json.loads(socket.recv()) return response ``` ```javascript JavaScript theme={"system"} const WebSocket = require("ws"); const socket = new WebSocket(session_endpoint, [ "authenticationauthorization.bearer." + API_KEY, "event-protocol-v1" ]); function sendAndReceiveEvent(socket, eventData) { return new Promise((resolve, reject) => { socket.send(JSON.stringify(eventData)); socket.once('message', (data) => { resolve(JSON.parse(data)); }); socket.once('error', reject); }); } ``` For JavaScript, use the `Sec-WebSocket-Protocol` header to pass authentication and protocol version. ## Event Message Format All event messages are JSON objects with a required `type` field and optional `event_data` field: ```json theme={"system"} { "type": "event.type", "event_data": { // Event-specific data } } ``` **Response envelope:** with the single exception of `session.status` (see below), every server response carries a `type` field suffixed with `.response` and wraps the result in `event_data`: ```json theme={"system"} { "type": "event.type.response", "event_data": { "is_valid": true, "error_messages": [] } } ``` When `event_data` would be empty, it is returned as `null`. ## Session Events ### session.status Query the current status of the active session. ```python Python theme={"system"} event_message = {"type": "session.status"} response = send_and_receive_event(socket, event_message) print(f"Session status: {response}") ``` ```javascript JavaScript theme={"system"} const eventMessage = {"type": "session.status"}; const response = await sendAndReceiveEvent(socket, eventMessage); console.log(`Session status: ${JSON.stringify(response)}`); ``` **Response Example:** Unlike other events, `session.status` returns the full session metadata record (the same shape as [Create Lens Session](/api-reference/lens/create-session)), not the `{type, event_data}` envelope. The response currently includes an `api_key` field that echoes back the caller's real API key. Treat this field as a secret — do not log, persist, or expose it in client-side code. (Server-side scrub in progress.) ```json theme={"system"} { "session_id": "lsn-250313c2177253cbaa7a73542edd90", "lens_id": "lns-fd669361822b07e2-bc608aa3fdf8b4f9", "lens_name": "Activity Monitor", "session_status": "LensSessionStatus.SESSION_STATUS_RUNNING", "session_endpoint": "wss://api.u1.archetypeai.app/v0.5/lens/sessions/lsn-250313c2177253cbaa7a73542edd90", "session_ttl_sec": 86400, "registration_timestamp": 1779430869.7525718, "last_event_timestamp": 1779430869.7525718, "last_update_timestamp": 1779430869.9271567, "session_start_timestamp": 1779430869.8115742, "session_destroyed_timestamp": null, "num_active_connections": 0, "num_updates": 1, "num_inputs": 0, "num_outputs": 0, "num_events": 0, "input_data_stream_id": null, "output_data_stream_id": null, "lens_config": { /* full lens configuration */ } } ``` ### session.validate Run validation checks on the current session, including health checks and model connectivity. ```python Python theme={"system"} event_message = {"type": "session.validate"} response = send_and_receive_event(socket, event_message) if response.get("event_data", {}).get("is_valid"): print("Session is valid and ready") else: print(f"Validation failed: {response.get('event_data', {}).get('error_messages')}") ``` ```javascript JavaScript theme={"system"} const eventMessage = {"type": "session.validate"}; const response = await sendAndReceiveEvent(socket, eventMessage); if (response.event_data?.is_valid) { console.log("Session is valid and ready"); } else { console.log(`Validation failed: ${response.event_data?.error_messages}`); } ``` **Response Example:** ```json theme={"system"} { "type": "session.validate.response", "event_data": { "is_valid": true, "error_messages": [] } } ``` ### session.read Read pending event messages from the platform, such as log messages or asynchronous inference results. `session.read` only returns messages for lenses whose `model_pipeline` writes to the WebSocket mailbox. Lenses that use a `server_sent_events_writer` output processor (Activity Monitor and most cookbook lenses) route inference results to the [SSE consumer endpoint](/api-reference/lens/consumer) instead — for those, `session.read` returns `event_data: null` even when [`GET /lens/sessions/metadata`](/api-reference/lens/get-sessions-metadata) shows non-zero `num_outputs`. Inspect the lens's `model_pipeline` via [`GET /lens/metadata`](/api-reference/lens/get-metadata) to confirm which output channel it uses. Each client should generate a unique `client_id` to enable parallel reading. Use a new `client_id` to reset message stream playback. ```python Python theme={"system"} import uuid client_id = str(uuid.uuid4())[:8] # Generate unique 8-character ID event_message = { "type": "session.read", "event_data": {"client_id": client_id} } response = send_and_receive_event(socket, event_message) messages = (response.get("event_data") or {}).get("messages", []) for message in messages: print(f"[{message['timestamp']}] {message['type']}: {message['data']}") ``` ```javascript JavaScript theme={"system"} const clientId = Math.random().toString(16).substr(2, 8); const eventMessage = { "type": "session.read", "event_data": {"client_id": clientId} }; const response = await sendAndReceiveEvent(socket, eventMessage); (response.event_data?.messages ?? []).forEach(message => { console.log(`[${message.timestamp}] ${message.type}: ${message.data}`); }); ``` **Response Example (no pending messages):** ```json theme={"system"} { "type": "session.read.response", "event_data": null } ``` **Response Example (with pending messages):** ```json theme={"system"} { "type": "session.read.response", "event_data": { "messages": [ { "timestamp": 1741843200.123, "type": "inference.result", "data": { "result": "A construction worker wearing a hard hat and safety vest" } }, { "timestamp": 1741843201.456, "type": "log.info", "data": "Frame processed successfully" } ], "client_id": "a1b2c3d4" } } ``` ### session.destroy Destroy the active session directly via the control stream. ```python Python theme={"system"} event_message = {"type": "session.destroy"} response = send_and_receive_event(socket, event_message) print(f"Session destroyed: {response}") # Close WebSocket connection socket.close() ``` ```javascript JavaScript theme={"system"} const eventMessage = {"type": "session.destroy"}; const response = await sendAndReceiveEvent(socket, eventMessage); console.log(`Session destroyed: ${JSON.stringify(response)}`); // Close WebSocket connection socket.close(); ``` ## Input Stream Configuration ### input\_stream.set Configure input data streams to automatically feed data through the lens. #### RTSP Video Stream Connect a real-time video camera using RTSP protocol: ```python Python theme={"system"} event_message = { "type": "input_stream.set", "event_data": { "stream_type": "rtsp_video_streamer", "stream_config": { "rtsp_url": "rtsp://camera.example.com:554/stream", "target_image_size": [360, 640], "target_frame_rate_hz": 0.2 } } } response = send_and_receive_event(socket, event_message) print(f"RTSP stream configured: {response}") ``` ```javascript JavaScript theme={"system"} const eventMessage = { "type": "input_stream.set", "event_data": { "stream_type": "rtsp_video_streamer", "stream_config": { "rtsp_url": "rtsp://camera.example.com:554/stream", "target_image_size": [360, 640], "target_frame_rate_hz": 0.2 } } }; const response = await sendAndReceiveEvent(socket, eventMessage); console.log(`RTSP stream configured: ${JSON.stringify(response)}`); ``` #### CSV File Reader Connect a CSV file for data streaming: ```python Python theme={"system"} event_message = { "type": "input_stream.set", "event_data": { "stream_type": "csv_file_reader", "stream_config": { "file_id": "jena_climate_2009_2016.csv" } } } response = send_and_receive_event(socket, event_message) print(f"CSV stream configured: {response}") ``` ```javascript JavaScript theme={"system"} const eventMessage = { "type": "input_stream.set", "event_data": { "stream_type": "csv_file_reader", "stream_config": { "file_id": "jena_climate_2009_2016.csv" } } }; const response = await sendAndReceiveEvent(socket, eventMessage); ``` ### Available Input Stream Types **Description**: Real-time video streaming from RTSP cameras **Configuration Parameters**: * `rtsp_url` (string): RTSP stream URL * `target_image_size` (array): \[height, width] in pixels * `target_frame_rate_hz` (float): Frames per second to process **Use Cases**: Security cameras, live monitoring, real-time analysis **Description**: Stream data from uploaded CSV files **Configuration Parameters**: * `file_id` (string): ID of uploaded CSV file **Use Cases**: Time series analysis, batch data processing, historical data analysis **Description**: Stream a pre-recorded video file (e.g. `.mp4`) that was previously uploaded via the [Files API](/api-reference/files/upload) **Configuration Parameters**: * `file_id` (string): `file_id` returned by the upload — typically the original filename (e.g. `"my_video.mp4"`), **not** the `file_uid` UUID **Use Cases**: Offline analysis of recorded footage, replaying dashcam / camera archives through a vision lens See [Video File Reader](/core-concepts/streams/data-connectors/readers/video-reader) for the full data-connector reference. **Description**: Direct sensor data streaming **Configuration Parameters**: * Configuration varies by sensor type **Use Cases**: IoT sensors, accelerometers, temperature sensors ## Direct Model Queries ### model.query Send direct queries to Newton models with custom data payloads. `model.query` is only handled by lenses whose pipeline includes a model-query processor. Lenses that wrap a streaming processor (e.g. `lens_camera_processor`, `lens_timeseries_state_processor`) expect input via `input_stream.set` and will time out on `model.query`. Responses arrive asynchronously — long-running queries return a timeout response with `message: "Response timed out for query"` if the model has not replied within the WebSocket read window. #### Image QA Example ```python Python theme={"system"} import base64 # Load and encode image with open("construction_site.jpg", "rb") as img_handle: base64_img = base64.b64encode(img_handle.read()).decode("utf-8") event_message = { "type": "model.query", "event_data": { "model_version": "Newton::c2_4_7b_251215a172f6d7", "template_name": "image_qa_template_task", "instruction": "Answer the following question about the image:", "focus": "Describe the safety equipment visible in the image.", "max_new_tokens": 512, "data": [{ "type": "base64_img", "base64_img": base64_img }], "sensor_metadata": {} } } response = send_and_receive_event(socket, event_message) print(f"Newton response: {response.get('event_data', {}).get('result')}") ``` ```javascript JavaScript theme={"system"} const fs = require('fs'); // Load and encode image const imageBuffer = fs.readFileSync('construction_site.jpg'); const base64Img = imageBuffer.toString('base64'); const eventMessage = { "type": "model.query", "event_data": { "model_version": "Newton::c2_4_7b_251215a172f6d7", "template_name": "image_qa_template_task", "instruction": "Answer the following question about the image:", "focus": "Describe the safety equipment visible in the image.", "max_new_tokens": 512, "data": [{ "type": "base64_img", "base64_img": base64Img }], "sensor_metadata": {} } }; const response = await sendAndReceiveEvent(socket, eventMessage); console.log(`Newton response: ${response.event_data?.result}`); ``` #### Object Detection Example ```python Python theme={"system"} event_message = { "type": "model.query", "event_data": { "model_version": "Newton::c2_4_7b_251215a172f6d7", "template_name": "image_bbox_template_task", "instruction": "Localize all objects in the picture and build bounding box around them.", "focus": "Input: [person,car,hard_hat,safety_vest]", "max_new_tokens": 512, "data": [{ "type": "base64_img", "base64_img": base64_img }], "sensor_metadata": {} } } response = send_and_receive_event(socket, event_message) print(f"Detected objects: {response.get('event_data', {}).get('result')}") ``` ```javascript JavaScript theme={"system"} const eventMessage = { "type": "model.query", "event_data": { "model_version": "Newton::c2_4_7b_251215a172f6d7", "template_name": "image_bbox_template_task", "instruction": "Localize all objects in the picture and build bounding box around them.", "focus": "Input: [person,car,hard_hat,safety_vest]", "max_new_tokens": 512, "data": [{ "type": "base64_img", "base64_img": base64Img }], "sensor_metadata": {} } }; const response = await sendAndReceiveEvent(socket, eventMessage); console.log(`Detected objects: ${response.event_data?.result}`); ``` ## Newton Model Templates ### Available Templates **Template Name**: `image_qa_template_task` **Purpose**: Generate narrative descriptions of images **Parameters**: * `instruction`: Question or instruction for the model * `focus`: Specific aspect to focus on (e.g., "safety equipment", "project status") * `max_new_tokens`: Maximum response length (typically 512) **Output**: Natural language description, wrapped in the WS response envelope. **Example Response**: ```json theme={"system"} { "type": "model.query.response", "event_data": { "result": "The image shows construction workers wearing yellow hard hats and high-visibility safety vests." } } ``` **Timeout Response** (model did not reply within the read window): ```json theme={"system"} { "type": "model.query.response", "message": "Response timed out for query" } ``` **Template Name**: `image_bbox_template_task` **Purpose**: Detect and localize objects with bounding boxes **Parameters**: * `instruction`: Object detection instruction * `focus`: List of objects to detect (e.g., "Input: \[person,car,dog]") * `max_new_tokens`: Maximum response length **Output**: Structured bounding box coordinates, wrapped in the WS response envelope. **Example Response**: ```json theme={"system"} { "type": "model.query.response", "event_data": { "result": "person: [0.15, 0.20, 0.45, 0.80]\nhard_hat: [0.25, 0.15, 0.35, 0.25]\nsafety_vest: [0.20, 0.35, 0.40, 0.65]" } } ``` ## Error Handling Handle WebSocket errors and connection issues: ```python Python theme={"system"} import websocket import json import time def robust_websocket_connection(session_endpoint, api_key): max_retries = 3 retry_count = 0 while retry_count < max_retries: try: socket = websocket.create_connection( session_endpoint, header={"Authorization": f"Bearer {api_key}"}, timeout=30 ) return socket except Exception as e: retry_count += 1 print(f"Connection attempt {retry_count} failed: {e}") if retry_count < max_retries: time.sleep(2 ** retry_count) # Exponential backoff else: raise e def safe_send_and_receive(socket, event_data, timeout=30): try: socket.settimeout(timeout) socket.send_binary(json.dumps(event_data).encode()) response = json.loads(socket.recv()) return response except websocket.WebSocketTimeoutException: raise Exception("WebSocket timeout - no response received") except websocket.WebSocketConnectionClosedException: raise Exception("WebSocket connection closed unexpectedly") ``` ```javascript JavaScript theme={"system"} const WebSocket = require('ws'); function createRobustWebSocketConnection(sessionEndpoint, apiKey) { return new Promise((resolve, reject) => { const socket = new WebSocket(sessionEndpoint, [ "authenticationauthorization.bearer." + apiKey, "event-protocol-v1" ]); const timeout = setTimeout(() => { socket.terminate(); reject(new Error('WebSocket connection timeout')); }, 30000); socket.on('open', () => { clearTimeout(timeout); resolve(socket); }); socket.on('error', (error) => { clearTimeout(timeout); reject(error); }); }); } function safeSendAndReceive(socket, eventData, timeoutMs = 30000) { return new Promise((resolve, reject) => { const timeout = setTimeout(() => { reject(new Error('Request timeout')); }, timeoutMs); socket.once('message', (data) => { clearTimeout(timeout); try { resolve(JSON.parse(data)); } catch (e) { reject(new Error('Invalid JSON response')); } }); socket.once('error', (error) => { clearTimeout(timeout); reject(error); }); socket.send(JSON.stringify(eventData)); }); } ``` ## Best Practices * Always authenticate WebSocket connections with your API key * Implement connection retry logic with exponential backoff * Set appropriate timeouts for requests (30 seconds recommended) * Close connections properly to free resources * Use unique `client_id` for each client to enable parallel processing * Handle asynchronous events properly with `session.read` * Implement error handling for malformed responses * Log events for debugging and monitoring * Use appropriate image sizes for video streams (360x640 recommended) * Set reasonable frame rates (0.2 Hz for most use cases) * Monitor processing times and adjust accordingly * Batch similar queries when possible ## Next Steps Explore complete working examples Monitor and manage active sessions Upload files for CSV streaming Solve common WebSocket issues # Direct Query Source: https://docs.archetypeai.app/api-reference/query POST /query Run a natural-language query against a model, optionally grounded in uploaded files or inline data events This API endpoint is under active development and is subject to change. ## 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, and (on C 2.6 fusion checkpoints) video understanding. Used in `archetypeai-swat-demo-direct-query`, `archetypeai-earthquake-demo`, `archetypeai-grid-demo`. For video, use a C 2.6 Fusion checkpoint such as `Newton::c2_6_8b_fp8_260424d7a55d5e` — see the [atai-newton-fusion-model skill](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-fusion-model). * **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 [atai-newton-omega-model skill](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-model). The exact model identifiers available to your organization may differ — invalid values return `400 invalid_model_version`. ## Request Versioned model identifier such as `Newton::c2_5_8b_260413b723a9ab` (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. 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. Optional system prompt prepended to the query. Optional instruction prompt appended to the system prompt. Optional prefix used to seed the model's response. Optional named prompt template to apply server-side. 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` requires a C 2.6 fusion checkpoint such as `Newton::c2_6_8b_fp8_260424d7a55d5e` — older C 2.4/2.5 text checkpoints do not process video frames. The clip is decoded and uniformly sampled server-side (control this with `max_frames`); see the [atai-newton-fusion-model skill](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-fusion-model) for the full video patterns. 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`). Maximum tokens to generate in the response. Maximum video frames to sample when an `.mp4` file is supplied via `file_ids`. The platform maximum is 64 — values above 64 fail silently: the request returns 200 but the video is dropped and the model answers from priors. Video requires a C 2.6 fusion checkpoint (see [Overview](#overview)). Sampling temperature. Omit to use the model default. Whether to use sampling instead of greedy decoding. Penalty for repeating tokens already produced. Nucleus sampling cutoff. Top-k sampling cutoff. Penalty for tokens already present in the prompt. 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. When true, treat multiple `file_id`s / image events as a single multi-image input rather than independent inputs. 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. Free-form metadata stored alongside the query for the caller's own bookkeeping. Override the maximum combined prompt size in MB. Defaults to the server's `MAX_QUERY_SIZE_MB` setting (typically 0.04 MB). Override the maximum time to wait for a synchronous result before returning a `504`. 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. ## Response Server-generated identifier for this query. Include it when reporting issues to support so the platform team can correlate to server logs. Terminal status — `completed` for successful queries, `failed` if the worker returned an error. 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. Unix timestamp when the query was submitted. Unix timestamp when data loading began. Unix timestamp when inference began. Unix timestamp when the response was finalized. Seconds spent in the queue before processing began. Seconds spent on inference. End-to-end latency from submission to response. Identifier of the GPQ worker node that processed the query. 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. Single error string set by GPQ only when `status` is `failed`. 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. ```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_5_8b_260413b723a9ab", "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_5_8b_260413b723a9ab", "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_5_8b_260413b723a9ab", "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_5_8b_260413b723a9ab", "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_5_8b_260413b723a9ab', 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); } ``` ```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" } ] } ``` # Quick Reference Source: https://docs.archetypeai.app/api-reference/quick-reference Essential API commands and patterns for quick reference. ## Authentication ```bash theme={"system"} # Set your API key export ATAI_API_KEY="your-api-key-here" # Basic API call curl https://api.u1.archetypeai.app/v0.5/lens/info \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ## Common Patterns ### Create and Use a Session ```python Python theme={"system"} import requests # 1. Create session response = requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/create", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={"lens_id": "lns-fd669361822b07e2-237ab3ffd79199b0"} ) session = response.json() # 2. Use WebSocket endpoint for data streaming # session['session_endpoint'] contains WebSocket URL # 3. Destroy session when done requests.post( "https://api.u1.archetypeai.app/v0.5/lens/sessions/destroy", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={"session_id": session['session_id']} ) ``` ```bash cURL theme={"system"} # 1. Create session SESSION_ID=$(curl -s https://api.u1.archetypeai.app/v0.5/lens/sessions/create \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d '{"lens_id": "lns-fd669361822b07e2-237ab3ffd79199b0"}' \ | jq -r '.session_id') # 2. Destroy session curl https://api.u1.archetypeai.app/v0.5/lens/sessions/destroy \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"session_id\": \"$SESSION_ID\"}" ``` ### Upload and Process Files ```python Python theme={"system"} import requests # Upload file with open('image.png', 'rb') as f: response = requests.post( 'https://api.u1.archetypeai.app/v0.5/files', headers={'Authorization': 'Bearer YOUR_API_KEY'}, files={'file': f} ) file_data = response.json() print(f"Uploaded: {file_data['file_id']}") # List files response = requests.get( "https://api.u1.archetypeai.app/v0.5/files/metadata", headers={"Authorization": "Bearer YOUR_API_KEY"} ) files = response.json()["data"] for file in files: print(f"- {file['file_id']} ({file['num_bytes']} bytes)") ``` ```bash cURL theme={"system"} # Upload file curl -X POST https://api.u1.archetypeai.app/v0.5/files \ -H "Authorization: Bearer $ATAI_API_KEY" \ -F "file=@image.jpg" # List files curl https://api.u1.archetypeai.app/v0.5/files/metadata \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ## API Endpoints Summary ### Agents API | Method | Endpoint | Description | | - | - | - | | **Blueprints** | | | | `POST` | `/agents/blueprints` | [Create Blueprint](/api-reference/agents/blueprints/create-blueprint) | | `GET` | `/agents/blueprints` | [List Blueprints](/api-reference/agents/blueprints/list-blueprints) | | `GET` | `/agents/blueprints/{reference}` | [Get Blueprint](/api-reference/agents/blueprints/get-blueprint) | | `DELETE` | `/agents/blueprints/{reference}` | [Delete Blueprint](/api-reference/agents/blueprints/delete-blueprint) | | `GET` | `/agents/blueprints/{reference}/versions` | [List Blueprint Versions](/api-reference/agents/blueprints/list-blueprint-versions) | | **Bundles** | | | | `POST` | `/agents/bundles` | [Create Bundle](/api-reference/agents/bundles/create-bundle) | | `GET` | `/agents/bundles` | [List Bundles](/api-reference/agents/bundles/list-bundles) | | `GET` | `/agents/bundles/{bundle_id}` | [Get Bundle](/api-reference/agents/bundles/get-bundle) | | `DELETE` | `/agents/bundles/{bundle_id}` | [Delete Bundle](/api-reference/agents/bundles/delete-bundle) | | `POST` | `/agents/bundles/{bundle_id}/run` | [Run Bundle](/api-reference/agents/bundles/run-bundle) | | **Evals** | | | | `POST` | `/agents/evals` | [Create Eval](/api-reference/agents/evals/create-eval) | | `GET` | `/agents/evals` | [List Evals](/api-reference/agents/evals/list-evals) | | `GET` | `/agents/evals/{eval_id}` | [Get Eval](/api-reference/agents/evals/get-eval) | | `DELETE` | `/agents/evals/{eval_id}` | [Delete Eval](/api-reference/agents/evals/delete-eval) | | `POST` | `/agents/evals/{eval_id}/cancel` | [Cancel Eval](/api-reference/agents/evals/cancel-eval) | | `GET` | `/agents/evals/{eval_id}/examples` | [List Eval Examples](/api-reference/agents/evals/list-eval-examples) | | **Instances** | | | | `GET` | `/agents/instances` | [List Agents](/api-reference/agents/instances/list-agents) | | `GET` | `/agents/instances/{agent_id}` | [Get Agent](/api-reference/agents/instances/get-agent) | | `DELETE` | `/agents/instances/{agent_id}` | [Delete Agent](/api-reference/agents/instances/delete-agent) | | `POST` | `/agents/instances/{agent_id}/pause` | [Pause Agent](/api-reference/agents/instances/pause-agent) | | `POST` | `/agents/instances/{agent_id}/resume` | [Resume Agent](/api-reference/agents/instances/resume-agent) | | `POST` | `/agents/instances/{agent_id}/cancel` | [Cancel Agent](/api-reference/agents/instances/cancel-agent) | | `GET` | `/agents/instances/{agent_id}/events` | [List Agent Events](/api-reference/agents/instances/list-agent-events) | | `GET` | `/agents/instances/{agent_id}/logs` | [Get Agent Logs](/api-reference/agents/instances/get-agent-logs) | | `GET` | `/agents/instances/{agent_id}/results` | [Get Agent Results](/api-reference/agents/instances/get-agent-results) | | `POST` | `/agents/instances/{agent_id}/query` | [Query Agent](/api-reference/agents/instances/query-agent) | | **Nodes** | | | | `GET` | `/agents/nodes/registry` | [List Node Registry](/api-reference/agents/nodes/list-node-registry) | | **Optimizations** | | | | `POST` | `/agents/optimizations` | [Create Optimization](/api-reference/agents/optimizations/create-optimization) | | `GET` | `/agents/optimizations` | [List Optimizations](/api-reference/agents/optimizations/list-optimizations) | | `GET` | `/agents/optimizations/{optimization_id}` | [Get Optimization](/api-reference/agents/optimizations/get-optimization) | | `DELETE` | `/agents/optimizations/{optimization_id}` | [Delete Optimization](/api-reference/agents/optimizations/delete-optimization) | | `POST` | `/agents/optimizations/{optimization_id}/cancel` | [Cancel Optimization](/api-reference/agents/optimizations/cancel-optimization) | | `GET` | `/agents/optimizations/{optimization_id}/trials` | [List Optimization Trials](/api-reference/agents/optimizations/list-optimization-trials) | | `POST` | `/agents/optimizations/{optimization_id}/trials/{trial_id}/promote` | [Promote Trial](/api-reference/agents/optimizations/promote-trial) | ### Batch Processing API | Method | Endpoint | Description | | - | - | - | | **Jobs** | | | | `POST` | `/batch/jobs` | [Create job](/api-reference/batch/jobs/create-job) | | `GET` | `/batch/jobs` | [List jobs](/api-reference/batch/jobs/list-jobs) | | `GET` | `/batch/jobs/{id}` | [Get job info](/api-reference/batch/jobs/get-job) | | `POST` | `/batch/jobs/{id}/retry` | [Retry job](/api-reference/batch/jobs/retry-job) | | `DELETE` | `/batch/jobs/{id}` | [Delete job](/api-reference/batch/jobs/delete-job) | | `POST` | `/batch/jobs/{id}/cancel` | [Cancel job](/api-reference/batch/jobs/cancel-job) | | `GET` | `/batch/jobs/queue` | [Get global queue depths grouped by pipeline type](/api-reference/batch/jobs/get-queue-depths) | | **Events** | | | | `GET` | `/batch/jobs/{id}/events` | [List job events](/api-reference/batch/events/list-job-events) | | **I/O** | | | | `GET` | `/batch/jobs/{id}/inputs` | [List job inputs](/api-reference/batch/io/list-inputs) | | `GET` | `/batch/jobs/{id}/outputs` | [List job outputs](/api-reference/batch/io/list-outputs) | | **Progress** | | | | `GET` | `/batch/jobs/{id}/progress` | [List job progress](/api-reference/batch/progress/list-job-progress) | | **Registry: Pipelines** | | | | `GET` | `/batch/registry/pipelines` | [List pipelines](/api-reference/batch/registry/pipelines/list-pipelines) | | `GET` | `/batch/registry/pipelines/{id}` | [Get pipeline info](/api-reference/batch/registry/pipelines/get-pipeline) | | `GET` | `/batch/registry/pipelines/{id}/schema` | [Get pipeline schema](/api-reference/batch/registry/pipelines/get-pipeline-schema) | ### Files API | Method | Endpoint | Description | | - | - | - | | `POST` | `/files` | [Upload file](/api-reference/files/upload) | | `POST` | `/files/base64` | [Upload base64 file](/api-reference/files/upload-base64) | | `DELETE` | `/files/delete/{file_id}` | [Delete file](/api-reference/files/delete-file) | | `GET` | `/files/download/{file_id}` | [Download file](/api-reference/files/download-file) | | `GET` | `/files/info` | [Get files info](/api-reference/files/get-info) | | `GET` | `/files/metadata` | [List all files and their metadata](/api-reference/files/get-all-metadata) | | `GET` | `/files/metadata/{file_id}` | [Get a file's metadata](/api-reference/files/get-metadata) | | `POST` | `/files/uploads/initiate` | [Initiate a direct-to-cloud upload](/api-reference/files/initiate-upload) | | `POST` | `/files/uploads/{upload_id}/parts/urls` | [Generate presigned URLs for upload parts](/api-reference/files/generate-part-urls) | | `POST` | `/files/uploads/{upload_id}/parts/checkpoint` | [Checkpoint completed upload parts](/api-reference/files/checkpoint-parts) | | `POST` | `/files/uploads/{upload_id}/complete` | [Complete a direct-to-cloud upload](/api-reference/files/complete-upload) | | `POST` | `/files/uploads/{upload_id}/abort` | [Abort a direct-to-cloud upload](/api-reference/files/abort-upload) | ### Fine-Tuning Service | Method | Endpoint | Description | | - | - | - | | `POST` | `/fine-tuning/create-job` | [Create a fine-tuning job](/api-reference/fine-tuning/create-job) | | `GET` | `/fine-tuning/get-job` | [Get information about a fine-tuning job](/api-reference/fine-tuning/get-job) | | `GET` | `/fine-tuning/list-jobs` | [List fine-tuning jobs](/api-reference/fine-tuning/list-jobs) | | `POST` | `/fine-tuning/pause-job` | [Pause a fine-tuning job](/api-reference/fine-tuning/pause-job) | | `POST` | `/fine-tuning/resume-job` | [Resume a fine-tuning job](/api-reference/fine-tuning/resume-job) | | `POST` | `/fine-tuning/cancel-job` | [Cancel a fine-tuning job](/api-reference/fine-tuning/cancel-job) | | `GET` | `/fine-tuning/list-job-checkpoints` | [List the checkpoints saved for a given fine-tuning job](/api-reference/fine-tuning/list-job-checkpoints) | | `GET` | `/fine-tuning/list-job-events` | [List the job events for a given fine-tuning job](/api-reference/fine-tuning/list-job-events) | | `GET` | `/fine-tuning/list-job-logs` | [List the events for a given fine-tuning job](/api-reference/fine-tuning/list-job-logs) | | `GET` | `/fine-tuning/list-job-metrics` | [List a fine-tuning job's metrics](/api-reference/fine-tuning/list-job-metrics) | | `GET` | `/fine-tuning/list-checkpoint-options` | [List the checkpoints saved for jobs that match the specified filters](/api-reference/fine-tuning/list-checkpoint-options) | ### Lens API The Lens API has been deprecated and should no longer be used for new code. | Method | Endpoint | Description | | - | - | - | | `POST` | `/lens/sessions/create` | [Create new lens session](/api-reference/lens/create-session) | | `POST` | `/lens/sessions/destroy` | [Destroy lens session](/api-reference/lens/destroy-session) | | `GET` | `/lens/sessions/info` | [Get sessions summary](/api-reference/lens/get-sessions-info) | | `GET` | `/lens/sessions/metadata` | [Get active sessions metadata](/api-reference/lens/get-sessions-metadata) | | `POST` | `/lens/register` | [Register lens](/api-reference/lens/lens-register) | | `POST` | `/lens/clone` | [Clone lens](/api-reference/lens/lens-clone) | | `POST` | `/lens/modify` | [Modify lens](/api-reference/lens/lens-modify) | | `POST` | `/lens/delete` | [Delete lens](/api-reference/lens/lens-delete) | | `GET` | `/lens/info` | [Get lens summary info](/api-reference/lens/get-info) | | `GET` | `/lens/metadata` | [Get detailed lens metadata](/api-reference/lens/get-metadata) | ## Error Handling This example demonstrates both how to handle errors and how to support retrying API calls when transient errors occur. ```python theme={"system"} import requests import time import random def api_call_with_retry(func, *args, **kwargs): max_retries = 3 for attempt in range(max_retries): try: response = func(*args, **kwargs) if response.status_code == 429: # Rate limited retry_after = response.json().get('error', {}).get('details', {}).get('retry_after', 60) time.sleep(retry_after) continue response.raise_for_status() return response.json() except requests.exceptions.HTTPError as e: if e.response.status_code < 500: # Client error - don't retry raise e # Server error - retry with backoff wait_time = (2 ** attempt) + random.uniform(0, 1) time.sleep(wait_time) raise Exception("Max retries exceeded") ``` ## Common Error Codes | Code | HTTP Status | Description | Solution | | - | - | - | - | | `UNAUTHORIZED` | 401 | Invalid API key | Check API key format: `Bearer YOUR_KEY` | | `INVALID_LENS_ID` | 400 | Lens doesn't exist | Get valid IDs from `/lens/metadata` | | `SESSION_NOT_FOUND` | 404 | Session destroyed/expired | Create new session | | `RATE_LIMIT_EXCEEDED` | 429 | Too many requests | Implement exponential backoff | | `FILE_TOO_LARGE` | 413 | File > 1GB | Compress or split file | ## WebSocket Usage ```python theme={"system"} import websocket import json import base64 def on_message(ws, message): response = json.loads(message) print(f"Newton: {response}") def on_open(ws): # Send image data with open('image.jpg', 'rb') as f: image_data = base64.b64encode(f.read()).decode() ws.send(json.dumps({ "type": "image", "data": image_data, "focus": "safety equipment" # Optional })) # Connect to session WebSocket ws = websocket.WebSocketApp( session_endpoint, # From session creation response on_message=on_message, on_open=on_open ) ws.run_forever() ``` ## Rate Limits * **Default**: 100 requests per minute * **Burst**: Up to 20 requests per second * **Sessions**: 10 concurrent sessions per organization * **Files**: 1GB max size, 100 files per hour ## Quick Troubleshooting ```bash theme={"system"} curl https://api.u1.archetypeai.app/v0.5/lens/info \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash theme={"system"} curl https://api.u1.archetypeai.app/v0.5/lens/metadata \ -H "Authorization: Bearer $ATAI_API_KEY" | jq '.[].lens_id' ``` ```bash theme={"system"} curl https://api.u1.archetypeai.app/v0.5/lens/sessions/info \ -H "Authorization: Bearer $ATAI_API_KEY" ``` ```bash theme={"system"} # Get all sessions and destroy them curl https://api.u1.archetypeai.app/v0.5/lens/sessions/metadata \ -H "Authorization: Bearer $ATAI_API_KEY" \ | jq -r '.[].session_id' \ | xargs -I {} curl -X POST https://api.u1.archetypeai.app/v0.5/lens/sessions/destroy \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"session_id\": \"{}\"}" ``` ## Resources Manage API keys and organization settings, run batch jobs, and create and manage agents Get help from our technical team # Activity Monitor Source: https://docs.archetypeai.app/code-examples/command-line-demos/activity-monitor/activity-monitor (Archived) Legacy Lens-based CLI example: monitor video files or RTSP streams from the terminal. ## Prerequisites The instructions below assume you are following best practices and have downloaded this git repo into a parent directory at: \~/atai. If you have already installed the [ATAI Python Library](https://github.com/archetypeai/python-client) and cloned the [cookbook repository](https://github.com/archetypeai/archetypeai-cookbook), proceed directly to [Quickstart](#quick-start). Before proceeding, check the [requirements and correct Python version](https://docs.archetypeai.app/libraries/python#requirements) for the ATAI Python Library. To upgrade your Python client settings, please check our [Python Client library](https://docs.archetypeai.app/libraries/python#upgrade-python-client). #### Install Conda ``` wget https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh bash Anaconda3-2022.05-Linux-x86_64.sh source ~/.bashrc ``` #### Setup dev environment ``` conda create -n dev_env python=3.10 conda activate dev_env ``` #### Install [ATAI Python Library](https://github.com/archetypeai/python-client) ```bash theme={"system"} git clone git@github.com:archetypeai/python-client.git cd python-client python -m pip install . ``` #### Clone [Cookbook Repository](https://github.com/archetypeai/archetypeai-cookbook) ```bash theme={"system"} git clone https://github.com/archetypeai/archetypeai-cookbook.git ``` ## Quick Start Analyze video content through natural language queries using the interactive CLI. ### Running the Demo From the Cookbook root directory with your conda environment activated: ```bash theme={"system"} cd command-line-demos/activity-monitor python quickstart.py ``` Sample videos are available in the `sample_videos/` directory for testing the demo. ## Interactive Prompts 1. **API Endpoint**: Your ArchetypeAI API endpoint (press Enter to use the default) 2. **Input Type**: Choose `video` (local file) or `rtsp` (camera stream) 3. **Source**: * For video: Path to video file (drag & drop supported) * For RTSP: Camera stream URL 4. **Focus**: Your question about the video (e.g., "Is there a person?", "What's happening?") 5. **Temporal Focus**: The interval between analyzed frames in seconds (default: 5) ## Example Session ``` === Activity Monitor === Enter your API Endpoint (Press Enter for default): Input type (video/rtsp): Input type (video/rtsp): video Enter path to video file: /Users/PATH/Videos/delivery.mp4 Enter focus (what to look for): What's happening? Temporal focus (default: 5): --- Configuration Summary --- API Endpoint: https://api.u1.archetypeai.app/v0.5 Input: VIDEO Video: /Users/PATH/Videos/delivery.mp4 Focus: What's happening? Press Enter to start monitoring... Uploading video: /Users/PATH/Videos/delivery.mp4 Monitoring started — looking for: 'What's happening?' Press Ctrl+C to stop 00:00:05: A FedEx Ground delivery truck is parked on the street, and a person is walking towards it with a package. 00:00:06: A FedEx Ground delivery truck is parked on the street, and a person is walking towards it with a package. 00:00:07: A FedEx Ground delivery truck is parked on the street, and a person is walking towards it with a package. ... Stopped. Session finished. ``` ## Output The system provides timestamped natural language descriptions of the video content. Each line corresponds to a frame at the given timestamp, describing what the model observes at that point in the video. For local video files, responses are generated for the duration of the video. For RTSP streams, responses update continuously until you press `Ctrl+C` to stop monitoring. ## Temporal Focus Configuration The temporal focus defines the interval (in seconds) between analyzed frames in each inference cycle. A larger value means fewer frames are examined, which can reduce detail but speed up processing. A smaller value increases the granularity of analysis but may require more computation. ### Recommended Settings | Setting | Value | Use Case | | - | - | - | | Default | 5 | Optimal for most scenarios | | Short videos | 3 | Ensures sufficient granularity for brief clips | | Long-form content | 10–15 | Captures broader context and patterns | # Machine State Lens Source: https://docs.archetypeai.app/code-examples/command-line-demos/machine-state/machine-state (Archived) Legacy Lens-based CLI example: classify machine states from time-series CSV data. ## Prerequisites The instructions below assume you are following best practices and have downloaded this git repo into a parent directory at: \~/atai. If you have already installed the [ATAI Python Library](https://github.com/archetypeai/python-client) and cloned the [cookbook repository](https://github.com/archetypeai/archetypeai-cookbook), proceed directly to [Quickstart](#quick-start). Before proceeding, check the [requirements and correct Python version](https://docs.archetypeai.app/libraries/python#requirements) for the ATAI Python Library. To upgrade your Python client settings, please check our [Python Client library](https://docs.archetypeai.app/libraries/python#upgrade-python-client). #### Install Conda ``` wget https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh bash Anaconda3-2022.05-Linux-x86_64.sh source ~/.bashrc ``` #### Setup dev environment ``` conda create -n dev_env python=3.10 conda activate dev_env ``` #### Install [ATAI Python Library](https://github.com/archetypeai/python-client) ```bash theme={"system"} git clone git@github.com:archetypeai/python-client.git cd python-client python -m pip install . ``` #### Clone [Cookbook Repository](https://github.com/archetypeai/archetypeai-cookbook) ```bash theme={"system"} git clone https://github.com/archetypeai/archetypeai-cookbook.git ``` ## Quick Start Analyze time-series sensor data to classify machine states using few-shot learning with example patterns. ### Running the Demo From the cookbook root directory with your conda environment activated: ```bash theme={"system"} cd command-line-demos/machine-state python quickstart.py ``` Sample CSV files are provided in the `sample_files/` directory, including a data file and example focus files for testing the demo. ## Interactive Prompts 1. **API Endpoint**: Your ArchetypeAI API endpoint (press Enter to use the default) 2. **Data File**: Path to the CSV file containing sensor data to analyze 3. **Focus Files**: Paths to example CSV files for each state you want to classify. Type `done` when finished adding files. 4. **Window Size**: Number of data points per analysis window (default: 1024) 5. **Step Size**: Number of data points to advance between windows (default: same as window size) ## Example Session ``` === Machine State Lens === Enter your API Endpoint (Press Enter for default): Enter path to CSV to analyze: /Users/benxtan/Projects/ArchetypeAI/infer_sim5.csv --- Add Focus Files --- Provide CSV example(s) for each class (e.g., healthy.csv -> class 'healthy'). Type 'done' when finished. Focus CSV path (or 'done'): /Users/benxtan/Projects/ArchetypeAI/healthy_sim5.csv Added: class 'healthy_sim5' from healthy_sim5.csv Focus CSV path (or 'done'): done Window size [default 1024]: Step size [default 1024]: --- Configuration Summary --- Lens ID: lns-1d51909182270be2-bc1O8andqxf8b4os API Endpoint: https://api.u1.archetypeai.app/v0.5 Data file: /Users/benxtan/Projects/ArchetypeAI/infer_sim5.csv Classes: 1 - healthy_sim5: /Users/benxtan/Projects/ArchetypeAI/healthy_sim5.csv Press Enter to start the analysis... Session created: lsn-2b03144ecb0f022b5235b32734b308 Streaming...Press Ctrl+C to stop. [1768401541.39556] -> Predicted class: ['healthy_sim5', {'healthy_sim5': 5}] [1768401541.397359] -> Predicted class: ['healthy_sim5', {'healthy_sim5': 5}] [1768401541.398611] -> Predicted class: ['healthy_sim5', {'healthy_sim5': 5}] ... Stopped. Session finished. ``` ## Sample Data The demo includes sample files in the `sample_files/` directory: * `data.csv` - Sensor data to analyze * `focus/healthy.csv` - Example of healthy machine state * `focus/broken.csv` - Example of broken machine state ## Classification Tips ### Naming Convention Class names are automatically derived from focus file names: * `healthy.csv` creates class "healthy" * `broken.csv` creates class "broken" * `normal_operation.csv` creates class "normal\_operation" ## Window Size Configuration The window size parameter determines how many data points Newton analyzes in each inference cycle. This affects the granularity of state classification. ### Recommended Settings | Setting | Value | Use Case | | - | - | - | | Default | 1024 | Optimal for most scenarios | | High-frequency sensors (above 100Hz) | 256–512 | Finer granularity for fast-sampling data | | Low-frequency sensors (below 10Hz) | 64–128 | Appropriate window for slower data | | Maximum | 1024 | Upper limit for window size | ### How It Works Each window represents a time segment of sensor data. The system compares these windows against your focus examples to classify the machine state. Non-overlapping windows (step size = window size) provide independent classifications, while overlapping windows offer smoother state transitions. ### Constraints * Window size cannot exceed the length of your shortest focus file * Minimum window size is 16 data points for meaningful analysis # Example Projects Source: https://docs.archetypeai.app/code-examples/example-projects Open-source demo projects built on the Agents API and the Direct Query API — clone them as starting templates for agent, time-series, vision, and text reasoning applications. These public repositories demonstrate real applications built on the [Agents API](/core-concepts/agents/api), and on the [Direct Query API](/api-reference/query) with the Newton Omega and Fusion models. Each is a complete, runnable project — clone one as a starting template for your own use case. If you're new to the platform, run the [Developer Quickstart](/introduction/getting-started) first: it covers the same patterns at their smallest scale. To build with a coding agent, the [Agent Skills](/for-agents/agent-skills) teach these patterns directly. ## Agents Fit an agent on your own labelled data, then run it — see the [Operational State Monitoring agent](/core-concepts/agents/osm). Washing-machine vibration (LARCO) → an OSM agent fitted on the platform: an Optimizations search, the best trial promoted to a blueprint, one Evals test, then a bundle delivered to a second machine and scored against its held-back labels. ## Time-Series Embeddings (Newton Omega) Six-stage water-treatment-plant anomaly dashboard: per-channel Omega embeddings + client-side KNN, with embedding views and per-stage accuracy badges. Wind-farm SCADA data: detects a real frequency-converter fault against a healthy peer turbine using a leakage-free n-shot library. Drilling state classification from 14 North Sea wells, evaluated live against ground truth. ## Vision & Text Reasoning (Newton Fusion) Live Caltrans CCTV analysis — samples a burst of frames per interval and sends them as one multi-frame query to reason over flow, incidents, and conditions. Wildfire detection across 1,200+ ALERTCalifornia cameras — per-camera smoke, fire, and haze assessment plus zone Q\&A. Real-time USGS feed → text reasoning over structured seismic data: aftershock sequences, clustering, regional-risk ranking. California power grid (CAISO supply/demand) → reasoning on duck-curve dynamics, ramp, renewable share, and grid-stress risk. "Is anyone home?" — occupancy inference from residential WiFi device telemetry, with per-window verdicts shown against ground truth. If you build something with these patterns, open a PR against [agent-skills](https://github.com/archetypeai/agent-skills) to share what you learned — the empirical gotchas documented there came from real production runs. # Google Sheets Integration Source: https://docs.archetypeai.app/code-examples/machine-state/sensor-analysis-with-sheets (Archived) Legacy Lens-based example: sensor analysis logged to Google Sheets. ```mermaid theme={"system"} graph LR A[CSV Sensor Data] --> B[Machine State Lens] C[N-shot files] --> B B --> D[Google Sheets Results] style B fill:#9EBBFF,stroke:none,color:#000000 ``` ## How it works * **Machine State Lens** running in Archetype platform for time-series classification * **CSV analysis** with n-shot files sent to Newton for few-shot learning classification * **Google Sheets integration** for real-time results logging and collaborative monitoring * **Two integration modes**: 1. **File-to-Sheets**: Run code in the terminal and log results in Sheets 2. **Spreadsheet-Driven**: Control everything from Sheets ## Prerequisites The instructions below assume you are following best practices and have downloaded this git repo into a parent directory at: \~/atai. If you have already installed the [ATAI Python Library](https://github.com/archetypeai/python-client) and cloned the [cookbook repository](https://github.com/archetypeai/archetypeai-cookbook),proceed directly to [Setup](#setup). #### Install Conda ``` wget https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh bash Anaconda3-2022.05-Linux-x86_64.sh source ~/.bashrc ``` #### Setup dev environment ``` conda create -n dev_env python=3.10 conda activate dev_env ``` #### Install [ATAI Python Library](https://github.com/archetypeai/python-client) ```bash theme={"system"} git clone git@github.com:archetypeai/python-client.git cd python-client python -m pip install . ``` #### Clone [Cookbook Repository](https://github.com/archetypeai/archetypeai-cookbook) ```bash theme={"system"} git clone https://github.com/archetypeai/archetypeai-cookbook.git ``` ## Setup ### Google API Configuration To authenticate with Google Sheets, you'll need OAuth 2.0 credentials. Follow the [Google Sheets API Credentials Setup Guide](/code-examples/machine-state/setup/credentials-setup) to configure your `credentials.json` file. ## Run Demos ## Demo 1: Command Line to Sheets Analyze local CSV files and automatically log results to Google Sheets. ### Running the Demo From the Cookbook root directory with your conda environment activated: ```bash theme={"system"} cd spreadsheet-analysis/cl-to-sheets/ pip install -r requirements.txt python app.py ``` ### Interactive Prompts 1. **API Key**: Your ArchetypeAI API key 2. **Google Sheets ID**: Extract from your spreadsheet URL 3. **Data file**: Path to CSV file to analyze (drag & drop supported) - you can use the files under `command-line-demos/machine-state/sample-files` 4. **N-shot files**: Example CSV files for each state class ### Example Session ``` === Sensor Analysis with Google Sheets === Enter your Archetype AI API key: your-key-here Enter your Google Sheets ID: 1ehByJmpvDBH357BRuDBmQ2EB12qjTjj4Y0Z1OXxmGro Enter path to the file to analyze: /path/to/sensor_data.csv ✓ File loaded: 5000 rows Enter path to focus CSV file: /path/to/healthy.csv ✓ Added: class 'healthy' from healthy.csv Enter path to focus CSV file: /path/to/broken.csv ✓ Added: class 'broken' from broken.csv Enter path to focus CSV file: done --- Configuration Summary --- Data file: sensor_data.csv Focus classes: healthy, broken Press Enter to start analysis... 🔍 Analyzing sensor data... ✓ Window 1: healthy (92% confidence) - Logged to sheet ✓ Window 2: healthy (88% confidence) - Logged to sheet ✓ Window 3: broken (95% confidence) - Logged to sheet ``` ## Demo 2: Spreadsheet-Driven Control everything directly from Google Sheets - no need to interact with terminal once script is running. ### Setup Template Create a pre-configured spreadsheet template: ```bash theme={"system"} cd spreadsheet-analysis/spreadsheet-driven pip install -r requirements.txt python create_example_spreadsheet.py ``` Keep the spreadsheet ID for next step. ### Running the Monitor Start the monitoring script: ```bash theme={"system"} python app.py ``` ### Triggering Analysis #### Prepare Your Data 1. Open the Google Sheet created in the previous step 2. Navigate to the **Config** sheet and add your API key in cell **B1** 3. Import your sensor data: * Click on the **Data** sheet tab * Import your CSV data to analyze (File → Import → Upload) * Ensure headers match: `timestamp`, `a1`, `a2`, `a3`, `a4` #### Add Focus Examples 1. Create sheets for each machine state you want to classify 2. Import example data for each state: * Create/rename a sheet tab (e.g., "healthy", "broken") * Import CSV data representing that state * Repeat for each classification category #### Start Analysis 1. Return to the **Config** sheet 2. Type **"RUN"** in cell **B10** 3. Monitor progress in cell **B11** (status updates) 4. View results in the automatically created **Results** sheet ### Real-time Monitoring The script monitors cell B10 for triggers and updates status in B11: * **"Ready"** - Waiting for trigger * **"TRIGGERED"** - Analysis starting * **"RUNNING - Processed X windows"** - In progress * **"COMPLETED - Analyzed X windows"** - Finished * **"ERROR - \[details]"** - Something went wrong ## Window Size Configuration (to be reviewed) The window size parameter determines how many data points Newton analyzes in each inference cycle. This affects the granularity of state classification. ### Recommended Settings * **Default**: Auto-calculated based on focus file lengths * **High-frequency sensors** (greater than 100Hz): 256-512 points * **Low-frequency sensors** (less than 10Hz): 64-128 points * **Maximum**: 1024 points ### How It Works Each window represents a time segment of sensor data. The system compares these windows against your focus examples to classify the machine state. Non-overlapping windows (step size = window size) provide independent classifications, while overlapping windows offer smoother state transitions. ### Constraints * Window size cannot exceed the length of your shortest focus file * Minimum window size is 16 data points for meaningful analysis # Google Sheets API Credentials Source: https://docs.archetypeai.app/code-examples/machine-state/setup/credentials-setup (Archived) Setup guide for the legacy Google Sheets example: OAuth 2.0 credentials. ## Overview Both Google Sheets integration methods require OAuth 2.0 credentials to authenticate with the Google Sheets API. This guide walks through the one-time setup process. ## Prerequisites * Google account with access to [Google Cloud Console](https://console.cloud.google.com/) * Admin permissions to create a new project or access to an existing project ## Configuration Steps ### Step 1: Enable Google Sheets API 1. Navigate to [Google Cloud Console](https://console.cloud.google.com/) 2. Select an existing project or create a new one using the project dropdown 3. In the search bar, type **"Google Sheets API"** 4. Select the Google Sheets API from the results 5. Click **Enable** to activate the API for your project ### Step 2: Create OAuth 2.0 Credentials #### Configure OAuth Consent Screen 1. In the left sidebar, navigate to **APIs & Services** → **Credentials** 2. Click **+ CREATE CREDENTIALS** → **OAuth client ID** 3. If prompted, configure the OAuth consent screen first: * User Type: Select **External** (unless using Google Workspace) * App Information: * App name: "Newton Sheets Integration" (or your preferred name) * User support email: Your email address * Developer contact: Your email address * Scopes: No additional scopes needed (defaults are sufficient) * Test users: Add your email address 4. Click **Save and Continue** through each section #### Generate Client ID 1. Return to **Credentials** → **+ CREATE CREDENTIALS** → **OAuth client ID** 2. Application type: Select **Desktop app** 3. Name: "Newton Demo Client" (or your preferred identifier) 4. Click **Create** ### Step 3: Download and Install Credentials 1. In the OAuth 2.0 Client IDs list, locate your newly created client 2. Click the **Download** button (⬇) to download the JSON file 3. Rename the downloaded file to exactly: `credentials.json` 4. Place the file in the appropriate directories: * For File-to-Sheets: `newton-demos/spreadsheet-analysis/cl-to-sheets` * For Spreadsheet-Driven: `newton-demos/spreadsheet-analysis/spreadsheet-driven` Both integration methods require their own copy of `credentials.json` in their respective directories. ### Step 4: First-Time Authentication When you run either integration script for the first time: 1. Your default browser will open automatically 2. Sign in with your Google account 3. Review the permissions request 4. Click **Allow** to grant access 5. The script creates `token.pickle` for future authentication The `token.pickle` file stores your authentication token locally. Keep this file secure and do not commit it to version control. ## Security Best Practices ### File Management * Add `credentials.json` and `token.pickle` to `.gitignore` * Never commit authentication files to version control # Telegram Bot Setup Source: https://docs.archetypeai.app/code-examples/telegram-alerts/setup/bot-setup (Archived) Setup guide for the legacy Telegram alerts example: creating and configuring the Telegram bot. ## Step 1: Create the Bot Go to [https://web.telegram.org/](https://web.telegram.org/) and log into your Telegram account Open a new chat with BotFather → [https://web.telegram.org/k/#@BotFather](https://web.telegram.org/k/#@BotFather) 1. Click **Start** 2. Type `/newbot` and follow the instructions in the chat You'll receive a message with the bot token. It should follow the format `12345812:AAHFfasdfasdf`. Store it securely. ### Example Bot Token Message ``` Done! Congratulations on your new bot. You will find it at t.me/testing_atai_bot. Use this token to access the HTTP API: 796286017123123:AAHfDqivpCQXxM5SNt_BqBjNANddAdowHJASJU Keep your token secure and store it safely, it can be used by anyone to control your bot. ``` ## Step 2: Get Your Chat ID There are two simple ways to get your Chat ID: ### Option 1: Using @WhatChatIDBot Start a conversation with [@WhatChatIDBot](https://t.me/WhatChatIDBot) in Telegram The bot will give you a number - that's your Chat ID (e.g., `908246003`) WhatChatIDBot example showing Chat ID ### Option 2: Using @RawDataBot Start a conversation with [@RawDataBot](https://t.me/RawDataBot) in Telegram The bot will return JSON data. Copy the `id` field - that's your Chat ID RawDataBot JSON response showing ID field ## Step 3: Add Your Credentials Now you should have both: * **Bot Token**: `796286017123123:AAHfDqivpCQXxM5SNt_BqBjNANddAdowHJASJU` * **Chat ID**: `908246003` ### Update Application Code Add these credentials to your application: ```python app_telegram.py theme={"system"} # Update these values in your code BOT_TOKEN = "796286017123123:AAHfDqivpCQXxM5SNt_BqBjNANddAdowHJASJU" CHAT_ID = "908246003" ``` ```bash Environment Variables (Recommended) theme={"system"} # Create .env file TELEGRAM_BOT_TOKEN=796286017123123:AAHfDqivpCQXxM5SNt_BqBjNANddAdowHJASJU TELEGRAM_CHAT_ID=908246003 ``` ## Step 4: Test the Connection Run the bot application: `python app_telegram.py` Send `/start` to your bot in Telegram Your bot should respond with available commands and usage instructions # RTSP Configuration Source: https://docs.archetypeai.app/code-examples/telegram-alerts/setup/rtsp-setup (Archived) Setup guide for the legacy Telegram alerts example: RTSP on a Tapo C100 camera. # Set Up RTSP on Tapo C100 and access it over the Internet This document explains how to set up your Tapo camera as an RTSP stream, accessible by Newton. It follows two steps: first, you set up the Tapo as an RTSP camera, and second, you make the RTSP accessible over the internet. ## 1. Enable RTSP on Tapo C100 and access it locally Install the Tapo app on your smartphone (Tested on iOS) Add your Tapo C100 camera to the app following the Tapo instructions Go to: **Camera Settings → Advanced Settings (little gear on the top right) → Camera Account → Turn it on, and edit Account Information** Create an RTSP account (username & password) * This is different from your Tapo app account and will be used for RTSP authentication * For example: username and password as `testingwithatai` and `testingwithatai` Go to camera > Device Info > IP Address ## RTSP Stream URLs You should be able to see your RTSP stream (running locally) in these links: ```bash Main Stream (HD) theme={"system"} rtsp://USERNAME:PASSWORD@CAMERA_IP:554/stream1 ``` ```bash Sub Stream (Lower Quality) theme={"system"} rtsp://USERNAME:PASSWORD@CAMERA_IP:554/stream2 ``` For example: ```bash theme={"system"} rtsp://testingwithatai:testingwithatai@192.168.1.101:554/stream1 ``` ### Testing the Stream You can test it locally with VLC: **Media → Open Network Stream → paste the RTSP URL** or go to the browser and pass the link, it'll redirect you to VLC. ## 2. Make the RTSP Stream Accessible Over the Internet via Port Forwarding This exposes the camera directly to the internet, and the camera has microphone integrated. This is a security risk and should be used just for testing purposes. ### Port Forwarding Setup Log in to your router's admin panel (check Router Access Data on your router, it should look like this) Router Access Information Go to **Port Forwarding / Virtual Server** settings Forward **TCP port 554** to the local IP of your camera (e.g., `192.168.1.101`) Example rule: * **External Port:** 554 * **Internal Port:** 554 * **Internal IP:** 192.168.1.101 * **Protocol:** TCP Find your public IP address (Google "what is my IP" or use [whatismyip.com](https://whatismyip.com)) Access the stream externally using: ```bash theme={"system"} rtsp://USERNAME:PASSWORD@PUBLIC_IP:554/stream1 ``` ### Example External URL For example: ```bash theme={"system"} rtsp://testingwithatai:testingwithatai@79.158.9.105:554/stream2 ``` Replace `79.158.9.105` with your actual public IP address, and use your actual RTSP credentials. ## Security Considerations **Important Security Notes:** * Port forwarding exposes your camera directly to the internet * The camera not only streams images, but also sound # Real-time Camera Alerts Source: https://docs.archetypeai.app/code-examples/telegram-alerts/telegram-alerts (Archived) Legacy Lens-based example: smart video monitoring with alerts delivered to Telegram. ## Diagram ```mermaid theme={"system"} graph LR A[RTSP Camera] --> B[Lens] C[Terminal/Telegram] --> B B --> D[Response Filtering] D --> E[Telegram Alerts] style B fill:#9EBBFF,stroke:none,color:#000000 style D fill:#9EBBFF,stroke:none,color:#000000 ``` ## How it works * **Activity Monitor Lens** running in Archetype platform * **Real time camera analysis**. To set up your own camera, follow the [RTSP setup guide](/code-examples/telegram-alerts/setup/rtsp-setup) * **Curated prompting.** The model is prompted in a way that it tries to minimize hallucination, and to respond following a format that we can search after. It follows a 3 step process: 1. Analyze exactly what it sees in the video 2. Summarize observations related to the focus area 3. Decide whether to send an alert using the word **Alert** at the beginning. ```python theme={"system"} "STOP. FOLLOW THIS EXACT FORMAT: Step 1: Write I see in this video: " "then list ALL detected objects, vehicles, people, animals, buildings, and their " "visual or behavioral attributes (colors, shapes, positions, actions). Then close " "with . Step 2: Write Search result: and analyze if the item or event being " "searched for is present in your scan. Step 3: If the searched-for item is not found, " "write: No alerts: short description of what was detected, max 15 words. " "If the searched-for item is present, it is VERY IMPORTANT THAT YOU WRITE THIS: " "**Alert**: short description of what was detected, max 15 words ONLY return one of the above. " "Do not describe anything else." ``` * **Response filtering.** This format allows us to expect the trigger word **"Alert"** whenever what's in focus is detected, so we watch for that trigger word to send alerts. That trigger word could be anything, but would need to match in both prompt and response filter. ## Run the demos ## Prerequisites The instructions below assume you are following best practices and have downloaded this git repo into a parent directory at: \~/atai. If you have already installed the [ATAI Python Library](https://github.com/archetypeai/python-client) and cloned the [cookbook repository](https://github.com/archetypeai/archetypeai-cookbook), proceed directly to [Quickstart](/code-examples/command-line-demos/activity-monitor/activity-monitor#quick-start). #### Install Conda ``` wget https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh bash Anaconda3-2022.05-Linux-x86_64.sh source ~/.bashrc ``` #### Setup dev environment ``` conda create -n dev_env python=3.10 conda activate dev_env ``` #### Install [ATAI Python Library](https://github.com/archetypeai/python-client) ```bash theme={"system"} git clone git@github.com:archetypeai/python-client.git cd python-client python -m pip install . ``` #### Clone the [Cookbook Repository](https://github.com/archetypeai/archetypeai-cookbook.git) ```bash theme={"system"} git clone git@github.com:archetypeai/newton-demos.git ``` #### Configure RTSP Stream and Telegram Bot * **RTSP Stream**: Set up your camera's RTSP stream using the [RTSP Setup Guide](/code-examples/telegram-alerts/setup/rtsp-setup) * **Telegram Bot**: Create and configure your bot following the [Bot Configuration Guide](/code-examples/telegram-alerts/setup/bot-setup) - you'll need the bot token and chat ID ## Run Demos ### Demo 1: Command Line + Telegram * Open a terminal and activate the conda environment where python\_client is installed * Navigate to `telegram-alerts/terminal_bot` ```jsx theme={"system"} $ cd telegram-alerts/terminal_bot ``` * Open the file `app.py` * Add your bot token to BOT\_TOKEN * Add your chat ID to CHAT\_ID * In the terminal: * Run the following commands and follow the instructions: ```jsx theme={"system"} $ python app.py ``` When prompted, enter your API key, select `rtsp/video` and specify the focus area. The system will start monitoring and send notifications when alerts are triggered. Note that this script doesn't terminate sessions automatically. With this version, you can run multiple sessions simultaneously in different terminal windows. ### Demo 2: Only Telegram demo * Open a terminal and activate the conda environment where python\_client is installed. * Navigate to `telegram-alerts/bot_only`. ```jsx theme={"system"} $ cd telegram-alerts/bot_only $ pip install -r requirements.txt ``` * Open the file `app.py` * Add your bot token to BOT\_TOKEN * Add your chat ID to CHAT\_ID * In the terminal: * Run the following commands: ```jsx theme={"system"} $ python app.py ``` * When you run the script, you'll receive a message in Telegram. Follow the instructions to configure your smart monitor. Note: This version only supports running the script in **one terminal window**. # Anomaly Discovery Agent Source: https://docs.archetypeai.app/core-concepts/agents/anomaly-discovery Discovers novel anomalies and failure modes by distinguishing meaningful issues from normal variation, with no labeled failures required. Every sensor data time window comes back with an anomaly score, flagging behavior that falls outside the norm. The Anomaly Discovery Agent is especially useful for new assets, equipment with long life cycles, and unreachable assets such as deep-ocean or satellite systems where labels cannot be collected. ### Use Cases * **Detect previously unknown equipment issues:** The agent scores every window for how far it departs from normal, so problems you didn't know to look for surface from the data alone. * **Identify emerging process abnormalities:** The agent gives every window a continuous anomaly score, so behavior drifting away from normal shows up as a rising score before it becomes an outright fault. * **Surface novel failure modes:** The agent attaches an anomaly score to every detection, so the most unusual windows can be surfaced first for a person to look into. * **Monitor assets without labeled failure history:** The agent builds its baseline from normal-operation data alone, so an asset with no recorded failures can be monitored from day one. ## See an Interactive Example Try out the Anomaly Discovery agent with a predefined data set using our interactive example. Discovers anomalies in bearing vibration without prior knowledge of what a fault looks like. Each sensor data time window is labeled as either normal or anomaly, with a continuous anomaly score for how far it strays from normal operation. ## Using the Archetype AI Python Client How to use the [Archetype AI Python client](https://github.com/archetypeai/python-client/) to work with the Anomaly Discovery agent. An example that runs an Anomaly Discovery agent on sensor data using a platform-hosted quick-start bundle. # Managing Agents Using the Agents API Source: https://docs.archetypeai.app/core-concepts/agents/api An introduction to using the Agents API to create, run, and manage agents. ## Creating an Agent Using an Agent Blueprint Use the [Create Bundle](/api-reference/agents/bundles/create-bundle) endpoint to create an agent bundle using an agent blueprint. ```bash cURL theme={"system"} curl -X POST -H "Authorization: Bearer $ATAI_API_KEY" -H "Content-Type: application/json" \ "$ATAI_API_ENDPOINT/agents/bundle" -d '{ "blueprint": "osm", "name": "My agent name", "values": {"window_size": 16, "step_size": 1, "sample_rate_interval_tolerance": 10.0, "max_temporal_gap": 10.0}, "artifacts": {"fit-classifier": "s3://my-aws-folder/fit-classifier-name.safetensors"} }' ``` ```python Python theme={"system"} import os import requests api_key = os.environ["ATAI_API_KEY"] endpoint = os.environ["ATAI_API_ENDPOINT"] payload = { "blueprint": "osm", "name": "My agent name", "values": { "window_size": 16, "step_size": 1, "sample_rate_interval_tolerance": 10.0, "max_temporal_gap": 10.0, }, "artifacts": { "fit-classifier": "s3://my-aws-folder/fit-classifier-name.safetensors" }, } response = requests.post( f"{endpoint}/agents/bundle", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json=payload, timeout=60 ) ``` ```javascript JavaScript theme={"system"} const apiKey = process.env.ATAI_API_KEY; const endpoint = process.env.ATAI_API_ENDPOINT; const payload = { blueprint: "osm", name: "My agent name", values: { window_size: 16, step_size: 1, sample_rate_interval_tolerance: 10.0, max_temporal_gap: 10.0, }, artifacts: { "fit-classifier": "s3://my-aws-folder/fit-classifier-name.safetensors", }, }; const response = await fetch(`${endpoint}/agents/bundle`, { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify(payload) }); ``` This example creates an agent based on the Operational State Monitoring (OSM) agent blueprint, giving the new agent the name "My agent name", providing a Safetensors file as a fit classifier artifact, and providing several custom configuration options (`window_size`, `step_size`, `sample_rate_interval_tolerance`, and `max_temporal_gap`). ## Running an Agent Once an agent has been created, you can run it using the [Run Bundle](/api-reference/agents/bundles/run-bundle) endpoint. ```bash cURL theme={"system"} curl -X POST -H "Authorization: Bearer $ATAI_API_KEY" -H "Content-Type: application/json" \ "$ATAI_API_ENDPOINT/agents/bundle/$BUNDLE_ID/run" -d '{ "connectors": {"source": [{"type": "file", "id": "sample-data.csv"}]} }' ``` ```python Python theme={"system"} import os import requests api_key = os.environ["ATAI_API_KEY"] endpoint = os.environ["ATAI_API_ENDPOINT"] bundle_id = os.environ["BUNDLE_ID"] payload = { "connectors": { "source": [{"type": "file", "id": "sample-data.csv"}] } } response = requests.post( f"{endpoint}/agents/bundle/{bundle_id}/run", headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, json=payload, timeout=60 ) ``` ```javascript JavaScript theme={"system"} const apiKey = process.env.ATAI_API_KEY; const endpoint = process.env.ATAI_API_ENDPOINT; const bundleId = process.env.BUNDLE_ID; const payload = { connectors: { source: [{ type: "file", id: "sample-data.csv" }], }, }; const response = await fetch(`${endpoint}/agents/bundle/${bundleId}/run`, { method: "POST", headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", }, body: JSON.stringify(payload) }); ``` This code uses the agent to process the data in a CSV file named `sample-data.csv` which has already been uploaded to the Archetype Platform using the [Files API](/core-concepts/files). ## Related Content * [Managing Agents Using the Developer Console](/developer-console/agents/overview) # Manual Generation Agent Source: https://docs.archetypeai.app/core-concepts/agents/manual-generation Analyzes video recordings of a procedure and generates step-by-step work instructions, with a relevant image pulled for every step. Every step comes back as editable structured text, ready to refine and publish. Generates a comprehensive, step-by-step Standard Operating Procedure from a video recording. The output transforms the demonstrated process into an actionable manual that enables any user to complete the task independently. The generated SOP includes: * Sequential step-by-step instructions with clear, concise language * The time range in the source video during which each step takes place * Descriptions of actions, expected outcomes, and important context * Callouts for critical warnings, tips, prerequisites, or dependencies ## Use Cases * **Generate work instructions and standard operating procedures (SOPs):** Extracts the procedure from a video into ordered steps, each with a title, a description, a timestamp, and a frame image, ready to edit and export. * **Document maintenance and inspection procedures:** One recording of the procedure done correctly produces a draft manual, every step linked to the moment in the video it came from. * **Create visual training and onboarding materials:** Every step comes with a visual reference, so the work can be followed and completed correctly. ## Video Recommendations For best results, follow these guidelines: * Use input videos whose durations are five minutes or less. * Include audio narration. It's not mandatory but makes generating accurate output easier. * Any narration should only describe the correct process. Describing an incorrect action in the audio track can reduce the accuracy of the generated manual. ## Configuration The default prompt for the Manual Generation Agent caps the number of steps generated to 10. If your video demonstrates more than 10 steps, provide a custom prompt that states a higher cap on the number of steps. For example: > Generate a concise, ordered list of every distinct step performed in this video, covering > the procedure from the first action to the last. Include brief steps and steps that are > repeated. Use up to 25 steps. Keep each step to at most 20 words. Use both what is shown and > what is said. Do not invent steps that are not shown or stated in the video. Note the inclusion of the instruction "Use up to 25 steps." ## Output Artifacts The output from a successful run of a Manual Generation agent is a JSONL file describing the manual generated by the agent. The JSONL contains a `results` list; each entry in the list describes one step of the procedure shown in the video. Each step in the procedure contains the following properties: | Property | Description | | - | - | | `frame_start` | The video frame number at which the described step begins. | | `frame_end` | The video frame number at which the described step ends. | | `instruction` | The text of the instruction for the step. | | `step` | The step number (starting at 0). | | `timestamp_start` | The timestamp at which the action begins in the video. | | `timestamp_end` | The timestamp at which the action ends in the video. | ## See an Interactive Example Try out the Manual Generation agent with a predefined data set using our interactive example. Generates a step-by-step manual from a recorded procedure. Watches the mouse assembly build and returns numbered steps with the time range each one spans. ## Using the Archetype AI Python Client How to use the [Archetype AI Python client](https://github.com/archetypeai/python-client/) to work with the Manual Generation agent. An example that runs a Manual Generation agent on a procedure video using a canonical blueprint and a newly created bundle. # Operational State Monitoring Agent Source: https://docs.archetypeai.app/core-concepts/agents/osm Continuously monitors machines and industrial processes by identifying changing operating states from multimodal sensor data. Every window comes back with a predicted state and a confidence score. The Operational State Monitoring (OSM) agent continuously labels which operating regime a system is in, from a small set of N-shot labeled examples gathered across environments or sessions. There is no concept of normal or anomalous; every regime is a valid state, and the agent simply reports which one the system currently occupies. Unlabeled data can be incorporated to improve coverage. ## Use Cases * **Monitor asset condition and performance:** Classifies every window into an operating state, turning the raw sensor stream into a continuous, timestamped state record. * **Detect process drift and degradation:** Tracks each state’s dwell time over rolling periods, so slow decline shows up early. * **Identify and maintain optimal operating envelopes:** Reveals the operating envelope as the states an asset normally holds, so out-of-range behavior stands out. ## See an Interactive Example Try out the OSM agent with predefined data sets using our interactive examples. We have two examples available: Classifies the operational state of a drilling rig. Reads nine sensor channels from a North Sea well and labels each time window as one of six states: drilling, reaming, off bottom, in slips, trip in slips, or shut in. Classifies the operating state of a fan coil unit. Reads six sensor channels and classifies them as a stuck valve, a stuck damper, or a heating-side fault. ## Using the Archetype AI Python Client How to use the [Archetype AI Python client](https://github.com/archetypeai/python-client/) to work with the OSM agent. An example that runs an Operational State Monitor (OSM) agent on sensor data using a platform-hosted quick-start bundle. # Overview Source: https://docs.archetypeai.app/core-concepts/agents/overview Overview of the available agent blueprints and how they're used to create new agents. An agent is a bundle of resources that describe how to use Newton to perform a certain task. With an agent configured to perform a needed task, all you need to do is provide the input file or files and the agent will process your data and return the desired output. Agents are created based on agent blueprints, which are templates used as the starting point for building agents that use the Newton Platform to analyze sensor data. Archetype AI offers a variety of agent blueprints you can use to create your own agents: | Agent | Description | | - | - | | [Anomaly Discovery Agent](/core-concepts/agents/anomaly-discovery) | Surface unusual segments that deviate from learned normal behavior. | | [Manual Generation Agent](/core-concepts/agents/manual-generation) | Transform operational video into clear, step-by-step Standard Operating Procedure (SOP) manuals. | | [Operational State Monitoring Agent](/core-concepts/agents/osm) | Continuous awareness of the regime in which a system is operating, drawn from a small set of labeled examples. | | [Rare Event Detection Agent](/core-concepts/agents/rare-event-detection) | Identify rare events from a handful of labeled examples, set against normal operation. | | [Task Verification Agent](/core-concepts/agents/task-verification) | Verify operational tasks are completed correctly and in compliance with defined Standard Operating Procedures (SOPs). | There are two ways you can monitor and manage agents from these agent blueprints: * [Using the Archetype Agents API](/core-concepts/agents/api) * [Using the Archetype Developer Console](/developer-console/agents/overview) To create an agent, you currently need to use the Agents API's [Create Bundle](/api-reference/agents/bundles/create-bundle) endpoint. # Rare Event Detection Agent Source: https://docs.archetypeai.app/core-concepts/agents/rare-event-detection Detects known faults and failures by matching new data against a handful of labeled examples. Each sensor data window is classified as normal or abnormal, with a confidence score. The agent identifies specific, rare events — faults that are easy to miss in a long stream of events — using a small number of labeled examples of each fault alongside examples of normal behavior. These faults do not stop the process; they require post-process remediation or maintenance. ## Use Cases * **Detect known failure modes:** Classifies each window as normal or one of your labeled faults, so a fault you've characterized is caught wherever it recurs. * **Identify critical operational events:** Returns each detected fault timestamped and scored, so high-stakes events surface instead of staying buried in the stream. * **Monitor infrequent quality or safety issues:** Catches issues for which it is too rare to build a conventional detector. * **Reduce missed detections despite limited training data:** Recognizes a fault by its signature, not its exact waveform, so a few labeled examples catch it across other assets. ## See an Interactive Example Try out the Rare Event Detection agent with a predefined data set using our interactive example. Detects rare failures in an industrial water pump. Reads sensor channels (e.g. motor speed, bearing and lube-oil temperatures) and flags each window as normal or breakdown. ## Using the Archetype AI Python Client How to use the [Archetype AI Python client](https://github.com/archetypeai/python-client/) to work with the Rare Event Detection agent. An example that runs a Rare Event Detection agent on sensor data using a platform-hosted quick-start bundle. # Task Verification Agent Source: https://docs.archetypeai.app/core-concepts/agents/task-verification Verifies work is performed according to standard operating procedures by observing video data. Returns a pass/fail verdict with a short description and the timestamp it came from, plus a summary across the run. The Task Verification Agent verifies whether an observed task execution matches the defined Standard Operating Procedure (SOP) and determines if the task was completed successfully and correctly. * Compares the observed actions, sequence, and outcomes against the expected SOP steps. * Identifies completed, skipped, incorrect, or out-of-order steps. * Validates whether critical requirements, dependencies, and success criteria were met. * Detects deviations, inconsistencies, or operational errors. * Assesses overall task completion status and execution quality. ## Use Cases * **Detect task deviations and quality issues:** Marks each SOP step passed, failed, or missing against the video, with the timestamps and a reason for every call. * **Verify SOP compliance:** Give it the SOP and a video and it returns a per-step result zero-shot, with no training or setup, so compliance is the set of steps that passed. * **Reduce manual quality inspections:** Runs the same step-by-step check on every recorded video instead of a sampled few, each result timestamped so review jumps straight to the failures. * **Support operator training, onboarding, and consistency:** Returns a reason for every passed, failed, or missing step, so recurring mistakes across runs show where operators need coaching. ## Configuration For best results, use input videos whose duration is no more than five minutes. ## See an Interactive Example Try out the Task Verification agent with a predefined data set using our interactive example. Verifies a recorded task against a reference procedure. Watches the manifold cap assembly and marks each SOP step as completed, out of order, or missing. ## Using the Archetype AI Python Client How to use the [Archetype AI Python client](https://github.com/archetypeai/python-client/) to work with the Task Verification agent. An example that runs a Task Verification agent on a task-execution video using a canonical blueprint and a newly created organization-owned bundle. # Overview Source: https://docs.archetypeai.app/core-concepts/batch-processing/overview How the Batch Processing API runs jobs against many files via the Jobs Orchestration Service: jobs, indexes, tasks, pipelines, and the job lifecycle. The Batch Processing API uses the Jobs Orchestration Service (JOS) to run processing jobs against multiple files. JOS owns the entire lifecycle of the jobs it runs: it validates the configuration, manages job pipelines, handles Kubernetes resource management, monitors the progress of the job, and publishes events. Events are delivered and metrics streamed using Redis streams. ## Concepts ### Job A **job** is a complete work request submitted to JOS using either the [Batch Manager](/developer-console/batch-manager) in the Console or the Batch Processing API. ### Index An **index** is a unit of parallel execution within a job. A job's **`parallelism`** parameter specifies the maximum number of indexes that will be used to process that job. ### Completion A **completion** is a successful resolution of an index. ### Task A **task** is the finest-grained data processing unit within the Jobs Orchestration Service. A task represents a single item to be processed. For example, a task may handle a single inference request on one input, or one training step on a batch. Tasks are distributed across indexes, and progress tracking and metrics are reported at the task level. ### Pipeline A pipeline is a named, versioned configuration template that defines defaults and requirements for a particular workload. Pipelines are managed by the Jobs Orchestration Service and are referenced by APIs when submitting jobs. The pipeline configuration includes: * The container image and command, indicating which worker to use. * Resource defaults such as minimum CPU, memory, and GPU type. * Queue routing information. * Timeout and retry policy settings. * The OpenAPI/JSON schema defining all configuration options and rules. * A user configuration schema defining a subset of the configuration schema that users are allowed to override when submitting a job. Fields outside this schema are locked to pipeline defaults. * The default configuration for the pipeline, specifying the default values for all configuration fields, except for the required fields. This is the base configuration that gets merged with the user overrides. ## The Batch Job Lifecycle Each job has a lifecycle, indicated by the job's [status](/api-reference/batch/jobs/get-job#param-status). When a job is first created by using the [Create Job](/api-reference/batch/jobs/create-job) endpoint, it begins in the `PENDING` state. When it's admitted into a queue for processing, its state changes to `ADMITTED`. When a GPU is available to run the job, its state changes to `RUNNING`. Cancelled jobs transition to the `CANCELLED` state, while successfully completed jobs have the state `COMPLETE`. If a higher priority job is scheduled on the same GPU as an existing job, the existing job transitions into the `PREEMPTED` state. It will automatically return to the `PENDING` state when it is re-enqueued. If a job reaches a *recoverable* error state, the job transitions into the `INTERRUPTED` state. On the other hand, if a job fails, its state transitions to `FAILED`. This can happen for a variety of reasons such as invalid input parameters or issues with the supplied data. A `PAUSED` or `INTERRUPTED` job can be resumed using the [Resume Job](/api-reference/batch/jobs/resume-job) endpoint; this moves the job back to the `PENDING` state, which will attempt to continue the job from its last checkpoint. ## Running a Batch Using the Console To run a batch using the console, use the [Batch Manager](/developer-console/batch-manager). ## Running a Batch using the Batch Processing API Use the [Files API](/core-concepts/files/files) to upload the files to be processed into your file library, if they're not already there. Create the job using the [Create Job](/api-reference/batch/jobs/create-job) endpoint. This creates the job and adds the job to the pipeline. Monitor the job's status using the [Get Job](/api-reference/batch/jobs/get-job) endpoint. The job has finished running if its state is `COMPLETE`, `CANCELLED`, `INTERRUPTED`, or `FAILED`. To pause a job, use the [Pause Job](/api-reference/batch/jobs/pause-job) endpoint. If a job needs to be cancelled, use the [Cancel Job](/api-reference/batch/jobs/cancel-job) endpoint. `PAUSED` or `INTERRUPTED` jobs can be resumed using the [Resume Job](/api-reference/batch/jobs/resume-job) endpoint. `FAILED` jobs cannot be retried. As the job progresses (or once it's completed), you can get a list of the events that have occurred on the job using the [List Job Events](/api-reference/batch/events/list-job-events) endpoint. You can get a list of the output files generated by the job using the [List Outputs](/api-reference/batch/io/list-outputs) endpoint. Once you have the list, you can download the artifacts using HTTPS requests. ### Examples Find examples demonstrating various aspects of using the Batch Processing API in our [archetypeai-batch-examples-volve](https://github.com/archetypeai/archetypeai-batch-examples-volve) repository. These examples use real-world sensor data from the [Equinor Volve Data Village](https://www.equinor.com/energy/volve-data-sharing) and show how to: * Prepare data for analysis * Upload data to the platform * Run the batch jobs * Download the output data * Evaluate the output data against ground truth # YAML Parameter Reference Source: https://docs.archetypeai.app/core-concepts/batch-processing/yaml-parameters A reference for the parameters available when configuring batch jobs. This reference describes each of the YAML parameters available when configuring each of the task types supported by the Batch Processing API. Per-worker machine state classification job configuration. Inference batch size. Must be an integer `1` or higher. Optional K-Nearest Neighbor (KNN) classifier over embeddings configuration. The type of metric to use. One of `cityblock`, `cosine`, `euclidean`, `haversine`, `l1`, `l2`, `manhattan`, `nan_euclidean`. KNN count. Must be at least `3`. Whether or not to normalize embeddings before classification. The uniform distance weighting method to use with KNN: `distance` or `uniform`. The number of iterations to process between forced flushes. Must be at least `1`. The type of encoder model to use for the Machine State Classification task: `omega_1_3_surface`, `omega_1_3_power_drive`, `omega_1_4_base`, `omega_1_5_base`. Windowed reader configuration options. The names of the columns to include in the analysis. The step between consecutive windows. Must be at least `1`. The name of the column in the input data that contains the timestamps. The number of samples in each window. Must bet at least `1`. Number of worker pods to run in parallel for a single job. **Must be set to `1`.** ```yaml Example configuration theme={"system"} worker: config: batch_size: 32 classifier_config: metric: euclidean n_neighbors: 5 normalize_embeddings: false weights: uniform flush_every_n_iteration: 150 model_type: omega_1_4_base reader_config: data_columns: - c1 - c2 - c3 step_size: 1024 timestamp_column: timestamp window_size: 64 parallelism: 1 ``` Per-worker activity detection inference configuration. Generation hyperparameters. Whether or not to enable stochastic sampling. When `false`, decoding is greedy. The upper bound on tokens generated, per sample. Must be at least `1`. Penalty applied to previously-generated tokens. Must be greater than `0` and no greater than `2.0`. Values above `1.0` discourage repetition. Softmax temperature for sampling. Must be greater than `0` and no greater than `2.0`. The higher this value, the more diverse. Nucleus-sampling threshold. Keeps the smallest token set whose cumulative probability is greater than or equal to this value. Must be greater than `0` and no greater than `1.0`. Top-k cutoff. Set to `0` to disable cutoff. The maximum number of video frames sampled per video input. Extra frames are dropped uniformly. Must be between 1 and 64. Specifies the model bundle to use. Standard permitted values are: * `newton/c:2.3.0-7b-base` * `newton/c:2.4.0-7b-base` * `newton/c:2.5.0-8b-base` * `newton/c:2.5.1-8b-base` * `newton/c:2.6.0-8b-bf16-base` * `newton/c:2.6.0-8b-fp8-base` * `newton/c:2.6.0-30b-a3b-fp8-base` * `newton/visual-audio-c:2.5.0-v2-8b` * `newton/visual-audio-c:2.6.0-v2-8b-fp8` Number of worker pods to run in parallel for a single job. **Must be set to `1`.** ```yaml Example configuration theme={"system"} worker: config: generation: do_sample: true max_new_tokens: 256 repetition_penalty: 1 temperature: 0.7 top_k: 20 top_p: 0.8 max_video_frames: 32 model_variant: newton/c:2.5.1-8b-base parallelism: 1 ``` # Fine-Tuning Source: https://docs.archetypeai.app/core-concepts/customization/fine-tuning Train a forked instance of Newton on your own data set: the most powerful customization option, producing an org-private model adapted to your use case. **Fine-tuning** is a process by which you train one of Archetype's models with a data set specifically designed to optimize the model's performance for your use case. This is the most powerful customization option, producing a model specifically adapted to your sensor configuration or use case. The result of fine-tuning Newton is a forked instance of Newton configured for your use case, encrypted and access-controlled with visibility to your organization only. ## When to Use Fine-Tuning Fine-tuning is appropriate when: * You have a unique use case or bespoke sensor that can benefit from custom training on a proprietary dataset * You have a substantial labeled dataset (typically hundreds or thousands of examples) * [N-shot examples](/core-concepts/customization/n-shot-examples) aren't sufficient for your accuracy requirements * You need Newton to learn complex patterns specific to your domain ## What Fine-Tuning Produces The result of fine-tuning is a new instance of the base model with: * A custom model and inference configuration, tuned for your use case * Encryption and access controls limiting visibility to your organization only * Behavior adapted to your specific sensor configuration and use case based on the knowledge gained from fine tuning on your custom dataset. ## Labeled Examples Fine-tuning relies on high-quality examples to help steer a pre-trained instance of Newton to a new sensor configuration or use case. Each labeled example consists of an **input** and **output** pair in JSON or YAML format. This provides Newton the information required to understand that given *input X*, it should generate *output Y*. As Newton is a multimodal model, the input (X) can consist of one or more sensor types, with the output (Y) currently constrained to text output. ## Performing Fine-Tuning There are two ways to perform fine-tuning. The first is to use the [Fine-Tuning dashboard](/developer-console/fine-tuning/fine-tuning) in the Archetype Console. The second is to use the Fine-Tuning Service directly using its [API](/api-reference/fine-tuning). ## Best Practices **Quality over Quantity** A smaller set of high-quality, representative examples is more valuable than a large set of noisy or inconsistent examples. **Consistent Formatting** Ensure your output format is consistent across examples. Newton will learn the patterns in your labeled data. **Cover Edge Cases** Include examples that represent the full range of scenarios Newton will encounter, including edge cases and unusual inputs. ## Examples Find examples showing how to run a fine-tuning job using the Fine-Tuning Service on GitHub: * [Newton examples](https://github.com/archetypeai/archetypeai-fine-tuning-examples-newton-c) * [Omega examples](https://github.com/archetypeai/archetypeai-fine-tuning-examples-newton-omega) # Lens Customization Source: https://docs.archetypeai.app/core-concepts/customization/lens-customization (Archived) Legacy Lens runtime: customizing lens behavior through configuration. Lens customization is the simplest way to adapt Newton to your use case. It involves creating or modifying the parameters of a lens without having to provide any additional training data. At a high level, a lens lets you configure two key components of a lens: * Lens Parameters: such as the instruction and focus of the lens * Lens Data Streams: such as what sensors should be connected to a lens and where the lens output should be streamed. ## What You Can Configure ### Instruction and Focus The `instruction` and `focus` parameters in `lens_parameters` tell Newton what to look for and how to respond. These are analogous to system prompts in traditional LLMs, but are specifically designed for physical-world reasoning tasks. ```yaml theme={"system"} lens_parameters: instruction: | You are an intelligent traffic monitoring system. Monitor the traffic feed for the following activity or object. Output alerts in the format: [alert]{activity or object name}: {description} focus: All red pickup trucks driving east. ``` **Best practices for instructions:** * Be specific about the output format you expect * Provide context about the sensor placement or environment (e.g., "this camera is on 104th and main street looking west-to-east") * Clearly define what constitutes an alert or event worth reporting ### Input and Output Streams Configure how data flows into and out of the lens: Each lens can be customized to read and write from dedicated data streams. For example, a developer can stream data from a CSV file or video file into a lens and then stream the results back to an external application via a Server Sent Events stream. Available stream types are documented in the [Streams](/core-concepts/streams/data-streams) section. The example below demonstrates how a CSV file can be hooked up and streamed into a lens. ```yaml theme={"system"} input_streams: - stream_type: csv_file_reader stream_config: file_id: data.csv window_size: 1024 step_size: 1024 output_streams: - stream_type: server_sent_events_writer ``` Available stream types are documented in the [Streams](/core-concepts/streams/data-streams) section. ### Lens-Specific Parameters Different lenses expose different configuration options. Common parameters include: | Parameter | Description | Example | | - | - | - | | `buffer_size` | Number of samples to buffer before processing | `1024` | | `window_size` | Size of the sliding window for analysis | `1024` | | `step_size` | How far to advance the window between analyses | `512` | | `normalize_input` | Whether to normalize input data | `true` | Refer to the documentation for your specific lens to see all available parameters. ## When to Use Lens Customization Lens customization is appropriate when: * You're getting started and want to quickly test different configurations. * You want to change what Newton focuses on for your specific use case, such as real-time safety alerts in a factory. * Your use case or sensor data does not require extensive customization. ## Next Steps If lens customization alone isn't achieving the results you need, consider adding [N-Shot Examples](/core-concepts/customization/n-shot-examples) to guide Newton's behavior with labeled examples. # N-Shot Examples Source: https://docs.archetypeai.app/core-concepts/customization/n-shot-examples Classify time-series sensor data with the Newton Omega model by comparing new windows against a small labeled reference library — no training required. N-shot examples allow you to guide Newton's behavior by providing labeled examples at inference time. For the **Newton Omega** model, this means building a *reference library*: a small set of sensor windows you've labeled (one or a few per class), embedded once and kept on the client side. New data is classified by comparing its embedding against that library. **Key advantage:** N-shot classification works with very few examples (often just one per class), eliminating the need for retraining or fine-tuning when you have limited labeled data. ## How N-Shot Works Omega is an encoder: it turns a window of sensor readings into a fixed-size embedding vector via a single [Direct Query](/api-reference/query) call. Windows that represent similar physical behavior land close together in embedding space, which makes classification a nearest-neighbor problem: 1. **Build the reference library** — for each class (e.g. `healthy`, `broken`, `overheating`), embed a handful of labeled windows and store the vectors with their labels. 2. **Classify new data** — embed each incoming window the same way and take a majority vote among its *k* nearest library vectors (KNN). Both steps use the same request shape — a `data.numeric_array` event per channel, no prompt: ```python theme={"system"} body = { "model": "OmegaEncoder::omega_embeddings_1_4", "query": "", "normalize_input": False, "events": [ {"type": "data.numeric_array", "event_data": {"contents": [values]}} ], } ``` The library and the KNN vote live entirely in your client — a few lines of code with no server-side state to manage. The [quickstart's fault-detection example](/introduction/getting-started#3-detect-a-machine-fault-with-the-newton-omega-model) runs this full cycle on real bearing vibration data, reaching 95% accuracy on held-out windows from a library of just 8 labeled examples. ## Requirements for N-Shot Examples In the Direct Query workflow, windowing and normalization are your client's responsibility. Two of the rules below exist because of that: use **one window length** everywhere (mixing lengths invalidates KNN distances), and normalize with **one scaler fit on your reference pool** rather than per window. Skipping either produces a pipeline that runs without errors but classifies poorly. **Format consistency** Your reference examples must match the format of your incoming data: * Same sampling rate * Same variates (columns/channels) * Same data formats * Same window length (16–1024 timesteps; use one length for both the library and inference windows, since mixing lengths invalidates KNN distances) * No leaking of incorrect examples into other classes' reference data **Consistent normalization** Fit one scaler (per-channel mean/std) on your reference pool and apply it to every window — library and inference alike — calling the API with `normalize_input: false`. Per-window normalization (`normalize_input: true`) erases cross-window amplitude differences, which are often exactly the signal that separates classes. **Coverage** Provide at least one example for each possible state or class you want Newton to identify. **Quality** Examples should be clean, representative instances of each class, taken from contiguous recordings — the encoder reads a window as an ordered series, so windows that span gaps in the data produce misleading embeddings. Avoid noisy or ambiguous examples that could confuse the classification. ## When to Use N-Shot Examples N-shot examples are appropriate when: * You have limited labeled data (even just one example per class) * You need to classify states or detect patterns that Newton doesn't recognize by default * You want to customize behavior without the overhead of fine-tuning * Your classification needs may change frequently, as you can update the reference library without retraining ## Learn More The full library → KNN → evaluation cycle on real bearing data, in one runnable script. Teach your coding agent the embedding and KNN patterns, including a full-scale evaluation harness. Clean, split, and featurize time-series data into a leakage-free reference library. Request and response reference for the /query endpoint. ## Next Steps If n-shot examples aren't achieving the accuracy you need, or you have a large labeled dataset, consider [Fine-Tuning](/core-concepts/customization/fine-tuning) to train a custom Newton instance. # Overview Source: https://docs.archetypeai.app/core-concepts/customization/overview Three ways to customize Newton — prompting, n-shot examples, and fine-tuning — and how to choose based on your model family and labeled data. Newton is a foundation model for reasoning about and acting on the physical world. You can customize Newton in three primary ways, progressing from lightweight configuration to deeper adaptation using your own data. Not every method applies to every model family: **Newton Fusion** is steered with natural-language prompts, while **Newton Omega** is a time-series encoder that takes no prompt — its behavior is shaped entirely by the data you give it. | Level | Method | Applies to | Complexity | When to Use | Model Weight Changes | Training GPU Required | | - | - | - | - | - | - | - | | 1 | [Prompting](#prompting) | Fusion | Low | Adjusting behavior through instructions at query time | No | No | | 2 | [N-Shot Examples](#n-shot-examples) | Fusion & Omega | Medium | Guiding output with labeled examples at inference time | No | No | | 3 | [Fine-Tuning](#fine-tuning) | Fusion & Omega | High | Training a new model instance on your dataset | Yes | Yes | These customization options work together, letting you apply one or several to tailor Newton to your specific needs. Each approach varies in complexity and cost, so we suggest beginning with the lightest method available for your model and advancing only as your requirements evolve. ## Prompting *Applies to: Newton Fusion.* The Fusion model is steered at query time through the [Direct Query API](/api-reference/query) — no training, no configuration to manage: * **Instructions** — set the model's role and behavior with `instruction_prompt` (for example, *"You are a perception agent analyzing activity in front of a house. Reply in 2-3 sentences."*). * **Output format** — make the prompt the schema: ask for *"ONLY a JSON object: `{"activity": "...", "confidence": <0..1>}`"* and parse the response directly. * **Generation parameters** — control length and sampling with `max_new_tokens`, `temperature`, and related parameters. The [Developer Quickstart](/introduction/getting-started#2-analyze-a-video-with-the-newton-fusion-model) shows prompting on a live video example. Omega has no prompting tier: it receives raw sensor windows and returns embeddings, so customization starts at level 2. ## N-Shot Examples *Applies to: Newton Fusion & Newton Omega — through different mechanisms.* A small set of labeled examples steers the model without any training: * **Fusion** — include labeled input/output examples in the prompt itself so the model imitates them, the same way you set instructions and output format in [Prompting](#prompting). * **Omega** — build a labeled *reference library* of embedded sensor windows and classify new windows against it with a nearest-neighbor vote. See [N-Shot Examples](/core-concepts/customization/n-shot-examples); the [quickstart's fault-detection example](/introduction/getting-started#3-detect-a-machine-fault-with-the-newton-omega-model) reaches 95% accuracy from 8 labeled windows this way. ## Fine-Tuning *Applies to: Newton Fusion & Newton Omega.* When you have hundreds of labeled examples per class and need maximum accuracy, the [Fine-Tuning Service](/core-concepts/customization/fine-tuning) trains a dedicated checkpoint on your dataset. Fine-tuned checkpoints are selected by model ID at query time, so they drop into existing Direct Query and Batch workflows. ## Choosing the Right Approach **Start simple:** Begin with prompting (Fusion) or a small n-shot reference library (Omega), and consider fine-tuning only when you have sufficient data and need maximum accuracy. Choosing the right customization method based on your data: ```mermaid theme={"system"} %%{init: {'theme': 'base', 'themeVariables': {'fontSize': '14px'}}}%% flowchart TD Q1[Do you have labeled data?] Q1 -->|No| P[Prompting
Fusion: adjust instructions
& output format
] Q1 -->|Yes| Q2[How much labeled data?] Q2 -->|1-10 examples per class| NS[N-Shot Examples
Fusion: examples in the prompt
Omega: reference library + KNN
] Q2 -->|100+ examples per class| FT[Fine-Tuning] classDef questionBox fill:#4A6CF7,stroke:#4A6CF7,color:#fff classDef answerBox fill:#fff,stroke:#4A6CF7,color:#333 class Q1,Q2 questionBox class P,NS,FT answerBox ``` # Direct-to-Cloud Uploads Source: https://docs.archetypeai.app/core-concepts/files/cloud-upload Upload files up to 250GB with the direct-to-cloud workflow: presigned part URLs, checkpointing, and upload completion. While the basic file upload functions ([Upload File](/api-reference/files/upload) and [Upload Base64 File](/api-reference/files/upload-base64)) are limited to files of 255MB and less, you can upload files up to 250GB using the Direct-to-Cloud upload workflow. ## Step-by-Step The direct-to-cloud workflow begins by using the Files API to request a list of presigned URLs: one for each chunk of the file to be uploaded. With those in hand, your code then performs an HTTPS `PUT` for each chunk, sending it to the corresponding presigned URL. ### Initiate the Upload To start a direct-to-cloud upload, call the [Initiate Upload](/api-reference/files/initiate-upload) endpoint, providing the name of the file (`filename`), its MIME type (`file_type`), and its length in bytes (`num_bytes`). This returns an ID for the upload (`upload_id`) and an array of `parts`. Each part in the array specifies the part number (`part_number`), the presigned URL to which the part data should be uploaded (`url`), the offset into the file at which the part begins (`offset`), and the part's length in bytes (`length`). The timestamp at which the presigned URL expires is also provided (`expires_at`). ### Upload the parts Upload each part using HTTPS `PUT` to its presigned URL. Capture the each response header's `ETag`; this is the part's `part_token`. Optionally, you can **checkpoint** completed parts with the [Checkpoint Upload Parts](/api-reference/files/checkpoint-parts) endpoint. Doing this lets you skip them if the upload is paused and then later resumed. You can also optionally refresh any presigned URLs that are about to expire, using the [Generate Upload Part URLs](/api-reference/files/generate-part-urls) endpoint. ### Complete the Upload Complete the upload using the [Complete Upload](/api-reference/files/complete-upload) endpoint, submitting part numbers and corresponding `part_token` for each uploaded part. Parts which have been checkpointed do not need to be included in the part list when calling the Complete Upload endpoint. ## Aborting an Upload To abort an in-progress upload, use the [Abort Upload](/api-reference/files/abort-upload) endpoint, specifying the `upload_id` of the upload to abort. This releases the resources used on the server for the specified upload. ## Example For an example including the use of direct-to-cloud uploads, see our [batch processing example repository](https://github.com/archetypeai/archetypeai-batch-examples-volve), which includes a script that uploads files using the direct-to-cloud endpoints. # Introduction to the Files API Source: https://docs.archetypeai.app/core-concepts/files/files Upload and manage data on the Archetype platform: organization-scoped access, file IDs, upload paths, and supported formats. The Files API is used to upload data to the Archetype platform for tasks like data summarization or model fine tuning. ## Organization & Access All files are securely siloed within a developer's organization. Any file uploaded by a developer is visible and accessible by any developer within the same organization, however, they are not visible or available to anyone outside the developer’s organization. Any developer in the same organization can upload files, download files, query information about a file, or modify a file for any file within the same org. ## Files API The Files API supports the following: * Upload new files * Download existing files * List information across all files * Retrieve metadata across all existing files * Modify metadata for existing files * Delete existing files ## File IDs Each file uploaded to the Archetype platform is assigned a `file_id`. The `file_id` can be used to reference the file across the Archetype platform, such as passing that file to a Lens for analysis. The `file_id` is returned as the response when each file is uploaded, and is typically the base name of the uploaded file. ## Uploading Files There are two ways to upload files to the Newton platform: * Upload through the Files API endpoints ([Upload File](/api-reference/files/upload) and [Upload Base64 File](/api-reference/files/upload-base64)). These endpoints accept the file data and transfer it to the underlying AWS S3 data store automatically, but only accept files up to 512MB in size. * [Direct-to-cloud upload](/core-concepts/files/cloud-upload) lets you bypass the Newton platform, uploading the data directly to presigned URLs provided by AWS S3. Files uploaded this way may be up to 250GB. Lenses and the Lens API do not support files larger than 255MB, regardless of how they were uploaded. Files over 255MB will cause the Lens to fail. ## File Duplicates The Files API will automatically update any file to the latest file instance if two files are uploaded to the Archetype platform with the same file name. As files are shared across multiple developers in the same organization, developers should be cautious when uploading common file names such as “test.png” or “image.png” as these could overwrite files from other developers in the same organization. ## File Formats At this time, the current file formats are supported: * image/jpeg * image/png * image/base64 * video/mp4 * CSV * JSON * JSONL # Overview Source: https://docs.archetypeai.app/core-concepts/introduction/introduction The platform's core concepts: Newton models, Files, Batch Processing, Direct Query, and Customization, and how they fit together. The Archetype platform is organized around a set of core concepts that work together to power Physical AI applications. These components define how data enters the system, how Newton interprets it, and how insights flow back to your applications — synchronously through Direct Query, or at scale through Batch Processing. ## Core Components **Models** are the interpretive engine of the platform. Newton is a family of foundation models trained on physical sensor data: * **Newton Fusion** reasons over text, images, and video, and answers in natural language — describe a scene, evaluate an assembly step, or extract structured JSON from a dashboard. * **Newton Omega** encodes windows of time-series sensor readings into fixed-size embedding vectors, the building blocks for classification and anomaly detection on vibration, power, temperature, and other signals. See [Model Performance](/core-concepts/models/model-performance) for how the models are evaluated and how to measure them against your own workloads. **Files** offer a centralized way to upload and manage data on the Archetype platform. The Files API supports multiple formats — including images (JPEG, PNG), videos (MP4), CSVs, and JSON files. Standard uploads handle files up to 255MB, and the [direct-to-cloud workflow](/core-concepts/files/cloud-upload) supports files up to 250GB. Uploaded files are securely stored within your organization, making them accessible to your team while remaining private to others. Each file is assigned a unique **file ID** that you can reference throughout the platform — attaching a video to a query, feeding sensor logs to a batch job, or supplying training data for fine-tuning. **Batch Processing** runs processing jobs against many files at once. You submit a **job** against a named, versioned **pipeline** — via the [Batch Processing API](/api-reference/batch) or the Console's [Batch Manager](/developer-console/batch-manager) — and the platform manages the rest: parallel execution across workers, progress tracking at the task level, retries, and lifecycle events. Batch Processing is the counterpart to Direct Query for fleet-scale workloads: analyzing an archive of inspection videos, embedding months of sensor history, or running a fine-tuned model across your whole dataset. **Direct Query** ties these together for interactive use. A single synchronous `POST /query` call selects a model, attaches your data — uploaded files or inline data events — and returns the result in the same response. No sessions to manage, no infrastructure to stand up. It's the fastest way to go from a sensor reading or video clip to an answer, and the path the [Developer Quickstart](/introduction/getting-started) walks through. **Customization** adapts Newton to your domain. Steer model behavior with [n-shot examples](/core-concepts/customization/n-shot-examples) — labeled reference data supplied at query time — or train dedicated checkpoints on your own data with the [Fine-Tuning Service](/core-concepts/customization/fine-tuning). Run a model against your data in one synchronous call. Upload and manage data referenced across the platform. Run managed jobs against many files in parallel. How Newton models are evaluated and benchmarked. Train Newton checkpoints on your own data. Teach your coding agent to build on Newton. As a developer, the fastest way in is the [Developer Quickstart](/introduction/getting-started): create an API key, run your first Direct Query calls against the Fusion and Omega models, then scale up with Batch Processing and the Files API. Looking for Lenses and data streams? Those docs now live in the **Archive** section at the bottom of the navigation. # Lens Parameters Source: https://docs.archetypeai.app/core-concepts/lenses/lens-parameter (Archived) Legacy Lens runtime: reference for configuring lens parameters across lens types. A Lens is a software interface that allows developers to configure and interact with Newton. Lenses define how sensor data flows in and out of Newton and specify how Newton should interpret that data for a given use case. ## Parameter Categories Lens parameters fall into two categories: * **Basic Parameters** control core behavior like analysis focus, timing, and output format. These are the primary settings you'll adjust for your use case. * **Advanced Parameters** fine-tune performance characteristics like buffering, model replicas, and token limits. Default values work well for most applications. ## Activity Monitor Lens The Activity Monitor Lens analyzes camera data to identify activities, movements, or events within a scene. It detects human and object behaviors for applications like workflow monitoring, interaction tracking, and space usage analysis. ### Basic Parameters | Parameter | Description | Default | Notes | | - | - | - | - | | **instruction** | Defines the lens's role, objective, and output format | Answer the following question about the video: | Include role context, target behaviors, and response formatting | | **focus** | Steers what the model prioritizes in the sensor stream | Describe the video. | Narrow analysis to specific behaviors or conditions without retraining | | **temporal\_focus** | Controls how video frames are sampled over time | `5` | Temporal focus is defined as an integer in the number of seconds" This means over 5 seconds, 5 samples 5 frames are analyzed; higher values distribute frames across longer windows | #### Instruction Format Structure your instruction with these components: ``` [ROLE] You are a smart camera monitoring a conveyor belt in a manufacturing facility. [OBJECTIVE] Detect complete work stoppages that require human intervention. [OUTPUT FORMAT] ALERT: [reason in 5-7 words]. ``` ### Advanced Parameters | Parameter | Description | Default | Notes | | - | - | - | - | | **camera\_buffer\_size** | Number of frames kept in buffer before processing | 5 | Buffer size of 5 means model sees 5 frames per inference | | **camera\_buffer\_step\_size** | Step size for frame sampling | 5 | Step of 5 frames means next window starts 5 frames later | | **memory\_prompt\_buffer\_size** | Previous lens responses kept in prompt history | `0` | Keep default for best results | | **max\_new\_tokens** | Maximum tokens generated during inference | 512 | Keep default for best results | | **min\_replicas** | Minimum model replicas maintained | 1 | Keep default for best results | | **max\_replicas** | Maximum model replicas allowed | 1 | Keep default for best results | Full documentation and configuration examples for the Activity Monitor Lens ## Machine State Lens The Machine State Lens classifies operational states of machines using sensor measurements. It distinguishes between normal operation, stressed conditions, and anomaly or failure modes like overheating, mechanical wear, or misalignment. The lens supports one-shot and few-shot classification, allowing adaptation to new machines without retraining. ### Basic Parameters | Parameter | Description | Default | Notes | | - | - | - | - | | **input\_n\_shot** | Labeled CSV examples for each machine state | — | At least one example required per state; format must match incoming data | | **window\_size** | Number of rows analyzed together | `1024` | Smaller values (256) give more frequent predictions; larger values (2048) provide more context | | **step\_size** | Rows to advance between predictions | `1024` | Controls prediction frequency | ### CSV Configuration Parameters | Parameter | Description | Notes | | - | - | - | | **timestamp\_column** | Column containing time information | Used to order and label predictions | | **data\_columns** | Sensor columns to analyze | Update to match your CSV structure; maximum 4 variates supported | ### Advanced Parameters | Parameter | Description | Default | Notes | | - | - | - | - | | **buffer\_size** | Time points kept in buffer per variate | `1024` | — | | **min\_replicas** | Minimum model replicas maintained | 1 | Keep default for best results | | **max\_replicas** | Maximum model replicas allowed | 1 | Keep default for best results | ### KNN Configuration Parameters | Parameter | Description | Default | | - | - | - | | **n\_neighbors** | Number of neighbors for classification | `5` | | **metric** | Distance metric | `manhattan` | | **weights** | Weight function | `distance` | | **algorithm** | Algorithm for neighbor computation | `ball_tree` | | **normalize\_embeddings** | Whether to normalize embeddings | `false` | Full documentation and configuration examples for the Machine State Lens ## Related Resources Get started with your first lens Understanding how lenses work An Activity Monitor code example A Machine State code example Configure lenses in a no-code environment # Lens Processors Source: https://docs.archetypeai.app/core-concepts/lenses/lens-processors (Archived) Legacy Lens runtime: Lens processors reference. **Lens processors** are components within a lens's `model_pipeline` that define how data is processed. They are configured in the `lens_config` when registering or modifying a lens. ### **Types of Lens Processors** The following processors are available: | **Processor Name** | **Purpose** | **File Types** | | - | - | - | | `lens_camera_processor` | Processes camera/video data for activity monitoring | .mp4 videos | | `lens_timeseries_state_processor` | Processes time-series sensor data for machine state classification | .csv files | | `lens_sensor_logs_processor` | Processes sensor logs | .jsonl files | ### **Configuration Example** A processor can be selected by passing in the processor name key within the model pipeline in a lens configuration: ``` model_pipeline: - processor_name: lens_camera_processor ``` *Note: The `processor_config` can be skipped if it is empty (it will automatically be added by the backend).* ### **Processor Parameters** #### *Camera Processor* | Parameter | Description | Default | Notes | | - | - | - | - | | `camera_buffer_size` | Number of frames kept in buffer before processing | `5` | Buffer size of 5 means the model sees 5 frames per inference | | `camera_buffer_step_size` | Step size for frame sampling | `5` | Step of 5 frames means the next window starts 5 frames later | #### *Timeseries State Processor* | Parameter | Description | Default | Notes | | - | - | - | - | | `window_size` | Number of rows analyzed together | `1024` | Smaller values (256) give more frequent predictions; larger values (2048) provide more context | | `step_size` | Rows to advance between predictions | `1024` | Controls prediction frequency | | `input_n_shot` | Labeled CSV examples for each machine state | — | At least one example required per state; format must match incoming data | #### *Sensor Logs Processor* | Parameter | Description | Default | Notes | | - | - | - | - | | `sensor_buffer_size` | Number of sensor log entries kept in the buffer | `5` | The processor waits until the buffer contains this many entries before running inference. When the buffer exceeds this size, older entries are removed. | | `input_buffer_step_size` | Step size for sampling incoming sensor events | `1` | Controls how many incoming events are skipped between samples. A value of 1 means every event is buffered; a value of 3 means only every 3rd event is buffered. Must be greater than 0. | ### **Output Writers** A lens's `model_pipeline` ends with an **output writer** processor that decides where inference results are sent. Each lens uses exactly one output channel — outputs do not appear on both at once. | **Writer** | **Where outputs go** | **How to consume** | | - | - | - | | `server_sent_events_writer` | The session's Server-Sent Events stream | [`GET /lens/sessions/consumer/{session_id}`](/api-reference/lens/consumer) — used by the [official SDK](https://pypi.org/project/archetypeai/)'s `lens.create_sse_consumer()` | | Default mailbox writer | The session's WebSocket message mailbox | [`session.read`](/api-reference/lens/websocket-events#session-read) events on the session WebSocket | The Activity Monitor lens and most cookbook lenses use `server_sent_events_writer` for output. To check which writer a specific lens uses, inspect its `model_pipeline` via [`GET /lens/metadata`](/api-reference/lens/get-metadata). If you are reading from `session.read` but seeing `event_data: null` while [`GET /lens/sessions/metadata`](/api-reference/lens/get-sessions-metadata) reports non-zero `num_outputs`, the lens is writing to the SSE channel — switch to the [consumer endpoint](/api-reference/lens/consumer). ### **Best Practices** * Always destroy sessions when done to free resources * Use appropriate buffer sizes for your data type * Match input data format to processor requirements The documentation focuses more on **Lenses** as the primary interface, with processors being internal components. For troubleshooting, check session status via the API and ensure proper authentication. ### Additional Resources: * [**Lenses Overview**](https://docs.archetypeai.app/core-concepts/lenses/overview) * [**Lens Parameter Overview**](https://docs.archetypeai.app/core-concepts/lenses/lens-parameter). * [**Test Lens with Echo Processor**](https://docs.archetypeai.app/core-concepts/lenses/lens-templates/test-lens). # Activity Monitor Source: https://docs.archetypeai.app/core-concepts/lenses/lens-templates/activity-monitor (Archived) Legacy Lens runtime: the Activity Monitor starter lens template. The **Activity Monitor Lens** analyzes camera data to identify the activities, movements, or events occurring within a scene. It can detect a wide range of human or object behaviors, making it useful for applications such as monitoring workflows, tracking interactions, or observing space usage patterns. These insights help developers understand what is happening in an environment in real time and build systems that respond to meaningful activity. ## Configuration Example Here is an example configuration for the Activity Monitor lens: ```yaml theme={"system"} lens_name: Activity Monitor Lens lens_parameters: instruction: | You are an intelligent dashcam attached to the front of a car, looking for safety hazards to keep your driver safe. This includes reckless driving, people and also debris in the road such as car parts. ONLY when you see something hazardous or unsafe, respond with a notification in the following format {Alert: Description of safety hazard}. Do not include brackets in your message. Respond in less than 8 words. You are an expert. focus: safety equipment, vehicle movement, potential hazards temporal_focus: 5 model_parameters: model_version: Newton::c2_1_250408d4362cc9 ``` ## Running the Lens Try the Activity Monitor Lens in the command line, or through the no-code workbench with the following [example files](https://drive.google.com/drive/folders/1Mc0KIUmo3J1_CEGmeB_PI8Dnaey6OYBU?usp=drive_link). Step-by-step guide to running the Activity Monitor lens from the command line Step-by-step guide to running the Machine State Lens in a no-code environment ## Lens Inputs The Activity Monitor Lens supports analysis on one-or-more input camera streams from either a live camera or pre-recorded video. See the following data streams on how to hook up a real-time or pre-recorded video: Reads sensor data from a Video file. Reads real-time video data from an RTSP camera. ## Lens Parameters The Activity Monitor Lens contains a set of basic and advanced parameters to tune based on your specific use cases.\ \ **Basic Parameters** * **Instructions** define the Lens’s overall purpose and analysis behavior. They specify how the video should be interpreted, including: * The role and objective * Example situations or behaviors to analyze * Output logic and formatting * Here's a simple example:`[ROLE] You are a smart camera monitoring a conveyor belt in a manufacturing facility. [OBJECTIVE] Detect complete work stoppages that require human intervention. [OUTPUT FORMAT] ALERT: [reason in 5-7 words].` * **Focus** is a runtime control that steers what the model prioritizes within the sensor stream without requiring retraining. It allows you to narrow analysis to specific behaviors or conditions * **Temporal Focus** controls how video frames are sampled over time * **Default (**`temporal_focus = 5`**)**: Samples 5 frames over 5 seconds * **Higher values**: Distribute the same number of frames across longer time windows * **Example**: `temporal_focus = 5` samples 5 frames over 5 seconds. **Advanced Parameters** *(these are set to the best defaults)* * **Camera Buffer Size:** Number of frames to keep in the camera buffer before processing. e.g., buffer size = 5 → model sees 5 frames per inference * **Camera Buffer Step Size:** Step size for camera buffer frame sampling. e.g., step size = 5 frames → next window starts 5 frames later * **Memory Prompt Buffer Size:** How many previous lens responses kept in prompt history (keep default 0 or 10 for best results). * **Max New Tokens:** Max number of new tokens to generate during model inference. (keep at default for best results). * **Min Replicas:** Minimum number of model replicas to maintain for the Lens. (keep at default for best results). * **Max Replicas:** Max number of model replicas allowed for the Lens. (keep at default for best results). ## Lens Outputs Like all Lenses, the Activity Monitor Lens outputs a continuous stream of [Events](/core-concepts/streams/events/overview). A developer can connect one-or-more output streams from a lens to allow them to consume the events. # Machine State Lens Source: https://docs.archetypeai.app/core-concepts/lenses/lens-templates/machine-state (Archived) Legacy Lens runtime: the Machine State starter lens template. The **Machine State Lens** classifies the operational state of a machine using its sensor measurements. It can distinguish between normal operation, stressed conditions, and a variety of anomaly or failure modes (such as overheating, mechanical wear, or misalignment). These classifications support common engineering tasks like monitoring machine health, diagnosing issues, and optimizing performance. Developers can **configure the lens’s focus** by supplying a small number of labeled examples that represent the machine states they want to detect. Because abnormal-state data is often limited, the lens supports **one-shot and few-shot classification**, allowing it to generalize to new machines and new state categories without retraining or fine-tuning. This makes it suitable for deployments where labeled data is sparse but rapid adaptation is required. ## Configuration Example Here is an example configuration for the Machine State lens: ```yaml theme={"system"} lens_config: model_pipeline: - processor_name: lens_timeseries_state_processor processor_config: {} model_parameters: model_name: OmegaEncoder model_version: OmegaEncoder::omega_embeddings_01 normalize_input: true buffer_size: 1024 csv_configs: timestamp_column: timestamp data_columns: - a1 - a2 - a3 - a4 window_size: 1024 step_size: 1024 knn_configs: n_neighbors: 5 metric: manhattan weights: distance algorithm: ball_tree normalize_embeddings: false input_n_shot: healthy: healthy.csv broken: broken.csv min_replicas: 1 max_replicas: 1 input_streams: - stream_type: csv_file_reader stream_config: file_id: data.csv window_size: 1024 step_size: 1024 loop_recording: false output_format: "" output_streams: - stream_type: server_sent_events_writer ``` ## Running the Machine State Lens Try the Machine State Lens in the command line, or through the no-code workbench with the following [example files](https://drive.google.com/drive/folders/1IGD_0rLbJmyekJxO2OqpF5lgqdAqUklo?usp=drive_link). Step-by-step guide to running the Machine State lens from the command line Step-by-step guide to running the Machine State Lens in a no-code environment ## Lens Input The Lens input consists of time-varying sensor measurements representing physical parameters of a machine over time. These measurements can be provided either as a live stream from one or more sensors or as a prerecorded data file. ### General Requirements * The sampling rate should be fixed and constant over the lens session: monotonically increasing, fixed intervals. * Each variate should have the same sampling rate and sample time points. * The maximum supported number of variates (channels) is 4. * The data may contain NaNs or Infs. However the lens will output an INVALID\_STATE identifier at the corresponding time point(s). ### Using Pre-recorded .CSV files * The supported file format is CSV. * The CSV file should have a column for each variate. The variate (column) names should be specified in the header row. * If the number of variates in the CSV file exceeds the maximum supported, the user should specify a list of variate names to be used by the lens. If no list is provided, then the lens will default to the first four non-timestamp columns. * Each row of the CSV file should contain the data for one time point. * The sensor measurements should be formatted as plain-text numeric values. * The CSV file should contain a column called "timestamp" containing the timestamp for each time point. The supported timestamp formats are ISO 8601 and Unix. ### For Live Sensor Streams * One sensor stream per session is supported. This stream should contain the data for all sensor variates (up to 4). * The supported sensor measurement data types are floats and integers. * The maximum number of time points per sensor stream packet is 1024. The number of time points per sensor stream packet can vary over the course of a session. * Each sensor stream packet should contain the name of each variate as a key and the variate measurement data in an array as the associated value. * Each sensor stream packet should contain a key called "timestamp" and the timestamps of the packet data in an array as the associated value. The supported timestamp formats are ISO 8601 and Unix. ### Working with Data Streams Developers can stream generic timeseries data from pre-recorded CSV files into a Lens by connecting a *CSV File Reader* data connector to the **input data stream** of a Lens. See the following data streams on how to hook up your sensor data: Reads sensor data from a CSV file. ## Lens Parameters **Basic Parameters** * **Input N Shot Examples:** To produce meaningful state outputs for a specific use case, the Lens must be focused using labeled examples of sensor data for each state of interest. Each example is provided to the Lens as a CSV file. * The specifications of the focus data file should match that of the incoming data stream, i.e. the sampling rate, variates, data formats, and timestamp formats should be the same. * At least one example must be provided for each possible state of the machine. * **Window Size:** Number of rows analyzed together. (Default is 1024) * **Smaller values** (e.g., 256): more frequent predictions, less context * **Larger values** (e.g., 2048): fewer predictions, more context per prediction * **Step Size:** How many rows to move forward between predictions (Default is 1024). * **CSV Configuration:** Configuration settings for csv data processing. The goal is to make sure the formatting of your CSV file is compatible with the lens. * **Timestamp Column:** The CSV column containing time information. Used to order and label predictions. * **Data Columns:** Which sensor/data columns to analyze. Update this array to match your CSV structure. **Advanced Parameters** * **Buffer size:** Number of time points to keep in the buffer for each variate * **Max Replicas:** Maximum number of model replicas allowed for the Lens * **Min Replicas:** Minimum number of model replicas to maintain for the Lens ## Lens Outputs The output of the Lens will be a continuous timestamped stream of the identified machine state. Like all Lenses, the Machine State lens outputs a continuous stream of [Events](/core-concepts/streams/events/overview). A developer can connect one-or-more output streams from a Lens to allow them to consume the events. # Test Lens Source: https://docs.archetypeai.app/core-concepts/lenses/lens-templates/test-lens (Archived) Legacy Lens runtime: the Test Lens starter template. The **Test Lens** is a pass-through lens that repeats input data for testing and debugging data streaming pipelines. It uses the lens\_echo\_processor to buffer and echo data without modification, making it ideal for validating data flow through the system. Use the Test Lens when you need to: * Test data streaming pipelines (CSV, Kafka, SSE) * Validate that data correctly flows from input to output * Debug stream configurations without processing overhead * Test read timeout behavior with actual data buffering * Verify integration between different stream types * Test data flow end-to-end without transformation ## Echo Processor The Test Lens uses the **lens\_echo\_processor**, which implements a pass-through mechanism for data flow testing. ### Processor Behavior The Echo processor: * Stores incoming data in an internal queue * Returns data unchanged when read * Acts as a buffer between input and output streams * Tracks statistics inherited from LensProcessorBase ### Implementation Details ```python theme={"system"} @registry.register_lens_processor("lens_echo_processor") class LensEchoProcessor(LensProcessorBase): """A simple echo processor that repeats the input for testing and debugging.""" def __init__(self, config: config_dict.ConfigDict, redis_db_cls: RedisDatabase) -> None: super().__init__(config, redis_db_cls) self.data_queue = queue.Queue() async def read(self, timestamp: float = -1.0) -> list[dict]: timestamp = timestamp if timestamp >= 0.0 else time.time() self.num_reads += 1 self.last_read_timestamp = timestamp if self.data_queue.empty(): return None events = [] while not self.data_queue.empty(): events.append(self.data_queue.get()) return events async def write(self, event_data: dict, timestamp: float = -1.0) -> dict: timestamp = timestamp if timestamp >= 0.0 else time.time() self.data_queue.put(event_data) self.num_writes += 1 self.last_write_timestamp = timestamp return event_data ``` ## Creating a Test Lens To create a Test Lens, register it with the Echo processor: ```python theme={"system"} client = ArchetypeAI(api_key, api_endpoint=api_endpoint) lens_metadata = client.lens.register({ "lens_name": "Echo Lens", "lens_config": { "model_pipeline": [{"processor_name": "lens_echo_processor", "processor_config": {}}], "model_parameters": {}, }, }) # The lens_id is returned in the metadata lens_id = lens_metadata["lens_id"] ``` ## Use Cases The Test Lens is designed for testing data streaming and pipeline functionality: 1. **CSV File Streaming** - Test streaming CSV files through the lens to validate file reader integration. 2. **Kafka Integration Testing** - Test reading from and writing to Kafka topics through the lens. 3. **Server-Side Events (SSE) Testing** - Validate that Server-Side Events streams correctly output data. 4. **Read Timeout Testing** - Test blocking read behavior with configurable timeout parameters. 5. **Data Flow Validation** - Verify that data correctly flows from input streams to output streams without modification. ## Examples ### CSV Reader Test This example demonstrates streaming a CSV file through a Test lens: ```python theme={"system"} def test_fn(session_id: str, session_endpoint: str, client: ArchetypeAI, config: dict) -> list[str]: """Main function to run the logic of a custom lens session.""" test_errors = [] # Upload the test file response_data = client.files.local.upload(config.csv_filename) file_id = response_data["file_id"] # Attach a CSV file reader as input to the lens event = { "type": "input_stream.set", "event_data": { "stream_type": "csv_file_reader", "stream_config": { "file_id": file_id, "window_size": 1, "step_size": 1, "loop_recording": 0, } } } response = client.lens.sessions.process_event(session_id, event) return test_errors # Create the Echo lens client = ArchetypeAI(api_key, api_endpoint=api_endpoint) lens_metadata = client.lens.register({ "lens_name": "Echo Lens", "lens_config": { "model_pipeline": [{"processor_name": "lens_echo_processor", "processor_config": {}}], "model_parameters": {}, }, }) lens_id = lens_metadata["lens_id"] # Create and run the session test_errors = client.lens.create_and_run_session( lens_id, test_fn, auto_destroy=True, client=client, config=config) # Cleanup client.lens.delete(lens_id) ``` ### Kafka Reader Test This example demonstrates reading from Kafka topics through a Test Lens: ```python theme={"system"} def test_fn(session_id: str, session_endpoint: str, client: ArchetypeAI, config: dict) -> list[str]: """Main function to run the logic of a custom lens session.""" test_errors = [] test_topic = secrets.token_hex(8) # Generate a unique test topic # Attach a Kafka input stream num_events_to_send = 16 event = { "type": "input_stream.set", "event_data": { "stream_type": "kafka_reader", "stream_config": { "topic_ids": [test_topic], "max_messages_per_read": 1, } } } response = client.lens.sessions.process_event(session_id, event) # Send messages to the lens producer = client.kafka.create_producer(topic_ids=[test_topic]) for i in range(num_events_to_send): producer.send(topic_id=test_topic, value={"counter": i}) producer.flush() # Wait for lens to process messages time.sleep(10) # Query the session status event = {"type": "session.status"} response = client.lens.sessions.process_event(session_id, event) num_events_received = response["num_inputs"] if num_events_received != num_events_to_send: test_errors.append(f"Number of lens inputs ({num_events_received}) does not match expected ({num_events_to_send})!") return test_errors # Create the Echo lens client = ArchetypeAI(api_key, api_endpoint=api_endpoint) lens_metadata = client.lens.register({ "lens_name": "Echo Lens", "lens_config": { "model_pipeline": [{"processor_name": "lens_echo_processor", "processor_config": {}}], "model_parameters": {}, }, }) lens_id = lens_metadata["lens_id"] # Create and run the session test_errors = client.lens.create_and_run_session( lens_id, test_fn, auto_destroy=True, client=client, config=config) # Cleanup client.lens.delete(lens_id) ``` ### Kafka Reader/Writer Test This example demonstrates streaming data through a Test Lens from Kafka input to Kafka output: ```python theme={"system"} def test_fn(session_id: str, session_endpoint: str, client: ArchetypeAI, config: dict) -> list[str]: """Main function to run the logic of a custom lens session.""" test_errors = [] test_uid = secrets.token_hex(8) input_test_topic = f"input_{test_uid}" output_test_topic = f"output_{test_uid}" # Attach Kafka input stream event = { "type": "input_stream.set", "event_data": { "stream_type": "kafka_reader", "stream_config": { "topic_ids": [input_test_topic], "max_messages_per_read": 1, } } } response = client.lens.sessions.process_event(session_id, event) # Attach Kafka output stream event = { "type": "output_stream.set", "event_data": { "stream_type": "kafka_writer", "stream_config": { "topic_ids": [output_test_topic], "max_messages_per_read": 1, } } } response = client.lens.sessions.process_event(session_id, event) if response["type"] != "output_stream.set.response": test_errors.append("Failed to receive output_stream.set response!") return test_errors # Send messages to input topic producer = client.kafka.create_producer(topic_ids=[input_test_topic]) num_events_to_send = 16 for i in range(num_events_to_send): producer.send(topic_id=input_test_topic, value={"counter": i}) producer.flush() # Create consumer for output topic consumer = client.kafka.create_consumer( topic_id=output_test_topic, auto_offset_reset="earliest", consumer_timeout_ms=1000, ) got_message = False for message in consumer: got_message = True # Verify session processed messages event = {"type": "session.status"} response = client.lens.sessions.process_event(session_id, event) num_events_received = response["num_inputs"] if num_events_received != num_events_to_send: test_errors.append(f"Number of lens inputs ({num_events_received}) does not match expected ({num_events_to_send})!") return test_errors # Create the Echo lens client = ArchetypeAI(api_key, api_endpoint=api_endpoint) lens_metadata = client.lens.register({ "lens_name": "Echo Lens", "lens_config": { "model_pipeline": [{"processor_name": "lens_echo_processor", "processor_config": {}}], "model_parameters": {}, }, }) lens_id = lens_metadata["lens_id"] # Create and run the session test_errors = client.lens.create_and_run_session( lens_id, test_fn, auto_destroy=True, client=client, config=config) # Cleanup client.lens.delete(lens_id) ``` ### Server-Side Events Reader Test This example demonstrates reading Lens output via Server-Side Events (SSE): ```python theme={"system"} def test_fn(session_id: str, session_endpoint: str, client: ArchetypeAI, config: dict) -> list[str]: """Main function to run the logic of a custom lens session.""" test_errors = [] # Attach a basic event emitter as input event = { "type": "input_stream.set", "event_data": { "stream_type": "event_emitter", "stream_config": { "max_events": 10 } } } response = client.lens.sessions.process_event(session_id, event) # Attach SSE writer for output event = { "type": "output_stream.set", "event_data": { "stream_type": "server_sent_events_writer", "stream_config": { "max_messages_per_read": 1, } } } response = client.lens.sessions.process_event(session_id, event) if response["type"] != "output_stream.set.response": test_errors.append("Failed to receive output_stream.set response!") return test_errors # Connect to SSE stream api_endpoint = f"{config.api_endpoint}/lens/sessions/consumer/{session_id}" sse_event_stream = SSEClient(api_endpoint, headers={"Authorization": f"Bearer {config.api_key}"}) # Read events from SSE stream event_counter = 0 max_num_events = 10 for event in sse_event_stream: event_counter += 1 if event_counter >= max_num_events: break if event_counter == 0: test_errors.append("Failed to receive SSE events!") return test_errors # Create the Echo lens client = ArchetypeAI(api_key, api_endpoint=api_endpoint) lens_metadata = client.lens.register({ "lens_name": "Echo Lens", "lens_config": { "model_pipeline": [{"processor_name": "lens_echo_processor", "processor_config": {}}], "model_parameters": {}, }, }) lens_id = lens_metadata["lens_id"] # Create and run the session test_errors = client.lens.create_and_run_session( lens_id, test_fn, auto_destroy=True, client=client, config=config) # Cleanup client.lens.delete(lens_id) ``` ### Read Timeout Test This example demonstrates testing read timeout functionality with the Test Lens: ```python theme={"system"} def test_fn(session_id: str, session_endpoint: str, client: ArchetypeAI, config: dict) -> bool: """Main function to run the logic of a custom lens session.""" # Clear any pending messages client_id = "test_client" event_message = {"type": "session.read", "event_data": {"client_id": client_id}} max_read = 10 while max_read > 0: response = client.lens.sessions.process_event(session_id, event_message) max_read = 0 if response["event_data"] is None else max_read - 1 # Test with 2 second timeout event_message = { "type": "session.read", "event_data": {"read_timeout_sec": 2.0, "client_id": client_id} } timer_start = time.time() response = client.lens.sessions.process_event(session_id, event_message) timer_end = time.time() timer_delta = timer_end - timer_start assert response["type"] == "session.read.response" assert response["event_data"] is None assert timer_delta > 2.0 and timer_delta < 3.0 # Test with 5 second timeout event_message = { "type": "session.read", "event_data": {"read_timeout_sec": 5.0, "client_id": client_id} } timer_start = time.time() response = client.lens.sessions.process_event(session_id, event_message) timer_end = time.time() timer_delta = timer_end - timer_start assert response["type"] == "session.read.response" assert response["event_data"] is None assert timer_delta > 5.0 and timer_delta < 6.0 return True # Create the Echo lens client = ArchetypeAI(api_key, api_endpoint=api_endpoint) lens_metadata = client.lens.register({ "lens_name": "Echo Lens", "lens_config": { "model_pipeline": [{"processor_name": "lens_echo_processor", "processor_config": {}}], "model_parameters": {}, }, }) lens_id = lens_metadata["lens_id"] # Create and run the session success = client.lens.create_and_run_session( lens_id, test_fn, auto_destroy=True, client=client, config=config) # Cleanup client.lens.delete(lens_id) ``` ## Supported Input Streams The Test Lens can accept the following input stream types: * **csv\_file\_reader** - Read data from CSV files * **kafka\_reader** - Read messages from Kafka topics * **event\_emitter** - Generate test events ## Supported Output Streams The Test Lens can output to the following stream types: * **kafka\_writer** - Write messages to Kafka topics * **server\_sent\_events\_writer** - Stream events via SSE ## # What is a Lens? Source: https://docs.archetypeai.app/core-concepts/lenses/overview (Archived) Legacy Lens runtime: what Lenses are and how they interpret sensor data. A **Lens** is a software interface that allows developers to configure and interact with Newton. Lenses define how sensor data flows in and out of Newton and specify how Newton should interpret that data for a given use case. By configuring a Lens, developers can direct Newton's interpretive capabilities to solve domain-specific problems or tasks. A developer can customize a pre-made Lens or create one from scratch using natural language instructions. In essence, a Lens provides Newton with instructions on how to transform raw sensor data into a desired interpretation. Newton Lens Overview There are two main components that allow a developer to customize a lens for their unique use case: 1. [Lens Parameters](/core-concepts/lenses/overview#lens-parameters): how a developer can customize a lens, such as setting the instruction, focus, and temporal parameters 2. [Lens Data Streams](/core-concepts/lenses/overview#lens-data-streams): how a developer gets real-time or pre-recorded data in/out of a lens. In this version of the platform, developers can create new lenses only by adjusting key parameters of what we have called "starter lenses". Specifically, we have created two Starter Lenses: Monitors activity of humans or machines via live or pre-recorded video. Estimates the operational state or condition of a machine via physical sensors. ### Lens Parameters Each Lens is defined via a *lens config*, which defines the key parameters of the lens. Every Lens has a unique *lens ID* which allows a developer to pass a single reference across the Newton Platform to load, run, and modify specific lenses. A Lens config can be written as a YAML file and passed to the Archetype Platform via the Lens APIs. An example of the Activity Monitor Lens config is shown below: ```yaml theme={"system"} lens_name: Example Safety Lens lens_parameters: instruction: | You are an intelligent camera that monitors for safety violations. Monitor the incoming sensor data and output an alert if any unsafe behavior is observed. focus: safety equipment, hazards temporal_focus: 5 model_parameters: model_version: Newton::c2_1_250408d4362cc9 ``` For detailed inforation about lens parameters, visit the Activity Monitor Lens or Machine State Lens pages. ### Lens Data Streams Each Lens supports processing of real-time or pre-recorded sensor data using a set of general input and output data streams. All Lenses support three categories of data streams: * *Input Streams:* used for streaming sensor data into a lens (e.g. streaming a pre-recorded video into a lens) * *Output Streams:* used for streaming results out of a lens (e.g. sending inference results to an app via Server Side Events) * *Control Streams:* used for managing a lens session (e.g. starting/stopping/modifying a lens) ```mermaid theme={"system"} graph LR subgraph inputs [Developer Sensors] A(Sensor A) --> InputConnector1(Connector #1) B(Sensor B) --> InputConnector2(Connector #2) end subgraph core [Archetype Platform] InputConnector1 --> InputStreams InputConnector2 --> InputStreams InputStreams(Input Streams) --> Lens((Lens)) Lens --> OutputStreams(Output Streams) end subgraph outputs [Developer Applications] OutputStreams --> OutputConnector1(Output Connector #1) --> F(Alert System) OutputStreams --> OutputConnector2(Output Connector #2) --> G(Robotic Controller) OutputStreams --> OutputConnector3(Output Connector #3) --> H(Human Operator) end style InputConnector1 fill:#9EBBFF,stroke:none style InputConnector2 fill:#9EBBFF,stroke:none style InputStreams fill:#9EBBFF,stroke:none style Lens fill:#9EBBFF,stroke:none style OutputStreams fill:#9EBBFF,stroke:none style OutputConnector1 fill:#9EBBFF,stroke:none style OutputConnector2 fill:#9EBBFF,stroke:none style OutputConnector3 fill:#9EBBFF,stroke:none ``` Developers can stream either live or pre-recorded data in/out of Newton by attaching a specific stream to a Lens using a dedicated [data connector](/core-concepts/streams/data-connectors/). Common data connectors include input file readers, such as CSV file readers or video file readers, or live sensor readers, such as Kafka or RTSP cameras. The full list of data connectors can be found in the [Data Connectors](/core-concepts/streams/data-connectors/) page. # Improving Model Performance Source: https://docs.archetypeai.app/core-concepts/models/model-performance Recommendations to help improve the performance of Newton models for your use cases. Newton is a foundation model capable of addressing a wide variety of tasks in the physical space, offering strong general-purpose performance by default. However, you may be able to achieve better results for your use case by customizing the model. Customizing Newton involves systematically improving your results through adaptation, evaluation, and optimization. This guide provides recommendations to help get you started with this process. ## Prepare the Data Before you begin, you need to prepare the data for inference. The steps involved in data preparation vary depending on the type of data being analyzed and the method being used to analyze it. There are several ways in which data may need to be prepared prior to inference: * **Convert data:** Data needs to be converted into the required input format. * **Machine State Classification** tasks require CSV files. * **Activity Detection** tasks require JSONL files. * **Label data:** Make sure each column of CSV files is labeled. Ensure JSONL files have useful field names. * **Generate N-shot files (for Machine State Classification tasks):** Create N-shots that demonstrate the states you wish to detect. * **Impute missing data:** Sequences of missing values (NaNs) shorter than the window length should be imputed (for example, estimated using linear interpolation). Missing value sequences longer than the window length will return NaN outputs from the model. * **Normalize values:** The best normalization strategy is dependent on the data and should be chosen as part of your optimization policy. Possible strategies include per-window normalization, per-session (file) normalization, and global normalization, each per variate. Per-window normalization can be implemented using the platform configuration parameter `normalize_input = True`. If normalizing globally, the normalization coefficients should be determined using the N-shot/validation source data and then applied to the test data. * **Remove unneeded and unused variates:** Remove any variates whose values do not change across the dataset. Use only variates that are present in all files. ## Assess Newton The next step is to assess Newton's out-of-the-box performance for your target task. Start by testing the model on a representative sample of your real-world data. Experiment with different prompting styles, response formats, and instruction phrasing to observe how the model behaves under different conditions. Specific things to consider in this stage: * Instruction clarify and specificity * Output formatting requirements. For example, do you prompt for structured or conversational outputs? * Input length and context complexity * Edge cases and ambiguous examples The goal during this stage is to build an understanding of the model's baseline capabilities when analyzing your data, and what limitations you encounter. * Where does the model already perform well without customization? * What types of input produce inconsistent results? * Are failures caused by reasoning errors, unexpected formatting, factual errors, or missing context? * Does the model reliably follow instructions? ## Determine Success Criteria Whether the initial results are strong or otherwise, assembling a high-quality evaluation dataset is one of the most important investments you can make during the optimization process. Optimizing the model with data that doesn't adequately represent the kind of input it will see in real-world use doesn't result in a model tuned to work well for your data. A well-designed evaluation set provides a stable reference point for measuring improvements, comparing prompt strategies, and tracking regressions. Without a good evaluation set, any optimizations you make become subjective and difficult to validate. Before you start to optimize the model, it's critical to clearly define what "good performance" means for your use task or use case. Your success criteria should be quantitative whenever possible to ensure consistent and objective evaluation. Key metrics to consider include: * **Accuracy**: How often the model's predictions match the correct expected results (i.e., **ground truth**). * **Precision**: The quality and accuracy of the model's positive predictions. * **Recall**: The completeness of the model and its ability to find all actual positive instances within the data. * **False positive rate**: The percentage of time in which the model incorrectly claims negative instances in the data are positive. * **Exact match rate**: The percentage of time in which the model produces results that exactly match ground truth. Your choices for these metrics should be made based on the real-world impact of errors and should be aligned with your business and/or operational requirements. ## Develop Quality Evaluation Examples Once you've determined your success criteria, construct a set of examples that serve as a ground truth benchmark for model performance. These so-called "golden examples" should include representative inputs that reflect standard operational scenarios, as well as variations in conditions, edge cases, adversarial inputs, and noisy or incomplete data. Each example must be paired with high-quality expected outputs or ground truth labels that clearly define the correct model behavior for that case. The goal is often quality over quantity; a small but carefully-curated dataset is often more valuable than a large but low-quality dataset. High-quality evaluation sets prioritize coverage, correctness, and realism over volume, ensuring that even a limited number of examples can reliably expose model weaknesses and guide meaningful improvements. ## Prompt Tuning Many tasks can be significantly improved through better prompting alone. Prompt tuning should be approached systematically, leveraging the evaluation set of examples to measure the impact of different prompt versions. Things to consider when optimizing prompts: * **Provide sufficient context:** The model performs best when it has enough contextual information to properly interpret the input data and operational setting. Useful context may include detailed descriptions of sensors of instrumentation, operating conditions, data collection methodology, units and expected signal behavior, known system constraints, and relevant domain terminology. Providing rich contextual grounding often improves both reasoning quality and output consistency, especially for specialized industrial or scientific tasks. * **Clear task definition:** Prompts should explicitly describe the objective of the task, the expected type of response, the decision criteria, and any output constraints or assumptions the model should follow. Clearly defining what constitutes a successful answer helps to reduce ambiguity and improves consistency across different inputs and operating conditions. * **Include tips and guidance:** For complex inputs, it's often beneficial to guide the model toward the most relevant signals or patterns in the data. This may include highlighting important sensor correlations, expected temporal behaviors, anomaly signatures, operational thresholds, or known indicators of failure modes. Directing the model's attention toward meaningful aspects of the input can significantly improve reasoning accuracy and reduce irrelevant or inconsistent outputs. * **Optimize response format:** Structured outputs simplify downstream integration, validation, and automation by enforcing consistent response formats such as JSON schemas, tables, templates, or classification labels. However, overly restrictive output constraints can sometimes reduce the model's flexibility and reasoning capabilities. In some cases, letting the model provide intermediate reasoning or explanations before generating the final structured response can improve both accuracy and interpretability. ## Fine Tuning While prompt engineering can solve many use cases effectively, some applications require a deeper level of adaptation. [Fine-tuning](https://docs.archetypeai.app/core-concepts/customization/fine-tuning) lets Newton internalize task-specific behaviors, domain knowledge patterns, and output conventions directly into the model weights. Fine-tuning is the process of continuing training on a pre-trained foundation model using a curated dataset tailored to a specific task or domain. Instead of teaching the model from scratch, fine-tuning adapts the existing capabilities of Newton toward a narrower operational objective. The objective isn't to replace the foundation model's general intelligence, but to specialize and stabilize it for a particular operational environment. The challenge of fine-tuning comes from building a high-quality **fine-tuning dataset**. The quality of the dataset is usually the single largest factor determining fine-tuning success. A smaller, cleaner dataset often outperforms a much larger but noisy dataset. Key principles when designing your fine-tuning dataset: * **Variety over quantity:** Choosing a smaller dataset with diverse and representative examples is usually more valuable than a very large dataset with repetitive patterns. Diversity helps the model generalize better to unseen inputs. * **Coverage over all cases:** Training data should include the full range of expected scenarios, including edge cases, ambiguous inputs, failures, and uncommon situations. Be sure not to include only the most frequent examples. * **Balanced distribution:** Avoid over-representation of certain classes, formats, or workflows. Providing a balanced dataset prevents the model from becoming biased toward dominant patterns, and improves overall reliability. * **Build iteratively:** Fine-tuning datasets should evolve over time. As new failure nodes and production issues are discovered, additional examples should be added to the fine-tuning dataset to continuously improve model performance. # CSV File Reader Source: https://docs.archetypeai.app/core-concepts/streams/data-connectors/readers/csv-reader (Archived) Legacy Lens runtime: stream CSV timeseries data into a lens with the CSV File Reader connector. Developers can stream generic timeseries data from pre-recorded CSV files into a Lens by connecting a *CSV File Reader* data connector to the input data stream of a Lens. Prior to streaming CSV data to a lens, a developer should first **upload their CSV file to the Archetype platform** using the [Files API](/core-concepts/files/files). Upon uploading their CSV file, the developer will receive a **file\_id** that identifies that file throughout the Newton Platform. For example, the bash command below demonstrates how to upload a local CSV file from your terminal to the Archetype platform using the [Files API](/core-concepts/files/files). ```bash theme={"system"} curl https://api.u1.archetypeai.app/v0.5/files \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: multipart/form-data" \ -F file="@my_csv_data.csv" ``` Upon successful upload, you will receive a JSON response similar to: ```bash theme={"system"} { "is_valid":true "file_id":"my_csv_data.csv" "file_uid":"25081907c598752e7e71ef" } ``` Like all data stream connectors, the CSV file reader can be identified and configured via the following *stream type* and *stream config*: ``` stream_type: csv_file_reader stream_config: file_id: "your_csv_file_id.csv" ``` This can be passed to Newton as an [event](/core-concepts/streams/events/overview): ``` event: type: input_stream.set event_data: stream_type: csv_file_reader stream_config: file_id: "your_csv_file_id.csv" ``` # Parameters You can pass the following parameters to the CSV File Reader via the stream\_config. | Parameter | Description | Required | | - | - | - | | `file_id` | The file\_id of the CSV file you wish to pass to the CSV File Reader. The file\_id should correspond to a valid file you've uploaded via the files API. | Yes | # JSONL File Reader Source: https://docs.archetypeai.app/core-concepts/streams/data-connectors/readers/jsonl-file-reader (Archived) Legacy Lens runtime: stream JSONL data into a lens with the JSONL File Reader connector. Developers can stream generic JSONL data from pre-recorded JSONL files into a Lens by connecting a *JSONL File Reader* data connector to the input data stream of a Lens. Prior to streaming JSONL data to a lens, a developer should first **upload their JSONL file to the Archetype platform** using the [Files API](/core-concepts/files/files). Upon uploading their JSONL file, the developer will receive a **file\_id** that identifies that file throughout the Newton Platform. For example, the bash command below demonstrates how to upload a local JSONL file from your terminal to the Archetype platform using the [Files API](/core-concepts/files/files). ```bash theme={"system"} curl https://api.u1.archetypeai.app/v0.5/files \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: multipart/form-data" \ -F file="@my_data.jsonl" ``` Upon successful upload, you will receive a JSON response similar to: ```bash theme={"system"} { "is_valid":true "file_id":"my_data.jsonl" "file_uid":"25081907c598752e7e71ef" } ``` Like all data stream connectors, the JSONL file reader can be identified and configured via the following *stream type* and *stream config*: ``` stream_type: jsonl_file_reader stream_config: file_id: "your_file_id.jsonl" ``` This can be passed to Newton as an [event](/core-concepts/streams/events/overview): ``` event: type: input_stream.set event_data: stream_type: jsonl_file_reader stream_config: file_id: "your_file_id.jsonl" ``` # Parameters You can pass the following parameters to the JSON File Reader via the stream\_config. | Parameter | Description | Required | | - | - | - | | `file_id` | The file\_id of the JSONL file you wish to pass to the JSONL File Reader. The file\_id should correspond to a valid file you've uploaded via the files API. | Yes | # RTSP Video Reader Source: https://docs.archetypeai.app/core-concepts/streams/data-connectors/readers/rtsp-video-reader (Archived) Legacy Lens runtime: stream live RTSP camera video into a lens. Developers can stream live camera into a Lens by connecting a *RTSP Video Reader* data connector to the input data stream of a Lens. Prior to streaming live video to a lens, a developer should first setup their RTSP camera and be aware of the RTSP URL needed to access the camera. This can be done via the RTSP third-party software and not via the Archetype platform. Like all data stream connectors, the RTSP Video Reader can be identified and configured via the following *stream type* and *stream config*: ``` stream_type: rtsp_video_reader stream_config: rtsp_url: "your_rtsp_camera_url" ``` This can be passed to Newton as an [event](/core-concepts/streams/events/overview): ``` event: type: input_stream.set event_data: stream_type: rtsp_video_reader stream_config: rtsp_url: "your_rtsp_camera_url" ``` # Parameters You can pass the following parameters to the RTSP Video Reader via the stream\_config. | Parameter | Description | Required | | - | - | - | | `rtsp_url` | The URL of the RTSP stream. | Yes | | `target_image_size` | An array containing the width and height in pixels that the video should be resized to, which can help reduce the amount of data streamed through the platform and increase inference speed. Skipping this parameter will result in the default video size being used. | No | | `target_frame_rate_hz` | The speed in frames per second at which the video stream should be read. Skipping this parameter will result in the default video sample rate being used. | No | # Video File Reader Source: https://docs.archetypeai.app/core-concepts/streams/data-connectors/readers/video-reader (Archived) Legacy Lens runtime: stream pre-recorded video into a lens with the Video File Reader connector. Developers can stream pre-recorded video into a Lens by connecting a *Video File Reader* data connector to the input data stream of a Lens. Prior to streaming video to a lens, a developer should first **upload their video to the Archetype platform** using the [Files API](/core-concepts/files/files). Upon uploading their video, the developer will receive a **file\_id** that identifies that file throughout the Newton Platform. For example, the bash command below demonstrates how to upload a local MP4 video from your terminal to the Newton Platform using the [Files API](/core-concepts/files/files). ```bash theme={"system"} curl https://api.u1.archetypeai.app/v0.5/files \ -H "Authorization: Bearer $ATAI_API_KEY" \ -H "Content-Type: multipart/form-data" \ -F file="@my_video.mp4" ``` Upon successful upload, you will receive a JSON response similar to: ```bash theme={"system"} { "is_valid":true "file_id":"my_video.mp4" "file_uid":"2508191b9ce198595febe4" } ``` Like all data stream connectors, the video file reader can be identified and configured via the following *stream type* and *stream config*: ``` stream_type: video_file_reader stream_config: file_id: "your_video_file_id.mp4" ``` This can be passed to Newton as an [event](/core-concepts/streams/events/overview): ``` event: type: input_stream.set event_data: stream_type: video_file_reader stream_config: file_id: "your_video_file_id.mp4" ``` # Parameters You can pass the following parameters to the Video File Reader via the stream\_config. | Parameter | Description | Required | | - | - | - | | `file_id` | The file\_id of the video you wish to pass to the Video File Reader. The file\_id should correspond to a valid file you've uploaded via the files API. | Yes | # SSE Writer Source: https://docs.archetypeai.app/core-concepts/streams/data-connectors/writers/sse-writer (Archived) Legacy Lens runtime: stream lens output over Server-Sent Events with the SSE Writer connector. Developers can write events to an outgoing SSE stream from a Lens by connecting an *SSE Writer* data connector to the output data stream of a Lens. The SSE Writer writes events to an outgoing Server-Sent Events (SSE) stream that can be consumed by any HTTP client that supports event streams, making it ideal for web dashboards, monitoring applications, and real-time analytics. Like all data stream connectors, the SSE writer can be identified and configured via the following *stream type* and *stream config*: ``` stream_type: sse_writer stream_config: {} ``` As the stream\_config is empty, it can be skipped. This can be passed to Newton as an [event](/core-concepts/streams/events/overview): ``` event: type: output_stream.set event_data: stream_type: server_sent_events_writer ``` # Data Streams Source: https://docs.archetypeai.app/core-concepts/streams/data-streams (Archived) Legacy Lens runtime: input, output, and control streams for moving data in and out of a lens. The Archetype platform is built around the concept of [Lenses](/core-concepts/lenses/overview), which are software interfaces for building and interacting with real world through sensors and actuators. Developers can stream data in and out of a Lens by attaching one or more data streams to each Lens. ```mermaid theme={"system"} graph LR subgraph inputs [Developer Sensors] A(Sensor A) --> InputConnector1(Connector #1) B(Sensor B) --> InputConnector2(Connector #2) end subgraph core [Archetype Platform] InputConnector1 --> InputStreams InputConnector2 --> InputStreams InputStreams(Input Streams) --> Lens((Lens)) Lens --> OutputStreams(Output Streams) end subgraph outputs [Developer Applications] OutputStreams --> OutputConnector1(Output Connector #1) --> F(Alert System) OutputStreams --> OutputConnector2(Output Connector #2) --> G(Robotic Controller) OutputStreams --> OutputConnector3(Output Connector #3) --> H(Human Operator) end style InputConnector1 fill:#2D5FDD,stroke:none,color:#fff style InputConnector2 fill:#2D5FDD,stroke:none,color:#fff style InputStreams fill:#2D5FDD,stroke:none,color:#fff style Lens fill:#2D5FDD,stroke:none,color:#fff style OutputStreams fill:#2D5FDD,stroke:none,color:#fff style OutputConnector1 fill:#2D5FDD,stroke:none,color:#fff style OutputConnector2 fill:#2D5FDD,stroke:none,color:#fff style OutputConnector3 fill:#2D5FDD,stroke:none,color:#fff ``` This video file reader can be configured as the input stream to a Lens by sending the following [event](/core-concepts/streams/events/overview) to an active Lens: ```yaml theme={"system"} event: type: input_stream.set event_data: stream_type: video_file_reader stream_config: file_id: "your_video_file_id.mp4" ``` # Data Events Source: https://docs.archetypeai.app/core-concepts/streams/events/data-events (Archived) Data event formats for packaging sensor data (text, JSON, base64 image, numeric array); the payload shapes are also used by the Direct Query API's events parameter. Data events allow a developer to package and combine multimodal sensor so it can be used as real-time inputs to an active lens or to build offline datasets for fine-tuning and evaluating models. Each data event has a type (e.g. data.text, data.json, data.base64\_img) that identifies the category of multimodal data, with the event\_data containing the associated payload (e.g. the text data, the json data, the base64 image). The current data events are: * [data.text](#data-text) * [data.json](#data-json) * [data.base64\_img](#data-base64_img) ## data.text The **data.text** event can be used to embed textual data within an event message as part of a multimodal message. ### data.text parameters The data.text key identifies that this event is a text event. Contains the text payload and associated metadata. The contents key contains the main body of the text data. ### data.text example ```yaml theme={"system"} type: data.text event_data: contents: "Far out in the uncharted backwaters of the unfashionable end of the Western Spiral arm of the Galaxy lies a small unregarded yellow sun." ``` ## data.json The **data.json** event can be used to embed a base64 encoded image directly into an event message. The **data.json** event is used to send images directly as input to a lens. ### data.json parameters The data.json key identifies that this event is a json dictonary. Contains the JSON payload. ### data.json example ```yaml theme={"system"} type: data.json event_data: some_key: some_value another_key: another_value ``` ## data.base64\_img The **data.base64\_img** event can be used to embed a base64 encoded image directly into an event message. The **data.base64\_img** event is used to send images directly as input to a lens. ### data.base64\_img parameters The data.base64\_img key identifies that this event is a base64 image event. Contains the image payload and associated metadata. The base64 encoded image as a byte string. ### data.base64\_img example ```yaml theme={"system"} type: data.base64_img event_data: contents: iVBORw0KGgoAAAANSUhEUgAAAAUAAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg== ``` # Events Source: https://docs.archetypeai.app/core-concepts/streams/events/overview (Archived) Legacy Lens runtime: the events protocol for sending data and control messages in and out of a lens. The Archetype platform is built around the concept of [Lenses](/core-concepts/lenses/overview). Developers can stream data in and out of a lens by attaching one or more [data streams](/core-concepts/streams/data-streams) to each lens. ```mermaid theme={"system"} graph LR subgraph inputs [Developer Sensors] A(Sensor A) --> InputConnector1(Connector #1) B(Sensor B) --> InputConnector2(Connector #2) end subgraph core [Archetype Platform] InputConnector1 --> InputStreams InputConnector2 --> InputStreams InputStreams(Input Streams) --> Lens((Lens)) Lens --> OutputStreams(Output Streams) end subgraph outputs [Developer Applications] OutputStreams --> OutputConnector1(Output Connector #1) --> F(Alert System) OutputStreams --> OutputConnector2(Output Connector #2) --> G(Robotic Controller) OutputStreams --> OutputConnector3(Output Connector #3) --> H(Human Operator) end style InputConnector1 fill:#9EBBFF,stroke:none style InputConnector2 fill:#9EBBFF,stroke:none style InputStreams fill:#9EBBFF,stroke:none style Lens fill:#9EBBFF,stroke:none style OutputStreams fill:#9EBBFF,stroke:none style OutputConnector1 fill:#9EBBFF,stroke:none style OutputConnector2 fill:#9EBBFF,stroke:none style OutputConnector3 fill:#9EBBFF,stroke:none ``` The Archetype platform uses a unified **events protocol** to send data in and out of a Lens and to control and query various aspects of the platform. The events protocol is built on a JSON structure, with every event being identified by a **type** key, paired with a corresponding **event\_data** key. # Event Types and Event Data Every event consists of two fields: 1. **type**: a string to identify the event type 2. **event\_data**: a dictonary containing dedicated data for the corresponding type For example, a developer can query the status of an active lens session using the following event: ```yaml theme={"system"} type: session.status event_data: {} ``` # Event Types Common event types are as follows. Session Events allow a developer to query and control the state of an active lens session. Data Events allow a developer to specify and package multimodal sensor data sent in/out of a lens. Input Stream Events allow a developer to connect or disconnect specific input streams to/from a lens. Output Stream Events allow a developer to connect or disconnect specific output streams to/from a lens. # Session Events Source: https://docs.archetypeai.app/core-concepts/streams/events/session-events (Archived) Legacy Lens runtime: session events for querying, validating, and controlling active lens sessions. ## Session Lifecycle Sessions progress through these states: ```mermaid theme={"system"} stateDiagram-v2 [*] --> SESSION_STATUS_REGISTERED: create_session() SESSION_STATUS_REGISTERED --> SESSION_STATUS_STARTING: session.start SESSION_STATUS_STARTING --> SESSION_STATUS_RUNNING: Initialization complete SESSION_STATUS_RUNNING --> SESSION_STATUS_KILLED: session.destroy SESSION_STATUS_STARTING --> SESSION_STATUS_KILLED: session.destroy SESSION_STATUS_KILLED --> [*] ``` *** ## Session Event Types | Event Type | Pattern | Description | | - | - | - | | `session.status` | Query | Retrieve current session status and metadata | | `session.validate` | Request-Response | Validate session health and configuration | | `session.get` | Request-Response | Retrieve specific session information | | `session.modify` | Request-Response | Modify session configuration | | `session.update` | Request-Response | Update session state | | `session.read` | Direct | Read pending events from session queue | | `session.destroy` | Request-Response | Terminate session and free resources | *** ## session.status Query the current status and metadata of an active session. ```yaml Request theme={"system"} type: session.status ``` ```json Response theme={"system"} { "session_id": "lsn-...", "lens_id": "lens_...", "org_id": "org_...", "session_status": "SESSION_STATUS_RUNNING", "session_endpoint": "https://...", "reverse_proxy_endpoint": "https://...", "session_runner": "node_...", "node_tag": "default", "registration_timestamp": 1234567890.0, "last_event_timestamp": 1234567890.0, "last_update_timestamp": 1234567890.0, "num_active_connections": 2, "num_updates": 15, "num_inputs": 42, "num_outputs": 38, "num_events": 120, "session_ttl_sec": 600 } ``` *** ## session.validate Validate that a session is properly configured and healthy. ```yaml Request theme={"system"} type: session.validate event_data: {} ``` ```json Response theme={"system"} { "type": "session.validate.response", // Response content is lens-specific } ``` *** ## session.get Retrieve specific session configuration or state information. ```yaml Request theme={"system"} type: session.get event_data: # Parameters are lens-specific ``` ```json Response theme={"system"} { "type": "session.get.response", // Response content is lens-specific } ``` *** ## session.modify Modify session configuration or parameters while the session is running. ```yaml Request theme={"system"} type: session.modify event_data: # Parameters are lens-specific ``` ```json Response theme={"system"} { "type": "session.modify.response", // Response content is lens-specific } ``` *** ## session.update Update session state or trigger session processing. ```yaml Request theme={"system"} type: session.update event_data: # Parameters are lens-specific ``` ```json Response theme={"system"} { "type": "session.update.response", // Response content is lens-specific } ``` *** ## session.read Read pending events from the session's event queue. Unlike other session events, session.read returns immediately without waiting for a response. ```yaml Request theme={"system"} type: session.read event_data: # Parameters are lens-specific ``` ```json Response theme={"system"} { // Returns immediately with available events } ``` *** ## session.destroy Terminate an active session and free its allocated resources. Only affects sessions in `SESSION_STATUS_STARTING` or `SESSION_STATUS_RUNNING` status. ```yaml Request theme={"system"} type: session.destroy event_data: {} ``` ```json Response theme={"system"} { "type": "session.destroy.response", // Response confirms destruction } ``` *** ## Error Responses | Error Type | Message | Cause | | - | - | - | | `error` | `"Unknown session id: {session_id}"` | Session not found | | `error` | `"Failed to fetch session_runner!"` | No node assigned to session | ```json Session Not Found theme={"system"} { "type": "error", "message": "Unknown session id: lsn-abc123" } ``` ```json No Session Runner theme={"system"} { "type": "error", "message": "Failed to fetch session_runner!" } ``` # SSE Streaming Source: https://docs.archetypeai.app/core-concepts/streams/events/sse-streaming (Archived) Legacy Lens runtime: real-time SSE streaming of lens session output. ## SSE Stream Flow ```mermaid theme={"system"} sequenceDiagram participant Client participant API participant Session Client->>API: Open SSE stream (reader_id) API->>Session: Register reader API->>Client: sse.stream.start loop While session active Session->>API: New event available API->>Client: Event data end loop No events (every 5s) API->>Client: sse.stream.heartbeat end Note over API,Client: After timeout or session killed API->>Client: sse.stream.end API->>Session: Unregister reader ``` *** ## SSE Stream Characteristics | Feature | Behavior | | - | - | | **Reader Tracking** | Each reader gets unique `reader_id` for independent position tracking | | **Heartbeats** | Sent every 5 seconds when no data available | | **Auto-Timeout** | Stream closes automatically after extended inactivity | | **Session TTL** | Default 10 minutes (600 seconds) | | **Event Format** | Standard SSE: `data: {json}\n\n` | *** ## SSE Lifecycle Events ### sse.stream.start Sent when SSE stream connection opens. ```json sse.stream.start theme={"system"} { "type": "sse.stream.start", "event_data": { "session_id": "lsn-abc123", "reader_id": "reader_xyz" } } ``` *** ### sse.stream.heartbeat Sent periodically when no data events are available. ```json sse.stream.heartbeat theme={"system"} { "type": "sse.stream.heartbeat", "event_data": { "session_id": "lsn-abc123", "session_status": "SESSION_STATUS_RUNNING", "num_messages": 42, "num_bytes": 15234, "message_timeout": 2.5, "reader_id": "reader_xyz" } } ``` *** ### sse.stream.end Sent when stream closes (timeout or session termination). ```json Normal Close theme={"system"} { "type": "sse.stream.end", "event_data": { "session_id": "lsn-abc123", "session_status": "SESSION_STATUS_RUNNING", "num_messages": 100, "num_bytes": 45678, "message_timeout": 58.2, "reader_id": "reader_xyz" } } ``` ```json Session Killed theme={"system"} { "type": "sse.stream.end", "event_data": { "session_id": "lsn-abc123", "reader_id": "reader_xyz", "session_status": "SESSION_STATUS_KILLED", "warning": "Session status is : SESSION_STATUS_KILLED" } } ``` *** ## SSE Reader Statistics Each reader tracks the following metrics: | Metric | Description | | - | - | | `num_messages` | Total messages sent to this reader | | `num_bytes` | Total bytes transmitted | | `num_errors` | Transmission errors encountered | | `stream_send_delay_sec` | 95th percentile send latency | | `sse_start_time` | Stream start timestamp | | `sse_end_time` | Stream end timestamp | | `sse_run_time` | Total stream duration | # Stream Events Source: https://docs.archetypeai.app/core-concepts/streams/events/stream-events (Archived) Legacy Lens runtime: input/output stream configuration events for lens sessions. ## Input Streams An input stream is used to configure what input data gets connected to Newton and how it gets processed and interpreted via a specific lens. Newton works both with files and continuous streams of sensor data from the physical world, including videos, live camera streams, timeseries data, among other sensors. A developer can hook up their custom sensor or pre-recorded files to an input data stream using a [data connector](/core-concepts/streams/data-connectors). Common input data connectors are file readers, such as video and CSV readers, and streaming protocols, such as REST, Websockets, and Kafka. The full list of data connectors can be found in [Data Connectors](/core-concepts/streams/data-connectors). ## Output Streams An output stream is used to configure what data gets streamed out of Newton and how that data first gets processed and interpreted via a lens. A developer can hook up the output of Newton to their custom app or downstream listener by connecting an output stream to an external protocol using a [data Connector](/core-concepts/streams/data-connectors). Common output data connectors are streaming protocols, such as Server Side Events, REST, Websockets, and Kafka. The full list of data connectors can be found in [Data Connectors](/core-concepts/streams/data-connectors). For API details on stream event types and usage, see [Stream Event Types](/core-concepts/streams/events/stream-events). # Account Management Source: https://docs.archetypeai.app/developer-console/account-management View your account information and create and manage your API keys. ## The Account Panel At the bottom-left corner of every page in the Developer Console, you'll find the account menu. This menu is tucked behind your account name; click your name to open and close the menu. The menu contains the following options: * **Profile & API Keys:** Access your account details and manage your API keys. This option is only present if your account's role supports managing your API keys (that is, your role is either **Developer** or **Admin**). * **Leave Feedback:** Lets you send feedback to Archetype. * **Light Mode** or **Dark Mode:** Lets you toggle between light and dark background presentations. The mode defaults to your device's configured mode. * **Sign Out:** Signs you out of the Developer Console. If you're an organization administrator, an option will also appear in this menu to administer the organization. ## Accessing Your Profile To access your profile, find the **Profile & API Keys** option in the account menu: User menu with Profile & API Keys option
highlighted This opens your **Profile** page. The Profile page has two sections: **Details**, which lists details about your user account, and **API Keys**, where you can view, filter, manage, and search your existing API keys, as well as create new ones. The main user profile page ## Managing API Keys ### Creating an API Key Everything you build on the Archetype Platform authenticates using an API key, and the Developer Console is where you create them. To do so, start by signing in to the **[Developer Console](https://console.u1.archetypeai.app/)**, then open the **[Profile & API Keys](https://console.u1.archetypeai.app/profile/api-keys)** page using the option in the lower-left corner of the window. Don't have Developer Console access yet? [Request a free trial](https://forms.gle/yTu6xp7CCEvAYLqB9) to get started. 1. Click the **+ Create Key** button at the top-right corner of the **API Keys** section of the page. This opens the **Create API Key** panel: Create an API
   key 2. Enter a name for your new API key and click the **Create Key** button to create the new API key. A new modal will appear showing you information about the new API key: Your API Key
   modal 3. Copy the **secret key**, which starts with `sk_`. This is the value your code sends as **`ATAI_API_KEY`**. Treat the secret key like a password: store it in an environment variable or a `.env` file, never in source control. See [Environment Variables](/libraries/environment-variables) for setup details, then head to the [Developer Quickstart](/introduction/getting-started) to run your first queries using your new API key. ### Revoking an API Key If you are no longer using a particular API key, you should revoke it so that it can no longer be used to access your account and its data. To revoke an API key, mouse over the API key you want to revoke. This causes a revoke button () to appear at the right-hand side of the API key's row in the list. Click the revoke button to open the **Revoke API Key** panel: The Revoke API Key modal Review the displayed information about the API key. If you're *certain* you want to revoke the API key, click the **Revoke Key** button. Once you revoke an API key, all applications and services configured using that key immediately lose access to all Archetype AI APIs. ### Filtering API Keys By Status To filter the list of your API keys to show only those whose status (Active, Revoked, Expired, etc.) matches a given value, use the popup located immediately below the **API Keys** heading: Filtering to show only Revoked API
Keys In this example, the **Revoked** filter is highlighted. Once selected, this will restrict the API key list to show only those keys which have been revoked. # Agent Gallery Source: https://docs.archetypeai.app/developer-console/agents/agent-gallery Browse the available agent blueprints, view details about them, and access code examples and live demos. ## The Agent Gallery To view the available agent blueprints, visit the [Agent Gallery](https://console.u1.archetypeai.app/dashboard/blueprints) in the Developer Console. This presents a view showing cards for each of the available agent blueprints. Agent Gallery To learn more about a given agent, click on the corresponding blueprint's card in the Agent Gallery. ## The Agent Blueprint Details Page The agent blueprint details page provides information about the blueprint, including a list of common use cases and access to tools that let you experiment with and try out the blueprint. On this screen, you can also choose to view the blueprint's code by clicking the **View code** button, and you can view documentation about the agent blueprint by clicking **View docs**. ### On This Page * **Use cases:** A list of common use cases for agents started from this blueprint. * **Try it in the playground:** Most agents offer one or more playgrounds, where you can try running the agent against real data, with log access and access to the output as it comes in. * **Test it out:** Details on how to build and run a standalone example, either in your terminal or using agent skills. Not all agent blueprints offer all of these sections. # Agent Manager Source: https://docs.archetypeai.app/developer-console/agents/agent-manager View and run agents available to your organization. To view the agents available to your organization, click the **Agent Manager** option in the Developer Console sidebar. The Agent Manager offers two views: a card view and a list view. The Agent Manager list view The columns shown in the list are: * **Agent**: The human-readable agent name specified when the agent was created. * **Blueprint**: The agent blueprint on which the agent is based (such as Manual Generation, Task Validation, or a custom blueprint's ID starting with `bp_`). * **Runs**: How long ago the last run was, or "No runs yet" if the agent hasn't been run yet. * **Status**: The status of the agent (`BUILDING` or `READY`). * **Created**: The date on which the agent was created. Both the list view and the card view let you filter the agent list based on which blueprint was used to create the agent, and you can search for agents matching a given string. You can change the sort column (to Agent, Runs, or Created) by clicking on the corresponding column's header. Click the header again to reverse the sort order. You can also choose the sort column and sort order using the sorting popup button () located between the search field and the card/list view buttons. ## Running an Agent To run an agent from the Developer Console, visit the [Agent Manager](https://console.u1.archetypeai.app/dashboard/agents) and locate the agent you want to run. Click on it to open the agent: The agent page Click the ** Run Agent** button at the top-right corner of the agent page to begin the process of running the agent. This opens up a modal letting you configure the agent's inputs: Running an agent From here, select or upload your input files just like you do when setting up any batch processing job. This takes you to the running agent details page, where you can monitor and manage your agent run. ## Monitoring and Managing Agent Runs To monitor and manage agent runs, start by opening the agent page for the agent whose runs you want to manage. ### The Runs list At the bottom, in the **Runs** tab, is a list of the runs of the agent that are available to manage. Agent page showing runs The list shows, for each agent run: * When the agent run was started. * The input file(s). * The agent run's duration; this is the total amount of time that run lasted for completed runs, and the time to date for ongoing agent runs. * The agent run's status. * The agent run's unique ID. Click on an agent run in the **Runs** list to open that run's [details page](#the-agent-run-details-page). ### The Configuration The **Configuration** tab displays the values of the parameters configured for the agent run, with separate listings for the parameters that are customized for this run of the agent and the parameters that are using the blueprint's default values. ## Deleting an Agent To delete an agent from the Developer Console, open the agent page and click the button to the left of the ** Run Agent** button. This opens a popup which includes the ** Delete agent** button. Agent page Clicking the ** Delete agent** button pops up a modal confirming that you wish to delete the agent: Deleting an agent Review the information about the agent you're about to delete, including its name and bundle ID. Make sure it's the agent you intend to delete, since deletion is an irreversible action. You can only delete agents that have no runs in progress. If your agent is running, cancel all of its runs before deleting it. Once you're certain you wish to delete the agent, click the **Delete agent** button. If you decide not to delete the agent, click **Cancel** instead. Deleting an agent does not have any effect on the agent blueprint on which the agent is based. ## The Agent Run Details Page The **Run** details page displays details about an agent run. For running agents, the page includes **Pause** and **Cancel** buttons: Run details page for an ongoing agent run If the agent run has completed, the **Pause** and **Cancel** buttons aren't displayed: Running agent details In both cases, the left side of the page displays details about the run's progress: * The percentage of the agent run that has been completed, both numerically and as a progress bar. * A box including the number of files to be processed, the total size in bytes of the data to be processed, how much data has already been processed, and the most recent log output line. * A tab panel which lets you toggle between viewing: * The agent run's log entries. * A list of the input files specified when the run was started. * A list of the artifacts (output files) generated by the agent run. The right side of the page shows details about the agent run overall: * The run's unique ID, starting with `agt_`. * The agent's name. * The agent's bundle ID, starting with `bnd_`. * The agent blueprint on which the agent is based. * The path of the output file. * The date and time at which the agent run was created. * The date and time at which the agent run was started. * The date and time at which the agent run ended. # Using Agents in the Developer Console Source: https://docs.archetypeai.app/developer-console/agents/overview A guide to running, monitoring, and deleting agents using the Developer Console. The Developer Console provides dashboards to view the agent blueprints — the templates on which agents are based — as well as any agents you have created from the blueprints. Together, these dashboards let you manage and run your agents so you can engage Newton to perform complex tasks. ## Agent Dashboards * **[Agent Gallery](/developer-console/agents/agent-gallery)**: The Agent Gallery is where you can find the available agent blueprints, access examples of their use, and quickly reach documentation about each blueprint. * **[Agent Manager](/developer-console/agents/agent-manager)**: The Agent Manager is where you go to manage and run your agents, and view the status of ongoing agent runs. ## Related Content * [Managing Agents Using the Agents API](/core-concepts/agents/api) # Batch Manager Source: https://docs.archetypeai.app/developer-console/batch-manager Create, manage, and monitor batch processing jobs from the Batch Manager dashboard in the Developer Console. The [Developer Console](https://console.u1.archetypeai.app/) supports processing large datasets asynchronously using the **Batch Manager**. The Batch Manager lets you create and manage batch processing jobs, as well as monitor their status. ## The Batch Manager Dashboard Selecting the Batch Manager in the console presents you with the Batch Manager dashboard, which shows existing jobs, along with filters to let you see only jobs in the desired state, job search functionality, and other tools to help you manage and monitor jobs easily. The Batch Manager dashboard The dashboard lists all of the past and active batch jobs. This list can be filtered by job status. It can also be sorted by creation timestamp, completion percentage, and current status. To change sorting method, click on the column header to search on. Click a second time to reverse the order. You can also use the sort popup located between the **Search jobs** search box and the **+ Create** button located above the job list. ## Creating a Batch Processing Job To create a batch processing job, click the **+ Create** button at the top-right of the Batch Manager dashboard. This opens the **Create Batch Job** modal: The Create Batch Job modal Enter a human-readable name for the new batch processing job. This specifies the type of processing you want to do. Which models are available depends on which workflow key you choose. For example, Manual Generation jobs use a Newton C model, while Machine State Classification jobs use a Newton Omega model. If you selected **Custom Checkpoint** under **Model**, you are then also prompted to enter the checkpoint ID of the checkpoint for your fine-tuned model. See [Fine-Tuning](/developer-console/fine-tuning) for details on creating fine-tuned models. Make sure to use a fine-tuned model that corresponds to the workflow key you selected. Select or upload the files to run the job against. You can select up to 50 files. For the Machine State Classification workflow, select N-shot example files to train with. Be sure to add appropriate labels for each. Enter the configuration of the job using YAML. For example, for the Machine State Classification workflow, make sure the column names in the YAML configuration match the names of the columns in your data files. When everything's configured the way you want it, click **Create Job**. ## Viewing the Status of a Batch Processing Job To view status information about a job, such as its progress, its logs, and other job details, click on the job in the Batch Manager dashboard. The job status page displays information about the job, including: * The job's status (`PENDING`, `ADMITTED`, `RUNNING`, `PAUSED`, `COMPLETED`, `INTERRUPTED`, `FAILED`, `PREEMPTED`, or `CANCELLED`) * The amount of time the job has spent running * The total amount of time the job has spent in the queue * The job's ID * The job's workflow key * When the job was created * When the job started running * The YAML configuration of the job * Processing details about the job The processing details pane offers four tabs: * **Logs** shows detailed logs for the batch processing job. * **Artifacts** lists all of the artifacts generated by the job. * **Input Files** lists the input files provided when the job was started. * **Config** displays the job's configuration. ## Downloading Batch Artifacts To download the artifacts generated by completed jobs, you have two options: * To download all of the artifacts for a batch at once, click the **Download Artifacts** button to the right of the job title. This will download a Zip archive containing all the artifact files. * To download the artifact file for a specific job, click the download icon at the right side of that artifact's row in the **Job Artifacts** view. ## Canceling a Batch Processing Job To cancel a running job, click on the job in the Batch Manager dashboard, then click the **Cancel** button to the right of the job's title. # File Manager Source: https://docs.archetypeai.app/developer-console/file-manager/overview Upload and manage files for use with agents and batch processing jobs. Almost everything you do with the Archetype AI platform requires the use of input and/or output files. The Developer Console provides a **[File Manager](https://console.u1.archetypeai.app/dashboard/files)** which lets you upload files for use with Newton. It also provides the ability to view your organization's existing files as well as metadata about them. File Manager screenshot Above the file list is a search box for searching your file library. You can sort by file ID, file size, file status, or file creation date by clicking on the corresponding column header. Click the header again to reverse the sort order. You can also select the sort column and sort order using the sorting popup () located between the search field and the **+ Add Files** button. ## Viewing File Metadata To view a file's metadata, click on the caret (>) in front of the file's icon and name in the list. This expands the file's row to show the JSON metadata for the file. This information includes: * File ID (file name) * File UID (`fil_*`) * File MIME type * File size in bytes * File creation timestamp A clipboard icon at the top-right corner of the metadata box lets you copy to your clipboard the metadata in JSON format. ## Deleting a File To delete a file, hover over its row in the table. This makes visible a delete () icon at the right edge of the row. Click it to delete the file. There is no warning before deleting a file. Once you click the delete button, the file is immediately deleted. ## Uploading a File or Files To upload one or more files to your organization's file library, click the **+ Add Files** button above the top-right side of the file list. This opens the **Upload Files** dialog. The Upload Files dialog Specify the files to upload by either dragging and dropping files into the dialog, or by clicking the file selection panel and using your device's standard interface to select files to upload from its local file storage. Files are uploaded as soon as you drop them into the dialog or finish selecting them using your device's user interface. The dialog lists the types of files you can upload. These are: * MP4 video files, up to 255 MB in size * Sensor data in CSV files with a timestamp column and numeric channels * JSON, JSONL, TSV, and text files You may upload up to 50 files at a time. The maximum file size for uploads using the File Manager is 255 MB. To upload larger files, you'll need to use the Files API's [direct-to-cloud](/core-concepts/files/cloud-upload) capabilites. ## Learn More Learn about the Files API, which supports uploading, downloading, and managing files, including files larger than 255 MB using the direct-to-cloud functions. Get details about Files API endpoints and their usage. # Fine-Tuning Source: https://docs.archetypeai.app/developer-console/fine-tuning/fine-tuning Create and monitor fine-tuning jobs from the Developer Console: training data, job configuration, progress, logs, and checkpoints. To perform [fine-tuning](/core-concepts/customization/fine-tuning) of an Archetype AI model to produce a custom model for your use case, use the Fine-Tuning dashboard in the Developer Console. Dashboard menu ## Creating a Fine-Tuning Job Upon choosing the Fine-Tuning dashboard option in the sidebar, the Create Fine-Tuning Job modal appears. Create Fine-Tuning Job modal Enter a human-readable name for the fine-tuning job, then select the base model that you wish to fine-tune into a custom model. Next, choose the method by which the base model should be adapted to your data. The methods available depend on the base model you've selected. Some models may only offer one method. The adaptation methods are described in the user interface; click the method's name to see a description. After selecting the base model, the modal expands to include options to configure the fine-tuning job further, such as specifying training files, any validation files that are needed, and hyperparameter settings. ### Specifying Training and Validation Files Specifying training files for the fine-tuning job is done similarly to specifying files anywhere in the Archetype Console: you can provide files in one of three ways: * By selecting files already present in your library of files * By entering the file IDs (file names) of existing files in your library * By uploading new files to your library; doing so automatically adds them to the selected files list as well as adding them to your file library Selecting a file from the file library Specifying library files by file ID Uploading files to the library If using the Omega model, the list of selected files also lets you edit the class labels used for each corresponding file. Specifying class labels using the Omega model Validation files are added next, using a similar interface. These files are required by the Omega model and optional for the Newton C-model. ### Specifying Hyperparameters The exact hyperparameters available may vary depending on the base model and/or adaptation method you selected. To learn more about a given hyperparameter, highlight the icon next to its name to see a tooltip describing the hyperparameter. All hyperparameters assume an automatic default value, but you can adjust fine-tuning by setting particular values that suit your use case and input data. To specify a custom value for a hyperparameter, first check the **Custom** checkbox next to the hyperparameter's value input box, then enter the custom value for the hyperparameter. Specifying custom values for hyperparameters In the above example, a custom value of `32` is specified for the **Step Size** hyperparameter. ### Advanced Settings Finally, review the available advanced settings to see if there are any you need to set up. These are all optional. The advanced settings are: | Setting | Description | | - | - | | Model suffix | A string appended to the end of the name of the generated model file. This lets you more easily tell it apart from other fine-tuned models, such as if you have multiple versions of the same fine-tune. | | Checkpoint ID | The ID of the fine-tuning job checkpoint from which to start working. Using this lets you warm-start fine-tuning from a partially-completed job. Be sure to use a checkpoint whose base model matches the one you selected above. Model weights are initialized from the checkpoint instead of from the base model. The hyperparameters you specify *are* used. | | Seed | An optional random number seed to use for reproduceability. If you use the same seed as a previous run, with the same input parameters, you will get the same output. If you leave this blank, the seed is set at random. | For more information about these advanced settings, or for information about advanced settings not listed above, highlight the icon next to the setting's name to see a descriptive tooltip. Once all settings are configured, click the **Create Job** button to create the job and enqueue it to be run. ## Monitoring a Fine-Tuning Job To see a list of existing fine-tuning jobs and their current statuses, click **Fine-Tuning** in the Developer Console dashboard's sidebar. The Fine-Tuning dashboard To copy the name or job ID of a job, click the clipboard icon next to its name or ID when you mouse over a row in the job list. Copying a job name To view details about a job, click anywhere else in the row. This opens the details view for the job. Job details At the top is the job's name and current status. Next to this is the ** Pause** or ** Resume** button. The remainder of the details view is divided into several boxes. The **Overview** box lists basic information about the job, including: * The job ID * The base model on which the fine-tuned model will be based * The ID of the fine-tuned model (available only once the fine-tuning job has successfully completed) * The checkpoint ID from which the job was warm-started * The starting timestamp * The ending timestamp (available only once the job has completed) * The total amount of time the job took to run (available only once the job has completed) The **Parameters** box lists basic configuration information about the job, including: * The number of training files specified * The number of validation files specified * The suffix that will be applied to the new fine-tuned model's name * The random number seed that was specified, if any The **Training** box shows the progress of the training process. This information is updated periodically as the training progresses, and is displayed using a tabbed interface. The Progress tab displays progress information about the fine-tuning job, including the percentage of the job that is complete, the step that was last completed, the loss, the number of checkpoints that have been saved, and the estimated time remaining for the job. Fine-tuning job progress When fine-tuning based on the Newton-C model, a graph showing Loss compared to the step number is drawn. Loss • Steps The Logs tab displays log entries for the fine-tuning job. You can filter by the type of log entry, and you can search for specific information in the log. Fine-tuning job logs The Checkpoints tab lists the checkpoints that have been recorded for the fine-tuning job. These checkpoints can be used to warm-start a new fine-tuning job, or used as the fine-tuned model checkpoint ID when starting a batch processing job. Fine-tuning job checkpoints Click the clipboard icon next to the **Checkpoint ID** to copy the ID. This is useful, for example, when you want to warm-start a new job from a given checkpoint or to paste into the Batch Manager to use the fine-tuned checkpoint as the model for a batch processing job. The Training Files tab lists the training files specified for the job, with the ability to download copies of the files. Fine-tuning job training files ## Pausing and Resuming a Fine-Tuning Job To pause a fine-tuning job, open its details view. At the top of the view, to the right of the fine-tuning job's name and status, is the **Pause** button. The pause button's location Click ** Pause** to pause the job. The job will pause, freeing resources to be used by other jobs, and the button's name changes to ** Resume**. Click the ** Resume** button to continue the job from where it left off. ## Using a Fine-Tuned Model Once fine-tuning has completed, open the **Checkpoints** tab in the fine-tuning job's screen, then click the clipboard icon next to the checkpoint ID you wish to use as the model for your batch job. This will copy the checkpoint ID to your clipboard. Then, go to the [Batch Manager](/developer-console/batch-manager) and set up a new job. Before starting the job, set the **Fine-tuned checkpoint** field in the **Create Batch Job** panel to the ID of your model's checkpoint (by pasting the copied ID, for example). Setting the fine-tuned checkpoint This field is located immediately after where the source files (such as input files and N-shot example files) are specified. When you start the job, it will do so using your fine-tuned model. # Getting Started Source: https://docs.archetypeai.app/developer-console/introduction (Archived) Legacy Lens-era Developer Console guide: the Workbench, lens monitoring, and file management. The [Developer Console](https://console.u1.archetypeai.app/) is the front-end interface to the Archetype platform. It allows you to quickly use our lenses with your own data in a no-code environment (workbench), manage your files, and access documentation. ## What You Can Do in the Developer Console ### 1. Test Lenses in the Workbench The [Workbench](https://console.u1.archetypeai.app/workbench) is a no-code interface for testing Lenses with your own data. Using the workbench is easy for both developers and non-developers involves the following steps: 1. **Select your lens** 2. **Upload your own sample data** (or try our [sample files](https://drive.google.com/drive/folders/1iAT42EUpCEMj_sFvHvRAtJBTqSF_Jn-u?usp=drive_link) to get started quickly) 3. **Modify the lens parameters** 4. **Run a Session & View the output** Learn step by step on how to use the workbench with the [Activity Monitor Lens](https://docs.archetypeai.app/developer-console/workbench/activity) and [Machine State Lens](https://docs.archetypeai.app/developer-console/workbench/machine-state). Test_Lenses Lenses created programmatically (via [Python client](https://docs.archetypeai.app/libraries/python) or [API](https://docs.archetypeai.app/api-reference/introduction)) will automatically appear in your Developer Console, allowing you to monitor sessions, view results, and manage configurations from the interface. Learn more in the [quickstart guide](https://docs.archetypeai.app/introduction/getting-started). ### 2. Manage Resources The console dashboard provides a [File Manager](https://console.u1.archetypeai.app/dashboard/files) to: * Upload files that can be accessed via API key * View and delete files at any time These controls ensure that data and artifacts remain isolated to your API key. Dashboard_Files ### 3. Monitor Lenses and Sessions The console dashboard gives you visibility into the lenses and [sessions](https://console.u1.archetypeai.app/dashboard/monitor) that are running: * Lenses in use, including their lens ID and lens metadata * Active sessions and their duration This helps you track system usage and debug issues. Dashboard_Lenses ### 4. Create and Manage Batch Processing jobs The console dashboard includes the **Batch Manager**, which lets you create, manage, and monitor batch processing jobs. Batch processing lets you run a job against multiple files at once. Configure the job, select the files against which to run the job, and run the job. You can then watch the status of the job, or let the job run and check the results later. ### 5. Explore Documentation The console provides a link to the developer docs where you can: * Learn about [core concepts](/core-concepts/introduction/introduction) of the Archetype platform * Try the [Quickstart](/introduction/getting-started) and [example projects](/code-examples/example-projects) * View [API references](/api-reference/introduction) for integrating APIs into your prototypes and applications ## Access Requirements * Active Archetype platform API key - [Sign in here](https://console.u1.archetypeai.app/) The Workbench is continuously evolving. New lens types and capabilities are added regularly based on user feedback and platform improvements. # Model Registry Source: https://docs.archetypeai.app/developer-console/model-registry/model-registry View information about the models available for your use, including both platform-defined models and custom models created by your organization. Every model available for your use can be found in the **Model Registry**. This includes all platform-defined models and all custom models defined by your organization. ## The Model Registry Page Upon clicking **Model Registry** in the sidebar, you're presented with the main Model Registry page: The Model Registry page At the top of the list are features to filter and search the list: * The left-hand popup lets you filter by Newton model family. * The right-hand popup lets you filter by scope (that is, whether the model is platform-defined or organization-defined). * At the right side of the page is a search box to let you search for specific models by name. Below this is the list of models, with the following columns: | Column Name | Description | | - | - | | Model | The name of the model. | | Family | The model family. | | Size | The model size (in parameters). | | Context | The model's context window size. | | Scope | Whether the model is scoped to the platform (visible to all organizations) or the organization (visible only to your organization). | | Registered | The date on which the model was registered. Hover your cursor over the date to see a full date and time stamp. | The list is sorted in reverse chronological order; that is, the most recently created model is listed first. ## Viewing Model Details To see more details about a particular model, click on it in the model list. This will open a model details dialog that describes the model. Base models (those that aren't fine-tuned versions of other models) look like this: A platform model dialog In addition to displaying the model's name and description, a badge indicates that this is a **platform** model. Below that, a table provides the following information in its simplest form: * The model family. * The model's creation date. * The model ID, starting with `mdl_`. Other models, especially those created using fine-tuning, have more information: A more detailed model dialog Here, in addition to the information included in the simpler model details dialog, is listed the following additional information: * The inheritance of the model; that is, a log of each generation of parent model and the fine-tuning checkpoint ID used to create the model. This goes back as many generations as it takes to reach a base model. Each generation records: * The name of the parent model from which the examined model was generated. * The fine-tuning checkpoint ID used to generate the model. * The model ID of the parent model. * The hyperparameters associated with the model, if any. * Any metrics associated with the model. # Organization Administration Source: https://docs.archetypeai.app/developer-console/org-admin/overview Administrate your organization using the Developer Console's **Organization Admin** page. Developer Console sidebar for organization administrators

If you are an administrator for your organization, the Archetype Developer Console offers access to organization administration features through the **Organization Admin** option in the account panel at the bottom of the sidebar.

With this interface, you can view and manage your organization's members and their API keys and add and delete members. In addition, you can set the default role for new SSO users.

To manage your organization, click the **Organization Admin** option in the sidebar. This opens the **Organization Admin** page: The main Organization Admin page ## Organization Details The **Organization Admin** page displays at the top of the page a box containing information about the organization: * The organization's "slug," which is a short-form human-readable identifier for the organization. * The organization's unique ID, starting with `org_`. * The number of members in the organization, as well as the number of currently deactivated members. * The organization's default role; this is the role automatically assigned to new SSO users. ## Changing the Default Role To change the default role applied to new SSO users, click the **Edit** button to the right of the current default role in the **Details** panel at the top of the page. Setting the default role Use the **Default Role** popup to choose the default role for automatically-created SSO users; these are members created automatically when they are part of your SSO cohort and attempt to sign in, but do not yet have member accounts in your Archetype organization. Each possible role is described in the user interface: * **Viewer**: A safe default which grants read-only access to content. * **Developer**: A role which allows the member to manage their own API keys. * **Admin**: A role which grants full-organization administrative access. Every new SSO user is becomes an administrator by default. **Use with caution.** ## Managing Members Below the organization **Details** panel is a list of the organization's members. At the top of the list is a row including the following: * A popup which lets you filter by the member's role. * A search box. * The **+ Add Members** button. ### Adding Members To add one or more new members to your organization, click the **+ Add Members** button above the top-right corner of the member list. This opens the **Add Members** dialog: The Add Members panel To add a member, enter their email address, first name, last name, and their role. To add another member, click the **+** button at the right side of the row. Continue adding members until they've all been added, then click the **Create *N* Users** button (where *N* is the number of users to create). You can optionally bulk add multiple users at once by clicking the **Bulk add** button at the bottom-left of the panel. This opens the **Bulk add members** panel: Bulk add members panel This panel lets you enter all the users in the format: ``` Email,Firstname,Lastname,Role ``` For example: ``` miguel.garcia@example.com,Miguel,Garcia,developer alice.thomas@example.com,Alice,Thomas,admin john.doe@example.com,John,Doe,viewer ``` If you paste CSV in the given format, a header row is automatically ignored if it exists. Once you've entered (or pasted) all the member' information into the edit box, click the **Add *N* to list** button (where *N* is the number of member in the list). ### Changing a Member's Role To change a member's role, click on the role popup in the member's row in the member list. Choose their new role from the list. ### Managing a Member's API Keys To manage a member's API keys, click the key icon to the right of the member's information in the main Organization Admin panel. This opens the API keys panel for that member. For example: API keys for member panel At the top is the member's name. Below is a list of the member's API keys, both active and revoked. Each row in the list displays both the key's name and the key's ID. Secret API keys (the ones you provide to the Archetype API) are not displayed. To revoke an active key, press the (trash can) icon at the right end of the key's information row. Clicking the (trash can) icon to revoke a key takes effect *immediately*. There is no confirmation request before revocation occurs, and revoked keys cannot be reactivated. Be careful. ### Deactivating a Member To deactivate the account belonging to a member of your organization, click the **** (trash can) icon that appears in the row of the member you want to deactivate. Confirm the deactivation when asked to do so. Once a member has been deactivated, they cannot be reactivated. # Overview Source: https://docs.archetypeai.app/developer-console/overview What you can do in the Developer Console: create API keys, manage files, run batch jobs, fine-tune models, and access documentation. The [Developer Console](https://console.u1.archetypeai.app/) is the front-end interface to the Archetype platform. It's where you create and manage API keys, manage your files, create and monitor batch processing jobs, fine-tune models, and access documentation. ## Signing In To the Developer Console To sign in to the Developer Console, go to the Console's web site at [https://console.u1.archetypeai.app/](https://console.u1.archetypeai.app/). If you aren't already logged in, you will be asked to do so. Console log in form ### Signing in Using an Email Address If your account uses your email address to authenticate, click **Sign in with Email** to begin the sign-in process. Sign in with Email panel Enter your email address and click the **Continue** button. #### Signing in Using a Password If your organization uses password authentication, you'll next be prompted for your password. Sign in with Password panel Enter your password and click **Sign In**. This will take you to the Developer Console's main page. #### Signing in Using Single-Sign On If your organization uses single sign-on (SSO) to authenticate users, click **Sign in with Email**, then enter your email address. This opens your SSO provider's authentication workflow. Follow their prompts to authenticate and return to the Archetype AI web site, which will open the Developer Console following a successful authentication. ### Signing in with an API key If you're still using API keys to sign-in, enter your API key and click **Access Console**. You should also [contact Archetype AI support](mailto:support@archetypeai.dev) to transition your account to use email-based sign-in instead. Support for signing into the Developer Console using API keys is deprecated and will be retired soon. ## What You Can Do in the Developer Console ### Manage API Keys Everything you build on the platform authenticates with an API key, and your [Profile & API Keys](/developer-console/account-management#managing-api-keys) page is where you manage your keys. There, you can create new API keys, view and filter a list of your keys, and revoke your keys. ### Manage Resources The console dashboard provides a [File Manager](/developer-console/file-manager/overview) to: * Upload files that can be accessed via API key * View information about and delete files at any time These controls ensure that data and artifacts remain isolated to your API key. ### Create and Manage Batch Processing Jobs The console dashboard includes the [Batch Manager](/developer-console/batch-manager), which lets you create, manage, and monitor batch processing jobs. Batch processing lets you run a job against multiple files at once. Configure the job, select the files against which to run the job, and run the job. You can then watch the status of the job, or let the job run and check the results later. ### Fine-Tune Models The Console's [Fine-Tuning dashboard](/developer-console/fine-tuning/fine-tuning) walks you through training a custom Newton checkpoint on your own data: upload training files, configure the job, monitor training progress and loss curves, and pick a checkpoint to query. ### Explore Documentation The Console provides a link to the developer documentation where you can: * Learn about [core concepts](/core-concepts/introduction/introduction) of the Archetype Platform * Try the [Developer Quickstart](https://docs.archetypeai.app/introduction/getting-started) and [example projects](https://docs.archetypeai.app/code-examples/example-projects) * View [API references](https://docs.archetypeai.app/api-reference/introduction) for integrating APIs into your prototypes and applications # Activity Monitor Lens Source: https://docs.archetypeai.app/developer-console/workbench/activity (Archived) Legacy Lens-era Workbench tutorial: the Activity Monitor lens with video files. The **Activity Monitor Lens** analyzes camera data to identify the activities, movements, or events occurring within a scene. Use the [Activity Monitor lens](/core-concepts/lenses/lens-templates/activity-monitor) to analyze objects, activities, and concepts through video data. While the APIs work with both pre-recorded and live videos, the workbench only works with pre-recorded video files. ## 1. Access the Workbench Use your API key and log into the [Console](https://console.u1.archetypeai.app/workbench). Click on "Workbench" in the navigation bar. Make sure you have an active API key for the Archetype platform, and you're able to log in to the console. If you have any problems, please contact [support@archetypeai.dev](mailto:support@archetypeai.dev). ## 2. Select a Lens In the Workbench, the Lens name appears at the bottom of the screen. Click the name to open a tray showing all lenses available to your organization. Select the lens named "Activity Monitor" from the lens tray. ## 3. Upload Your Video The Workbench works with pre-recorded .mp4 video files for analysis. Download our sample dashcam video to follow along: [Ring\_Dashcam\_Traffic.mp4](https://drive.google.com/file/d/142EXjAriJq7_WVZlTVzvhVTv8aB8q_UQ/view?usp=drive_link). Or upload your own video file using the file selection in the top right of the input panel. Only MP4 video files under 255MB are currently supported. Other formats will not work. ## 4. Set Your Focus and Instructions Configure how the Activity Monitor lens analyzes your video by setting focus and providing custom instructions. In the instructions field, copy and paste these instructions for the Ring video analysis: ``` You are an intelligent dashcam attached to the front of a car, looking for safety hazards to keep your driver safe. This includes reckless driving and debris in the road such as car parts. ONLY when you see something hazardous or unsafe, respond with a notification in the following format {Alert: Description of safety hazard}. Do not include brackets in your message. Respond in less than 8 words. ``` You can also customize the Instructions to fit your use case—for example, by asking Newton to focus on specific aspects or answer targeted questions. For details on advanced parameters, see the [**Activity Monitor Lens**](https://docs.archetypeai.app/core-concepts/lenses/lens-templates/activity-monitor) section in Core Concepts. Type your focus in the bottom input bar. **Focus** is a runtime control that allows you to narrow analysis to specific behaviors or conditions. For the Ring\_Dashcam\_Traffic video, try the focus of **"safety hazards".** Focus Safety Hazards Temporal focus is a parameter in the workbench that controls frame sampling across time windows. **Change the temporal focus from 5 to 1**, which is the window in seconds for analysis. This determines how frequently the lens samples frames from your video for analysis. Temporal Focus Dashcam ## 5. Start Your Session and View Results Begin the analysis by clicking the arrow button in the bottom right of the screen to start the session. The session will begin processing your video with the selected lens and focus. Once the session is running, you'll be able to see output from the lens within the output panel. Click a message to view its corresponding video segment. A pill expands with a looping playhead. Click the video to close the pill and return to the main view. The output text will look something like this: ```text Example Output theme={"system"} [00:00:06] No visible hazards detected. Safe driving ahead. [00:00:07] No visible hazards detected at this moment. [00:00:08] Alert: Tire on road ahead. ``` ## Access Developer Logs (Optional) For debugging and detailed analysis, you can view the log panel above the focus bar. Session Logs Congratulations! You've successfully run your first Workbench session without writing any code. ## Optional: Try Variations Using the same video (or a [starter video](https://drive.google.com/drive/folders/1iAT42EUpCEMj_sFvHvRAtJBTqSF_Jn-u?usp=drive_link)), experiment with how Lens parameters affect the output: * **Change Focus** to `Vehicles` and observe the difference. * **Edit Instructions** using the template below and see how behavior and output change (*A prompt best practices section is coming soon)*: ``` Role: You are a smart camera monitoring a conveyor belt in a manufacturing facility. Objective: Detect complete work stoppages that require human intervention. Output: Return alerts in the following format: ALERT: ``` * **Adjust Temporal Focus** to `2` or `20` to compare shorter vs. longer time windows. Learn more in the [**Activity Monitor Lens**](https://docs.archetypeai.app/core-concepts/lenses/lens-templates/activity-monitor) section of Core Concepts. ## Learn More Try a quickstart tutorial in the terminal to get started with video. Ready to integrate Newton into your application? Explore the Lens API documentation # Machine State Lens Source: https://docs.archetypeai.app/developer-console/workbench/machine-state (Archived) Legacy Lens-era Workbench tutorial: the Machine State Lens with CSV files. The **Machine State Lens** classifies the operational state of a machine using its sensor measurements. Use the [Machine State Lens](/core-concepts/lenses/lens-templates/machine-state) to analyze time series sensor data and detect different machine states from your CSV files. ## 1. Access the Workbench Use your API key and log into the [Console](https://console.u1.archetypeai.app/workbench). Click on "Workbench" in the navigation bar. Make sure you have an active api key for the Archetype platform, and you're able to login to the console. If you have any problems, please contact [support@archetypeai.](mailto:support@archetypeai.dev)dev ## 2. Select a Lens In the Workbench, the Lens name appears at the bottom of the screen. Click the name to open a tray showing all lenses available to your organization. Select the lens named 'Machine State Lens' from the lens tray. ## 3. Upload Your CSV File The Machine State Lens works with time series data in .CSV format. At the top right of the input panel, you'll see a dropdown called "select.csv". Select a .CSV file you've already uploaded, or upload your own. We can start with this vibration example: [data.csv](https://drive.google.com/file/d/1zizePdJ1gsUHI-6Kp3Jfe22QJwjxuz28/view?usp=drive_link). Upload Csv2 CSV files must be properly formatted with sensor recordings. Each row should represent a single time sample and include a timestamp column (unix time) and one or more numeric sensor channels (a1 to an). ## 4. Edit Lens Parameters Lens parameters control how a Lens processes and analyzes data. To begin, add the n-shot examples provided below. Click on the lens name to view and modify the Lens parameters. Add N Shot examples that represent the states you'd like to classify.\ Download our sample CSV files to follow along: * [healthy.csv](https://drive.google.com/file/d/1HK5EKvPWj_acMYB2SeBgAbzMEEtunn_6/view?usp=drive_link) - Normal operating conditions * [broken.csv](https://drive.google.com/file/d/1hq1xyl9DBD_J1Legux3teypH1smvZfJm/view?usp=drive_link) - Equipment failure or malfunction N Shot Learn more about the additional parameters such as window size, step size, and data columns when working with your own data under [Machine State Lens](/core-concepts/lenses/lens-templates/machine-state). ## 5. Start Your Session and View Results Begin the analysis by clicking the arrow button in the bottom right of the screen to start the session. The session will process your CSV data with the Machine State Lens and your specified focus. Once processing begins, you'll see analysis results appear for your time series data. Click on any result to see the corresponding time window and view how the lens classifies different periods based on your labeled states. ```text Example Output theme={"system"} [12:34:56] healthy [12:45:12] broken [13:02:34] healthy ``` ## 6. Access Developer Logs (Optional) For debugging and detailed analysis, you can expand the session logs panel above the focus bar. Ms Logs Congratulations! You've successfully run your first Lens Workbench session without writing any code. ## Next Steps Try your own .csv files, and adjust the n shot examples and parameters based on your use case. A guide on recording your own data and examples is coming soon. ## Learn More Try a quickstart tutorial in the terminal to get started with CSV files. Ready to integrate Newton into your application? Explore the Lens API documentation # Agent Skills Source: https://docs.archetypeai.app/for-agents/agent-skills Use the official Archetype AI Agent Skills with your coding agent (Claude Code, Cursor, Codex, and others) to build on Newton faster. ## What are Agent Skills? Agent Skills are packaged, reusable instructions that teach an AI coding agent how to handle a specific Newton task — for example, *"evaluate the assembly steps shown in this video,"* *"embed these vibration windows and flag the anomalies,"* or *"scaffold a branded dashboard for the demo front-end."* Each skill is a folder containing a `SKILL.md` (plus optional runnable reference scripts and tests) that the agent loads on demand. Skills give agents the institutional knowledge you'd otherwise have to repeat in every prompt: which endpoint to call, what the request body looks like, and the empirical gotchas we've already verified against production. They're the difference between *"explain the Direct Query API"* (you do the synthesis) and *"run this clip through Newton and tell me if the assembly passed"* (the agent already knows how). The canonical source is the [archetypeai/agent-skills](https://github.com/archetypeai/agent-skills) repository. ## Install ### Any coding agent (recommended) The skills are published on [skills.sh](https://www.skills.sh/archetypeai/agent-skills). One command detects your coding agent (Claude Code, Cursor, Codex, Copilot, and 20+ others) and installs to the right location: ```bash theme={"system"} # Install into the current project npx skills add archetypeai/agent-skills # Or install globally (available in all projects) npx skills add archetypeai/agent-skills -g ``` ### Manual install (Claude Code) Alternatively, copy the skills folder into Claude Code's skills directory: ```bash theme={"system"} # Clone the repo git clone https://github.com/archetypeai/agent-skills.git cd agent-skills # Install globally (available in every project) cp -r skills/* ~/.claude/skills/ # Or install into a single project cp -r skills/* /path/to/your-project/.claude/skills/ ``` The `SKILL.md` format is portable: the same files work with any agent runtime that loads skills from a directory — see each agent's docs for the directory it reads from. ### Invoke Once installed, invoke any skill in your agent with a slash command: ``` # Agents /atai-operational-state-monitoring-agent /atai-operational-state-monitoring-agent-data-prep /atai-rare-event-detection-agent /atai-anomaly-discovery-agent /atai-manual-generation-agent /atai-task-verification-agent # Models /atai-newton-omega-model-data-prep /atai-newton-omega-model /atai-newton-fusion-model # Integrations /atai-newton-omega-nvidia-nemotron # Design /atai-design-system ``` ## Available skills Four groups: **Agents** run a maintained pipeline server-side over the Agents API, **Models** call Newton directly on `/query` and leave the orchestration to you, **Integrations** pair a Newton model with a third-party model, and **Design** covers the demo front-end. Every skill that calls the platform builds its reference scripts on the [official python client](https://github.com/archetypeai/python-client) (`pip install archetypeai`), declared in each skill's `references/requirements.txt`. Three skills call no API: `atai-newton-omega-model-data-prep` and `atai-operational-state-monitoring-agent-data-prep` are local data processing, and `atai-design-system` scaffolds through the `ds` CLI. One exception, for now: the OSM skill's Path 2 uses a small stdlib HTTP helper, because the client doesn't cover the Optimizations, Evals and promote endpoints yet. The Integrations skill uses the official client for its Newton calls and calls the partner model on its own API (for Nemotron, NVIDIA's hosted API with its own `NVIDIA_API_KEY`). ### Agents Managed end-to-end pipelines — upload an input, run a pre-packaged bundle or canonical blueprint, poll, download the output. No model to host. OSM can also be **fitted to your own data** on the platform (Optimizations → promote → Evals → bundle), with its data-prep skill in front. The three sensor agents answer different questions, and the discriminator is **what you already have labelled**: every regime (OSM), a handful of examples of one named fault (RED), or nothing but normal operation (AD). | Skill | When to use | | - | - | | [`atai-operational-state-monitoring-agent`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-operational-state-monitoring-agent) | Classify **every** operating regime over a sensor CSV, when you have a full labelled library of the states you care about — drilling states, machine modes, process phases. Two paths. **Path 1:** resolve the pre-packaged "OSM Quick Start" bundle by name (classifier and windowing already pinned), run one agent per input file, poll, and download per-window state predictions with per-class probabilities. **Path 2:** build an agent on your own labelled data — fit and score windowing and kNN settings with the Optimizations API, promote the best trial to a blueprint, test it once with the Evals API, deliver it as a bundle, and score the delivery against held-back labels. | | [`atai-operational-state-monitoring-agent-data-prep`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-operational-state-monitoring-agent-data-prep) | Turn labelled sensor recordings into the role files OSM's Path 2 accepts — an exact sample grid split at gaps, a check that the sensor can tell the states apart, a group-aware split, library-only z-score, one training file per state, continuous scored files, held-back delivery labels — and preflight every platform rule before upload. Local, no API key. | | [`atai-rare-event-detection-agent`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-rare-event-detection-agent) | Detect a **named** rare fault recurring — a pump breakdown, a process excursion — from a handful of labelled examples plus normal data. Nearest-prototype classifier over Omega embeddings, so it tolerates the severe class imbalance of one or two incidents against months of normal operation. Covers why incident-level detection and false-alarm rate must be scored separately from window-level accuracy. | | [`atai-anomaly-discovery-agent`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-anomaly-discovery-agent) | Flag "this no longer looks like normal operation" on an asset with **no fault history** — fitted on normal-only reference data, so everything it flags is something it was never shown. Per-window anomaly score from a fitted LOF detector with its threshold pinned. One detector per asset by construction; covers scoring by lead time and false-alarm rate rather than precision and recall. | | [`atai-manual-generation-agent`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-manual-generation-agent) | Turn a recording of a procedure into an ordered, timestamped manual — each step traceable to a frame range and time range in the source video. Runs the canonical `mga` blueprint (Newton fusion + Whisper, pinned by the blueprint), so audio matters: spoken-only content such as safety cautions shows up in the output. | | [`atai-task-verification-agent`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-task-verification-agent) | Check whether a recording followed a known procedure — upload the video **and** a reference SOP, get a per-step `PASSED` / `FAILED` / `MISSING` verdict with a timestamp and a reason. The SOP is a runtime input, so one bundle serves every procedure. Read the skill's reliability section before trusting a verdict: a skipped step whose tool or part is visible on screen can come back `PASSED`, so `PASSED` verdicts warrant human review. | ### Models Direct Query API — one stateless `POST /query` per request. Use these when you want control over the pipeline, or the raw vectors to build on. | Skill | When to use | | - | - | | [`atai-newton-omega-model-data-prep`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-model-data-prep) | Clean, split, and featurize multivariate time-series before the Omega model — gap-aware blocking + imputation, an out-of-time train/test split, and joint-state (X, y) featurization. Use to build a leakage-free n-shot reference set for `atai-newton-omega-model`. | | [`atai-newton-omega-model`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-model) | Get time-series embeddings from the Omega encoder (`OmegaEncoder::omega_embeddings_1_4`) on `/query` — send a window of sensor readings, get back a 768-d vector per channel (one call per channel, fanned out in parallel). Covers the request/response shape, the 16–1024 window-length range, `normalize_input`, and a client-side n-shot KNN classification example. | | [`atai-newton-fusion-model`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-fusion-model) | Call the Newton C 2.6 fusion model on `/query` with text, image, or video in one stateless POST — no session lifecycle, no batch job, no SSE. Covers the request shape per modality (including both video paths: `.mp4` + `max_frames`, and client-sampled frames + `query_metadata`), multi-image mode, generation parameters, JSON-output prompting, and the verified gotchas. | ### Integrations Newton paired with a third-party model: Newton does the sensing, the other model reasons over what Newton found. For running Newton inside a partner's stack instead, see [NVIDIA VSS with Newton Fusion](/integrations/nvidia-vss). | Skill | When to use | | - | - | | [`atai-newton-omega-nvidia-nemotron`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-nvidia-nemotron) | Turn Omega + KNN verdicts into operator-facing text with **NVIDIA Nemotron** on NVIDIA's hosted API — fault briefs (what changed, likely cause, what to check) or suggested operator actions. Omega senses, Nemotron explains: Nemotron gets the verdict and plain window statistics against a healthy baseline or peer, never the embeddings. Covers NVIDIA key types (an NGC key returns 403), model retirement, turning Nemotron 3's reasoning off (`chat_template_kwargs`, not `/no_think`), JSON-only prompts with validation in code, and caching. Includes a key/model preflight script and an end-to-end example on the bundled bearing data. | ### Design | Skill | When to use | | - | - | | [`atai-design-system`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-design-system) | Build the front-end for a Newton demo with the **Archetype AI Design System** — the published npm packages (`@archetypeai/ds-lib-tokens`, the Svelte console/labs component libraries) and the `ds` scaffolding CLI — instead of hand-rolling tokens, components, fonts, or brand styling. Scaffolds a SvelteKit + Tailwind v4 app and installs the design system's own agent config (`CLAUDE.md`/`AGENTS.md` + `ds-manifest.json`) as the source of truth thereafter. Components ship for Svelte 5 (React port in progress); the tokens package is framework-agnostic. | ## Example projects These public repos demonstrate the patterns covered by the skills above — clone them as starting templates: **Vision & text reasoning** ([`atai-newton-fusion-model`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-fusion-model)): * [traffic-demo](https://github.com/archetypeai/archetypeai-traffic-demo) — live Caltrans CCTV traffic analysis; samples a burst of frames per interval and sends them as one multi-frame `/query` clip to reason over flow, incidents, and conditions. * [wildfire-demo](https://github.com/archetypeai/archetypeai-wildfire-demo) — wildfire detection across 1,200+ ALERTCalifornia cameras with Newton vision (per-camera smoke/fire/haze + zone Q\&A). * [earthquake-demo](https://github.com/archetypeai/archetypeai-earthquake-demo) — real-time USGS feed → text reasoning over structured seismic data (aftershock sequences, clustering, regional-risk ranking). * [grid-demo](https://github.com/archetypeai/archetypeai-grid-demo) — California power grid (CAISO supply/demand) → text reasoning on duck-curve dynamics, ramp, renewable share, and grid-stress risk. * [wifi-demo](https://github.com/archetypeai/archetypeai-wifi-demo) — "is anyone home?" occupancy inference from residential WiFi device-telemetry (GHOST-IoT) — per-window verdict + per-device classification shown against ground truth. **Time-series embeddings + local KNN** ([`atai-newton-omega-model`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-model), with [`atai-newton-omega-model-data-prep`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-model-data-prep) for the reference set): * [swat-demo-direct-query](https://github.com/archetypeai/archetypeai-swat-demo-direct-query) — 6-stage water-treatment-plant anomaly dashboard: per-channel Omega embeddings + client-side KNN, with PCA-2/UMAP-2 embedding views and per-stage accuracy badges (plus `/query` text reasoning for operator suggestions). * [wind-turbine-demo](https://github.com/archetypeai/archetypeai-wind-turbine-demo) — Penmanshiel wind-farm SCADA: Omega embeddings + local KNN against a leakage-free n-shot library precomputed offline, detecting a real frequency-converter fault against a healthy peer turbine. * [drilling-demo](https://github.com/archetypeai/archetypeai-drilling-demo) — drilling state classification from 14 North Sea (Volve) wells: Omega embeddings + local KNN against a leakage-free n-shot library built from held-out reference wells, with live accuracy vs ACTC ground truth. **Omega + NVIDIA Nemotron** ([`atai-newton-omega-nvidia-nemotron`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-nvidia-nemotron), on top of [`atai-newton-omega-model`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-model)): * [swat-demo-nemotron](https://github.com/archetypeai/archetypeai-swat-demo-nemotron) — the SWaT water-treatment dashboard with NVIDIA Nemotron writing the operator suggestions: upstream / local / downstream action cards as JSON, checked in code against the plant topology and each stage's equipment, cached per anomaly set. * [wind-turbine-demo-nemotron](https://github.com/archetypeai/archetypeai-wind-turbine-demo-nemotron) — the Penmanshiel monitor with NVIDIA Nemotron fault briefs: when Omega flags a turbine, Nemotron compares the window with the healthy peer over the same hours. It pointed to the pitch system for a real 23-hour pitch-circuit stop, from SCADA alone. **Agent lifecycle on real data** ([`atai-operational-state-monitoring-agent`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-operational-state-monitoring-agent), with [`atai-operational-state-monitoring-agent-data-prep`](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-operational-state-monitoring-agent-data-prep) for the role files): * [operational-state-monitoring-agent-example-larco-quickstart](https://github.com/archetypeai/operational-state-monitoring-agent-example-larco-quickstart) — washing-machine vibration (LARCO, 9 channels at 200 Hz) → an OSM agent fitted on the platform: an Optimizations search, the best trial promoted to a blueprint, one Evals test, then a bundle delivered to a second machine and scored against its held-back labels (fill / wash / spin / drain). * [operational-state-monitoring-agent-example-larco](https://github.com/archetypeai/operational-state-monitoring-agent-example-larco) — the full study behind the quickstart: all 199 cycles of two machines, a simple vibration-level baseline compared at every stage, a 16-trial search, then a test on new settings and delivery to the second machine (106 cycles). Includes the packed role files, so you can skip the data preparation. If you build something with these skills, open a PR against [agent-skills](https://github.com/archetypeai/agent-skills) to share your patterns — the empirical gotchas in each `SKILL.md` came from real production runs and we'd love more. # NVIDIA VSS with Newton Fusion Source: https://docs.archetypeai.app/integrations/nvidia-vss Use Newton Fusion as the video model (VLM) of NVIDIA's Video Search and Summarization (VSS) blueprint, through Newton Fusion's OpenAI-compatible endpoint. NVIDIA's [Video Search and Summarization (VSS)](https://github.com/NVIDIA-AI-Blueprints/video-search-and-summarization) blueprint answers questions about videos with an agent: an LLM plans, and a vision language model (VLM) looks at the video. VSS can call any **remote VLM** that speaks the OpenAI Chat Completions API. This guide sets up **Newton Fusion** as that VLM, through **Newton Fusion's OpenAI-compatible endpoint**. With this setup, Newton Fusion receives the **full video with its audio**. It sees the frames and hears what is said (as a transcript), so it can answer questions about both. VSS needs configuration changes only, no code changes. This example runs on an **NVIDIA DGX Spark** (GB10 Grace Blackwell, 128 GB unified memory). Newton Fusion, the VSS agent's LLM (NVIDIA Nemotron Nano 9B v2) and the rest of VSS all run on the one box, with no cloud calls at run time. **Newton Fusion's OpenAI-compatible endpoint is not publicly distributed yet.** The Newton Fusion model weights and the software that serves them are provided by Archetype AI. To run this integration, contact [support@archetypeai.dev](mailto:support@archetypeai.dev). The VSS web UI on a DGX Spark: an assembly video on the left, and the VSS Agent's description of it on the right, produced by Newton Fusion ## How it works How VSS calls Newton Fusion on a DGX Spark: the VSS agent plans with Nemotron, fetches the video from VST, and sends the full MP4 with audio to Newton Fusion's OpenAI-compatible endpoint, where Whisper transcribes the audio for Newton Fusion 1. You ask a question about an uploaded video. 2. The VSS agent's planner (Nemotron) decides to call its `video_understanding` tool. 3. VSS sends the video to Newton Fusion's endpoint as a Chat Completions request, with the MP4 inline. 4. Newton Fusion answers from the frames and the speech transcript. Nemotron then writes the final reply. ### Models | Role in VSS | Model | Runs as | Memory on the DGX Spark | | - | - | - | - | | VLM (video understanding) | **Newton Fusion F1.0** | Newton Fusion's OpenAI-compatible endpoint | \~47 GB at 64 frames per video, Whisper included | | Speech to text, feeding Newton Fusion | OpenAI Whisper large-v3 | Part of the same endpoint | (included above) | | LLM (planner) | NVIDIA Nemotron Nano 9B v2 FP8 | VSS's vLLM container | \~32 GB at `--gpu-memory-utilization 0.18` | Newton Fusion replaces VSS's default local VLM (NVIDIA Cosmos), which isn't deployed. ### Why the model is called `newton-fusion-omni-f1.0` VSS 3.2.1 decides what to send its VLM **from the model's name**: | Model name | What VSS sends | | - | - | | contains `omni`, with `ENABLE_AUDIO=true` | the full MP4, **with audio** | | contains `cosmos` | the full MP4, no audio | | anything else | JPEG frames only; **audio is dropped** | Newton Fusion's endpoint therefore serves the model under the name `newton-fusion-omni-f1.0`, so VSS sends it the whole video with its sound. The weights are the same as Newton Fusion F1.0. ## Requirements * An NVIDIA DGX Spark, with Docker and the NVIDIA container runtime (included in DGX OS) * NVIDIA VSS **3.2.1** * An NGC personal key with the **NGC Catalog** service, to pull the VSS containers (step 2) * Newton Fusion's endpoint package from Archetype AI (step 0) Steps are labelled **Workstation** (your laptop or desktop), **Spark** (a shell on the DGX Spark) or **Browser**. ## Set it up Contact [support@archetypeai.dev](mailto:support@archetypeai.dev) for the endpoint package. It contains the serving software for the DGX Spark (arm64, CUDA), its configuration, and the Newton Fusion F1.0 and Whisper large-v3 weights (\~38 GB). Copy the package to the DGX Spark and follow its README to place the weights. Newton Fusion's weights and the Whisper weights are both required: Whisper is what lets Newton Fusion use the audio. Start the endpoint as described in the package README. Loading the models takes about 3 minutes. The endpoint then listens on port `9095` and accepts two model names: `newton-fusion-omni-f1.0` (use this one with VSS) and `f1.0`. Check that it answers: ```bash theme={"system"} curl -s localhost:9095/v1/chat/completions -H 'Content-Type: application/json' \ -d '{"model":"newton-fusion-omni-f1.0","messages":[{"role":"user","content":"Say OK."}],"max_tokens":200}' ``` The first request after start-up takes up to a minute (one-time GPU setup); later ones answer in seconds. VSS sends the MP4 inline, base64-encoded, as a `video_url` content part: ```bash theme={"system"} python3 - <<'EOF' import base64, json, urllib.request video = base64.b64encode(open("my_video.mp4", "rb").read()).decode() body = { "model": "newton-fusion-omni-f1.0", "max_tokens": 4096, "temperature": 0, "messages": [{"role": "user", "content": [ {"type": "text", "text": "Describe what happens in this video, step by step, with times."}, {"type": "video_url", "video_url": {"url": f"data:video/mp4;base64,{video}"}}, ]}], } req = urllib.request.Request("http://localhost:9095/v1/chat/completions", json.dumps(body).encode(), {"Content-Type": "application/json"}) print(json.load(urllib.request.urlopen(req, timeout=900))["choices"][0]["message"]["content"]) EOF ``` Requests are limited to 64 MiB, so keep videos under about 45 MB (base64 adds a third). Newton Fusion sees 64 frames per video, at low resolution, so 480p video loses nothing. VSS's containers come from NVIDIA's container registry, `nvcr.io`. 1. Sign in at [ngc.nvidia.com](https://ngc.nvidia.com). Open your profile (top right) → **Setup** → **Generate Personal Key**. 2. Under **Services Included**, select **NGC Catalog**. That's the only service needed here: Newton Fusion and Nemotron both run on the DGX Spark, so **Public API Endpoints** (NVIDIA-hosted models) is optional. 3. Generate the key and copy it (`nvapi-…`). It's shown only once. On the DGX Spark, export it and test the login: ```bash theme={"system"} export NGC_CLI_API_KEY=nvapi-... export NVIDIA_API_KEY=$NGC_CLI_API_KEY # VSS expects both; the same value is fine here echo "$NGC_CLI_API_KEY" | docker login nvcr.io -u '$oauthtoken' --password-stdin # literal $oauthtoken ``` `Login Succeeded` means the key works. A bare `unauthorized` means **NGC Catalog** isn't on the key. VSS uses fixed container names and host ports (3000, 7777, 8000, 30000, 30001, 30081, 30888), so only one VSS deployment can run on a machine. Check for one: ```bash theme={"system"} docker ps -a --filter label=com.docker.compose.project=mdx --format '{{.Names}}\t{{.Status}}' ``` VSS's `dev-profile.sh up` (next step) removes an existing VSS deployment **with its volumes**, then deletes **every unused Docker volume on the host**, not only VSS's. On a machine shared with other projects, check with their owners first, and run it with `--dry-run` to see what it will do. Get VSS 3.2.1: ```bash theme={"system"} git clone --branch v3.2.1 --depth 1 https://github.com/NVIDIA-AI-Blueprints/video-search-and-summarization cd video-search-and-summarization/deploy/docker ``` Make two file edits that no command-line flag covers: ```bash theme={"system"} # Keep the audio: with the "omni" model name, VSS then sends the full MP4 with its sound. sed -i 's|^ENABLE_AUDIO=.*|ENABLE_AUDIO=true|' developer-profiles/dev-profile-base/.env # Give Nemotron 18% of the memory instead of 85%, leaving room for Newton Fusion. sed -i '/- --gpu-memory-utilization/{n;s|"0\.85"|"0.18"|}' services/nim/nvidia-nemotron-nano-9b-v2-fp8/compose.yml ``` Then deploy, pointing VSS at Newton Fusion's endpoint: ```bash theme={"system"} export VLM_ENDPOINT_URL=http://172.17.0.1:9095 # the host, as seen from VSS's containers; no /v1 export OPENAI_API_KEY=unused # the endpoint doesn't check it # --use-remote-vlm takes no value: it skips VSS's own VLM and calls VLM_ENDPOINT_URL instead scripts/dev-profile.sh up -p base -H DGX-SPARK -e \ --llm nvidia/NVIDIA-Nemotron-Nano-9B-v2-FP8 \ --use-remote-vlm \ --vlm-model-type nim \ --vlm newton-fusion-omni-f1.0 ``` `` is the address your browser uses to reach the DGX Spark. `172.17.0.1` is Docker's default bridge gateway; check yours with `ip -4 addr show docker0`. On first start, Nemotron downloads its weights (\~10 GB), which takes several minutes. Compared with NVIDIA's [remote VLM example](https://docs.nvidia.com/vss/latest/vss-agent/configure-vlm.html) (GPT-5.2 on OpenAI): | NVIDIA's example | For Newton Fusion | Why | | - | - | - | | `VLM_ENDPOINT_URL=https://api.openai.com` | `http://172.17.0.1:9095` | Newton Fusion's endpoint on the same DGX Spark | | `--vlm-model-type openai` | `--vlm-model-type nim` | In VSS 3.2.1, `openai` ignores `VLM_ENDPOINT_URL`, and `vllm` rejects the extra field VSS adds when sending audio. `nim` uses the URL and passes the request through | | `--vlm gpt-5.2` | `--vlm newton-fusion-omni-f1.0` | `omni` in the name, with `ENABLE_AUDIO=true`, means the full MP4 with audio | | `--llm-device-id 0` | `-H DGX-SPARK --llm …-FP8` | The DGX Spark profile; the FP8 Nemotron fits beside Newton Fusion | Open `http://:3000`. Upload a video (**+ Upload Video**), select it, click **+ Chat**, and ask, for example, *"Describe what's going on in the video."* Answers take 1–3 minutes. To confirm that Newton Fusion answered, on the DGX Spark: ```bash theme={"system"} docker logs vss-agent 2>&1 | grep "Using VLM profile" # nim_vlm, vlm_mode: remote, enable_audio: True, ..., use_video_file_base64: True docker logs vss-agent 2>&1 | grep "audio preserved" # one line per question: Downloading MP4 for inline base64 payload (audio preserved) ``` `use_video_file_base64: True` means VSS sends the full MP4, not frames. ```bash theme={"system"} cd video-search-and-summarization/deploy/docker scripts/dev-profile.sh down --dry-run # optional: print what it will do scripts/dev-profile.sh down ``` Then stop Newton Fusion's endpoint as described in the package README. `dev-profile.sh down` deletes the deployment's volumes (uploaded videos, the VST database), **every unused Docker volume on the host**, and VSS's data folder. To keep the uploads, run `docker compose -p mdx down` (without `-v`) instead. ## Tips * **Name the video and the tool in the question, and ask for one call.** Nemotron sometimes replies with a clarifying question, or calls Newton Fusion several times and rewrites its answer. This wording keeps it to one call, with Newton Fusion's answer passed through: > Analyze the video "\" with video\_understanding. Call it once, on the whole video, with my request below word for word as its user\_prompt, and present its result as your answer without analyzing again: \ In our tests it cut a typical answer from about 220 s to about 100 s. * **Ask for an explicit format for time stamps**, such as *"Put each step on its own line, in the form "MM:SS - MM:SS: what happens", using the actual times from the video."* With a looser request, Newton Fusion may answer in one paragraph, and Nemotron may then invent step times when it rewrites the answer. * **Ask about what is said, not other sounds.** Newton Fusion hears a video through its speech transcript, so narration and dialogue come through, but alarms, engines or music mostly don't. * **Prefer Newton Fusion's answer when the two differ.** Newton Fusion answers deterministically (temperature 0). Nemotron's rewrite is where details get dropped or changed. ## Known issues | Symptom | Cause and fix | | - | - | | VLM error 401 naming `platform.openai.com` | `--vlm-model-type openai` ignores `VLM_ENDPOINT_URL`. Use `nim` | | `unexpected keyword argument 'mm_processor_kwargs'` | `--vlm-model-type vllm` with the `omni` name. Use `nim` | | 404 on `/v1/v1/chat/completions` | `VLM_ENDPOINT_URL` ends in `/v1`. Remove it | | 404 `model_not_found` | `--vlm` isn't `newton-fusion-omni-f1.0` or `f1.0` | | VSS sends frames, not the MP4 | `ENABLE_AUDIO` was exported instead of set in `developer-profiles/dev-profile-base/.env` | | Nemotron restarts with "Free memory on device … less than desired GPU memory utilization" | Its memory share is too high beside Newton Fusion. Set it to `0.18` (step 4) | | A question about **part** of a video fails | VSS's video storage can cut partial clips whose video header can't be read up front. Archetype's endpoint package re-encodes such clips before they reach the model; if you still see this, contact support | | The first answer after a restart is slow | Normal: one-time GPU setup. Send one request before a demo | | An answer appears even with Newton Fusion stopped | It comes from the chat history. Test in a new chat | # Developer Quickstart Source: https://docs.archetypeai.app/introduction/getting-started Run your first Direct Query calls against the Newton Fusion and Newton Omega models — analyze a video and detect a machine fault from real sensor data, in a few lines of Python. ## Before you Begin You'll need Python 3.10+ and an API key. 1. Go to the API Keys page (e.g. [console.u1.archetypeai.app/profile/api-keys](https://console.u1.archetypeai.app/profile/api-keys)) to create an API key. 2. Complete the [Python Client Setup](/libraries/python), or install directly as shown below. Don't have an API key yet? [Request a free trial](https://forms.gle/yTu6xp7CCEvAYLqB9) to get access and register your interest in a hands-on workshop. ## 1. Setup Create a virtual environment, install the Archetype AI python client, and configure your credentials: ```bash theme={"system"} python3 -m venv venv source venv/bin/activate pip install archetypeai export ATAI_API_KEY="insert_your_key" export ATAI_API_ENDPOINT="https://api.u1.archetypeai.app/v0.5" ``` **Note:** Replace `"insert_your_key"` with the actual API secret key created using the Console. For more on environment variables, see [Environment Variables](/libraries/environment-variables). The virtual environment matters: recent Python installs on macOS (Homebrew) and Debian/Ubuntu block system-wide installs, so a bare `pip install` fails with `externally-managed-environment`. If you see that error, activate the venv first. Conda environments work too — see [Python Client Setup](/libraries/python). Both examples below use the [Direct Query API](/api-reference/query): a single synchronous `POST /query` — no session lifecycle to manage. The `model` parameter selects which model runs against your inputs: * **Newton Fusion** (`Newton::c2_6_...`) — reasons over text, images, and video, and answers in natural language. * **Newton Omega** (`OmegaEncoder::...`) — encodes a window of time-series sensor readings into a fixed-size embedding vector per channel, for building classifiers and anomaly detectors. ## 2. Analyze a Video with the Newton Fusion Model This example uploads a video and asks the Fusion model to describe what happens in it. The platform decodes the clip and uniformly samples frames server-side — no client-side video tooling needed. Save the following as `fusion_example.py`: ```python fusion_example.py expandable theme={"system"} import json import os import sys from archetypeai.api_client import ArchetypeAI MODEL = "Newton::c2_6_8b_fp8_260424d7a55d5e" def make_client(): # The /v0.5 version path is required — without it every call 404s. endpoint = os.environ.get( "ATAI_API_ENDPOINT", "https://api.u1.archetypeai.app/v0.5").rstrip("/") if not endpoint.endswith("/v0.5"): endpoint += "/v0.5" return ArchetypeAI(os.environ["ATAI_API_KEY"], api_endpoint=endpoint) def main(): client = make_client() # Analyze the sample video, or pass your own .mp4 as an argument: # python fusion_example.py your_video.mp4 video_path = sys.argv[1] if len(sys.argv) > 1 else "delivery.mp4" # Upload the video. The returned file_id is the filename — reference # the file by this (not the fil_... file_uid) in your query. upload = client.files.local.upload(video_path) file_id = upload["file_id"] body = { "model": MODEL, "query": "Describe the actions in the video.", "instruction_prompt": "You are a perception agent analyzing activity " "in front of a house. Reply in 2-3 sentences.", "file_ids": [file_id], "max_frames": 32, # frames sampled server-side (default 32, max 64) "max_new_tokens": 256, } result = client.requests_post( f"{client.api_endpoint}/query", data_payload=json.dumps(body), additional_headers={"Content-Type": "application/json"}, ) # The model's answer is at response.response[0]. print(result["response"]["response"][0]) if __name__ == "__main__": main() ``` Download our sample delivery video to follow along: ```bash macOS / Linux theme={"system"} curl -L -o delivery.mp4 "https://drive.usercontent.google.com/download?id=1Asy5D47WiDF0mGgP_3krS_GhZFS_c0mv&confirm=t" ``` ```powershell Windows theme={"system"} curl.exe -L -o delivery.mp4 "https://drive.usercontent.google.com/download?id=1Asy5D47WiDF0mGgP_3krS_GhZFS_c0mv&confirm=t" ``` Then run it: ```bash theme={"system"} python fusion_example.py ``` To analyze a different video, pass the path as an argument. Try more clips from our [starter video library](https://drive.google.com/drive/folders/1iAT42EUpCEMj_sFvHvRAtJBTqSF_Jn-u?usp=drive_link), or use your own `.mp4`: ```bash theme={"system"} python fusion_example.py your_video.mp4 ``` ### What you should see After roughly 15 seconds, the model's description of the video prints to your terminal: ```text theme={"system"} A FedEx Ground driver exits the truck, carries a package across the driveway, and places it on the lawn before returning to the vehicle. The truck then drives away, leaving the driveway clear. ``` Keep `max_frames` at 64 or below. Values above 64 fail silently — the request returns 200, but the video is dropped and the model answers from priors. For longer clips, allow a generous client timeout: video decoding can take several minutes. ## 3. Detect a Machine Fault with the Newton Omega Model The Omega model turns a window of time-series sensor readings into a 768-dimensional embedding — no prompt needed. You send the raw numbers and get vectors back, ready for downstream classification or anomaly detection. This example runs the full cycle on real vibration data from a bearing run-to-failure experiment: 1. **Build an n-shot library** — embed a handful of labeled windows (healthy and degraded). 2. **Classify held-out windows** the library has never seen, with a k-nearest-neighbors vote over the embeddings. 3. **Score the predictions** against ground-truth labels. Download the sample data (a \~54 MB subset of the NASA IMS Bearing Dataset — see the attribution note below): ```bash macOS / Linux theme={"system"} curl -sL --remote-name-all "https://raw.githubusercontent.com/archetypeai/agent-skills/main/skills/atai-newton-omega-model/references/sample_data/bearing_{healthy,degraded,inference,labels}.csv" ``` ```powershell Windows theme={"system"} curl.exe -sL --remote-name-all "https://raw.githubusercontent.com/archetypeai/agent-skills/main/skills/atai-newton-omega-model/references/sample_data/bearing_{healthy,degraded,inference,labels}.csv" ``` On Windows, use `curl.exe` — in PowerShell, plain `curl` is an alias for `Invoke-WebRequest`, which rejects these flags. Save the following as `omega_example.py`: ```python omega_example.py expandable theme={"system"} import csv import json import math import os from concurrent.futures import ThreadPoolExecutor from archetypeai.api_client import ArchetypeAI MODEL = "OmegaEncoder::omega_embeddings_1_4" WINDOW = 1024 # timesteps per window (the encoder handles 16-1024) CHANNEL = "bearing_1" # the bearing that fails in this experiment TEST_WINDOWS = 20 # held-out windows to classify (~1000 available) def make_client(): # The /v0.5 version path is required — without it every call 404s. endpoint = os.environ.get( "ATAI_API_ENDPOINT", "https://api.u1.archetypeai.app/v0.5").rstrip("/") if not endpoint.endswith("/v0.5"): endpoint += "/v0.5" return ArchetypeAI(os.environ["ATAI_API_KEY"], api_endpoint=endpoint) def read_column(csv_path, column, cast=float): """Read one column from a CSV into a list.""" with open(csv_path, newline="") as csv_file: reader = csv.reader(csv_file) index = next(reader).index(column) return [cast(row[index]) for row in reader] def embed(client, values): """Embed one window (16-1024 timesteps) into a 768-d vector.""" body = { "model": MODEL, "query": "", "normalize_input": False, "events": [ {"type": "data.numeric_array", "event_data": {"contents": [values]}} ], } result = client.requests_post( f"{client.api_endpoint}/query", data_payload=json.dumps(body), additional_headers={"Content-Type": "application/json"}, ) return result["response"]["response"] def knn_predict(embedding, library, k=3): """Majority vote among the k nearest labeled library embeddings.""" distances = sorted( (math.dist(embedding, lib_embedding), label) for lib_embedding, label in library ) votes = [label for _, label in distances[:k]] return max(set(votes), key=votes.count) def main(): client = make_client() # 1. Build a small n-shot library from the labeled shot files. # Normalize every window with ONE scaler fit on the library pool — # per-window normalization would erase the fault's amplitude signal. healthy = read_column("bearing_healthy.csv", CHANNEL) degraded = read_column("bearing_degraded.csv", CHANNEL) pool = healthy + degraded mean = sum(pool) / len(pool) std = (sum((value - mean) ** 2 for value in pool) / len(pool)) ** 0.5 def scale(values): return [(value - mean) / std for value in values] starts = range(0, len(healthy) - WINDOW + 1, 256) # overlapping shots shots = [(scale(healthy[s:s + WINDOW]), "healthy") for s in starts] shots += [(scale(degraded[s:s + WINDOW]), "degraded") for s in starts] with ThreadPoolExecutor(max_workers=8) as pool_executor: vectors = list(pool_executor.map( lambda shot: embed(client, shot[0]), shots)) library = [(vector, label) for vector, (_, label) in zip(vectors, shots)] print(f"n-shot library: {len(library)} labeled windows") # 2. Classify held-out windows the library has never seen. # bearing_inference.csv has no label column, so leakage is impossible. timestamps = read_column("bearing_inference.csv", "timestamp", cast=int) series = read_column("bearing_inference.csv", CHANNEL) # Non-overlapping windows that don't span a gap in the recording, # evenly spread across the timeline. all_starts = [ start for start in range(0, len(series) - WINDOW + 1, WINDOW) if timestamps[start + WINDOW - 1] - timestamps[start] == WINDOW - 1 ] stride = max(1, len(all_starts) // TEST_WINDOWS) test_starts = all_starts[::stride][:TEST_WINDOWS] with ThreadPoolExecutor(max_workers=8) as pool_executor: predictions = list(pool_executor.map( lambda start: knn_predict( embed(client, scale(series[start:start + WINDOW])), library), test_starts)) # 3. Score against the ground-truth labels (used ONLY for scoring). truth_by_timestamp = dict(zip( read_column("bearing_labels.csv", "timestamp", cast=int), read_column("bearing_labels.csv", "label", cast=str))) truths = [truth_by_timestamp[timestamps[start]] for start in test_starts] for start, pred, truth in zip(test_starts, predictions, truths): marker = "ok" if pred == truth else "MISS" print(f" ts={timestamps[start]:>8} predicted={pred:<8} truth={truth:<8} {marker}") # Metrics with "degraded" as the positive class: did we catch the fault? pairs = list(zip(predictions, truths)) correct = sum(pred == truth for pred, truth in pairs) true_pos = sum(pred == truth == "degraded" for pred, truth in pairs) true_neg = sum(pred == truth == "healthy" for pred, truth in pairs) false_pos = sum(pred == "degraded" and truth == "healthy" for pred, truth in pairs) false_neg = sum(pred == "healthy" and truth == "degraded" for pred, truth in pairs) precision = true_pos / (true_pos + false_pos) if true_pos + false_pos else 0.0 recall = true_pos / (true_pos + false_neg) if true_pos + false_neg else 0.0 f1 = 2 * precision * recall / (precision + recall) if precision + recall else 0.0 print("confusion matrix (rows: truth, cols: predicted)") print(f"{'':>16}{'healthy':>9}{'degraded':>10}") print(f"{'healthy':>16}{true_neg:>9}{false_pos:>10}") print(f"{'degraded':>16}{false_neg:>9}{true_pos:>10}") print(f"accuracy : {correct}/{len(pairs)} = {correct / len(pairs):.0%}") print(f"precision: {precision:.3f} recall: {recall:.3f} f1: {f1:.3f}" f" (positive class: degraded)") if __name__ == "__main__": main() ``` Run it: ```bash theme={"system"} python omega_example.py ``` ### What you should see The 28 embedding calls fan out 8-way in parallel; the run takes about 30 seconds: ```text theme={"system"} n-shot library: 8 labeled windows ts= 3000000 predicted=degraded truth=healthy MISS ts= 3051200 predicted=healthy truth=healthy ok ts= 3102400 predicted=healthy truth=healthy ok ... ts=18902624 predicted=degraded truth=degraded ok ts=18953824 predicted=degraded truth=degraded ok confusion matrix (rows: truth, cols: predicted) healthy degraded healthy 10 1 degraded 0 9 accuracy : 19/20 = 95% precision: 0.900 recall: 1.000 f1: 0.947 (positive class: degraded) ``` 19 of 20 held-out windows classified correctly from just 8 labeled examples — no model training, no feature engineering. The one miss is a borderline window at the very start of the recording; a larger library, or embedding all four sensor channels jointly, resolves it. The [`atai-newton-omega-model` skill](https://github.com/archetypeai/agent-skills/tree/main/skills/atai-newton-omega-model) runs this same pipeline at full scale — all \~1000 held-out windows, 4-channel joint embeddings, precision/recall reporting. The encoder handles window lengths of 16 to 1024 timesteps natively. Shorter windows are padded and masked internally; inputs over 1024 are truncated to the last 1024 points. **Data attribution:** the sample files are a curated subset of the **NASA IMS Bearing Dataset** (Set 2: a bearing run-to-failure experiment with four accelerometer channels), produced by the University of Cincinnati Center for Intelligent Maintenance Systems (IMS) and distributed via the [NASA Prognostics Data Repository](https://www.nasa.gov/intelligent-systems-division/discovery-and-systems-health/pcoe/pcoe-data-set-repository/). If you use this data in a publication or redistribute it, include NASA's requested citation: J. Lee, H. Qiu, G. Yu, J. Lin, and Rexnord Technical Services (2007). *Bearing Data Set*, IMS, University of Cincinnati. NASA Prognostics Data Repository, NASA Ames Research Center, Moffett Field, CA. ## Try Variations * **Edit the query and instruction prompt** — ask the Fusion model for structured output by making the prompt the schema, for example: `Respond with ONLY a JSON object: {"activity": "", "confidence": <0..1>}`. * **Adjust `max_frames`** — compare `8` vs `32` on the same clip: more frames capture more temporal detail at the cost of latency. * **Send images instead of video** — pass an uploaded `.png` or `.jpg` in `file_ids` and ask the Fusion model to describe or extract data from it. * **Vary the Omega window length** — change `WINDOW` to 64 or 256 timesteps and see how accuracy holds up; pick the length that fits your signal's dynamics (use the same length for the library and the test windows). * **Evaluate more held-out windows** — raise `TEST_WINDOWS` from 20 toward the \~1000 available; each window is one independent `/query` call. ## Build with a Coding Agent Do you have a dataset you want to try further? Use the [Agent Skills](https://github.com/archetypeai/agent-skills) with your favorite coding agent, or read the [Direct Query API reference](/api-reference/query). The official [Agent Skills](/for-agents/agent-skills) teach coding agents like Claude Code, Cursor, and Codex these exact patterns — including the gotchas — so you can say "run this clip through Newton and tell me if the assembly passed" and let the agent write the code. ## Troubleshooting If you're getting errors, see the [Troubleshooting](/support/troubleshooting) page for common issues and solutions, or check the [Python Client](/libraries/python) documentation for installation and upgrade instructions. Error responses share a common shape — see [Errors](/api-reference/errors). ## Learn More Full request and response reference for the /query endpoint. Teach your coding agent (Claude Code, Cursor, Codex) to build on Newton. Learn the fundamentals of the Newton AI platform. Manage your data uploads and supported file formats. Customize Newton models with your own data. Working demos built on these patterns, from traffic analysis to wind-turbine fault detection. # Overview Source: https://docs.archetypeai.app/introduction/overview What the Archetype platform is: the Newton foundation model for physical AI, platform capabilities, and where to start. The Archetype platform is a Physical AI platform designed to help you build systems that perceive, reason, and act in the real world. It's powered by a proprietary foundation model, Newton, which fuses multimodal sensor data - optical, radar, acoustic, motion, temperature, and more - to enable real-time perception, reasoning, and decision-making across machines, environments, and people. Archetype AI Platform Architecture ## About Newton Newton is Archetype AI's foundation model designed specifically for understanding the physical world through sensor data, a fundamentally different problem than what most AI models are built for. While large language models are trained predominantly on text (roughly 80%) with images and video as secondary modalities, Newton inverts this ratio: it's trained on approximately 50% physical sensor data (vibration, temperature, electrical current, motion) with video and text as supporting inputs. The architectural difference matters too. Standard multimodal models treat each input type separately, processing text in one pathway and images in another. Newton instead fuses hundreds of sensor modalities together, learning to reason across them simultaneously—because in the physical world, understanding a machine failure or a safety incident requires correlating vibration patterns with power draw with temperature with visual context, not analyzing each in isolation. The result is a model that can interpret raw sensor streams and respond to natural language queries about physical systems, enabling someone to ask "what's causing this motor to overheat?" rather than building a custom ML pipeline for that specific question. ### How Newton Processes Physical Data Newton combines two core components to bridge raw sensor data and human understanding: How Newton Sees the Physical World 1. **Physical World Model:** Ingests time-series sensor data (motion, power, electrical signals) and video streams capturing machine and human behavior. This layer can process many types of physical sensors without requiring model retraining, enabling capabilities like trajectory prediction, multivariate analysis, anomaly detection, and classification. 2. **Semantic World Model:** Translates between physical data and natural language, allowing you to interact with sensor streams conversationally—like talking with a human expert. You can provide scene descriptions and custom prompts to query presence, activity, and intent. ## Platform Capabilities With the Archetype platform you can: * **Access Newton through standard APIs:** Tap into Newton, the multimodal foundation model that fuses physical measurements and sensor data into unified understanding. Build Physical AI use cases via Python bindings or REST APIs, with just a few lines of code. Go to the API Keys page (e.g. [console.u1.archetypeai.app/profile/api-keys](https://console.u1.archetypeai.app/profile/api-keys)) to create an API Key. * **Connect any sensor or data source:** Easily integrate data from diverse sensors, devices, and systems. This includes real time or pre-recorded data, enabling analysis, testing, and simulation within a single environment. The platform allows customers to create and deploy systems that monitor, optimize, and automate complex physical operations. Early enterprise customers — including NTT DATA, Kajima, and the City of Bellevue — have already deployed systems to increase efficiency, reduce downtime, and improve safety in environments ranging from warehouses and construction sites to city streets. [Learn more](https://www.archetypeai.io/solutions). Overall, the Archetype platform is designed to accelerate the development and deployment of the Newton foundation model into real-world systems, enabling faster iteration and scaling of Physical AI applications. ## Get Started Get up and running with the Archetype platform. Install and use the Python SDK. Example code and sample applications. Teach your coding agent (Claude Code, Cursor, Codex) to build on Newton. Contact us for support. # Environment Variables Source: https://docs.archetypeai.app/libraries/environment-variables Configure environment variables for the Archetype AI platform. The Archetype AI Python client uses environment variables for authentication and API configuration. ## Required Variables ### ATAI\_API\_KEY Your unique API key for authenticating with the Archetype platform. ```bash theme={"system"} export ATAI_API_KEY="your_api_key_here" ``` To obtain an API key, contact [support@archetypeai.dev](mailto:support@archetypeai.dev). ### ATAI\_API\_ENDPOINT The API endpoint URL for the Archetype platform, **including the API version path**. ```bash theme={"system"} export ATAI_API_ENDPOINT="https://api.u1.archetypeai.app/v0.5" ``` The version path is required — an endpoint without it (e.g. `https://api.u1.archetypeai.app`) fails with 404 errors, which the Python client surfaces as an empty `ApiError: {}`. The version depends on the service: most APIs (query, files, batch) use `/v0.5`, while the [Fine-Tuning Service](/api-reference/fine-tuning/create-job) uses `/v0.6`. ## Setting Environment Variables Add the following to your shell configuration file (`~/.bashrc`, `~/.zshrc`, or similar): ```bash theme={"system"} export ATAI_API_KEY="your_api_key_here" export ATAI_API_ENDPOINT="https://api.u1.archetypeai.app/v0.5" ``` Then reload your shell: ```bash theme={"system"} source ~/.bashrc # or ~/.zshrc ``` ## Verifying Configuration To verify your environment variables are set correctly: ```bash theme={"system"} echo $ATAI_API_KEY echo $ATAI_API_ENDPOINT ``` Both should display the values you configured. # Overview Source: https://docs.archetypeai.app/libraries/libraries Set up your development environment to use the Archetype API with a client library in your preferred language This page covers setting up your local development environment to use the Archetype API. You can use one of our officially supported client libraries or your own preferred HTTP client. ## Export an API Key Before you begin, you'll need an API key to securely access the API across all client libraries. For support with API keys, please contact [support@archetypeai.dev](mailto:support@archetypeai.dev). Don't have an API key yet? [Request a free trial](https://forms.gle/yTu6xp7CCEvAYLqB9) to get access and register your interest in a hands-on workshop. Once you have your API key, store it in a safe location and export it as an environment variable in your terminal. Export your key by running the following in your terminal: ```bash theme={"system"} echo "export ATAI_API_KEY='yourkey'" >> ~/.zshrc ``` Reload your shell to activate the change: ```bash theme={"system"} source ~/.zshrc ``` Export your key by running the following in your terminal: ```bash theme={"system"} echo "export ATAI_API_KEY='yourkey'" >> ~/.bash_profile ``` Reload your shell to activate the change: ```bash theme={"system"} source ~/.bash_profile ``` Archetype client libraries are configured to automatically read your API key from the system environment. ## Install an Official Client Library Archetype provides an official client library for Python, with more languages coming soon. Official Python client for the Archetype platform You can find the official Python client for the Archetype platform on GitHub at [https://github.com/archetypeai/python-client](https://github.com/archetypeai/python-client). ## Request a Library Don't see a library for your preferred language? We'd love to hear from you. Contact us at [support@archetypeai.dev](mailto:support@archetypeai.dev) to request support for additional languages such as JavaScript, Go, Rust, or others. # Python Source: https://docs.archetypeai.app/libraries/python Install the official Python client on macOS, Linux, or Windows, verify the installation, and keep it up to date. The official Python client for the Archetype platform provides a simple interface to interact with the Archetype API. View source code, examples, and documentation ## Requirements * Python 3.10 or later * An Archetype API key (see [Libraries](/libraries) for setup instructions) ## Install Create a virtual environment, install the client, and set your credentials for your operating system: macOS ships with `python3`. Recent Homebrew and system Pythons block system-wide installs (PEP 668), so create a virtual environment first — a bare `pip install` fails with `externally-managed-environment`: ```bash theme={"system"} python3 -m venv venv source venv/bin/activate pip install archetypeai ``` Set your credentials in the activated shell (or persist them in `~/.zshrc`): ```bash theme={"system"} export ATAI_API_KEY="your_secret_key" export ATAI_API_ENDPOINT="https://api.u1.archetypeai.app/v0.5" ``` Debian and Ubuntu need the `venv` module installed separately, and their Pythons block system-wide installs (PEP 668), so create a virtual environment first: ```bash theme={"system"} sudo apt update && sudo apt install -y python3-venv python3 -m venv venv source venv/bin/activate pip install archetypeai ``` Set your credentials in the activated shell (or persist them in `~/.bashrc`): ```bash theme={"system"} export ATAI_API_KEY="your_secret_key" export ATAI_API_ENDPOINT="https://api.u1.archetypeai.app/v0.5" ``` Check your Python version first — the client needs 3.10 or later: ```bash theme={"system"} python3 --version ``` **If it shows 3.10 or later**, create the virtual environment with `python3` directly: ```bash theme={"system"} python3 -m venv venv source venv/bin/activate pip install archetypeai ``` **If it's older than 3.10**, install a newer interpreter first and use it instead — the package name varies by release, so check what's available (`dnf list 'python3.*'`): ```bash theme={"system"} sudo dnf install -y python3.11 python3.11-pip python3.11 -m venv venv source venv/bin/activate pip install archetypeai ``` Set your credentials in the activated shell (or persist them in `~/.bashrc`): ```bash theme={"system"} export ATAI_API_KEY="your_secret_key" export ATAI_API_ENDPOINT="https://api.u1.archetypeai.app/v0.5" ``` Install Python 3.10+ from [python.org](https://www.python.org/downloads/) (check **Add python.exe to PATH** during setup). If you're in a console-only session (SSM/SSH), install silently from PowerShell instead (adjust to the latest Python release): ```powershell theme={"system"} Invoke-WebRequest -Uri "https://www.python.org/ftp/python/3.12.10/python-3.12.10-amd64.exe" -OutFile "$env:TEMP\python-installer.exe" & "$env:TEMP\python-installer.exe" /quiet InstallAllUsers=1 PrependPath=1 Include_launcher=1 ``` **Important either way:** open a new PowerShell window afterward — PATH changes don't reach the existing session. Then: ```powershell theme={"system"} py -m venv venv .\venv\Scripts\Activate.ps1 pip install archetypeai ``` If activation is blocked by the execution policy, allow local scripts first: ```powershell theme={"system"} Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser ``` Set your credentials for the current session (use `setx` to persist them for new sessions): ```powershell theme={"system"} $env:ATAI_API_KEY = "your_secret_key" $env:ATAI_API_ENDPOINT = "https://api.u1.archetypeai.app/v0.5" ``` On other Linux distributions, the same pattern applies: ensure Python 3.10+ is installed, create and activate a virtual environment, then `pip install archetypeai`. For more on credentials, see [Environment Variables](/libraries/environment-variables). If you prefer [Anaconda or Miniconda](https://www.anaconda.com/download/success) to manage Python environments, create and activate an environment and install the client inside it: ```bash theme={"system"} conda create -n atai python=3.10 conda activate atai pip install archetypeai ``` ## Verify Installation Test that the client is correctly installed by running (inside your activated environment): ```bash theme={"system"} python -c "from archetypeai.api_client import ArchetypeAI; print(f'Version: {ArchetypeAI.get_version()}')" ``` If successful, you should see a version number printed: ```bash theme={"system"} Version: 26.04.30.0 ``` ## What's Included The Python client includes: * **API Client**: Core client for interacting with the Archetype platform * [**Examples**](https://github.com/archetypeai/python-client/tree/main/examples): Sample scripts demonstrating common use cases ## Upgrade Python Client * To show the currently installed version of the python client, please use ```bash theme={"system"} pip show archetypeai ``` * To upgrade to the latest version of the python client, please use ```bash theme={"system"} pip install --upgrade archetypeai ``` Please note the minimum requirements [here](https://docs.archetypeai.app/libraries/python#requirements). # v1.1.x Source: https://docs.archetypeai.app/release-notes/1.1.x These notes detail the new features, enhancements, and fixes included in each release of our platform. ## API & Services * **List endpoints across IAM, Data, Agent, and JOS services now use cursor pagination:** IAM list endpoints (orgs, users, superadmins, and API keys) are now bounded with a `limit` parameter (default 100, max 1000) and `after`/`before` cursors. File metadata lists replace shard- and offset-based paging with cursors, and all remaining agent service and JOS lists now return a `prev_cursor` for paging backwards. The v0.5 JOS API docs now also list the 400 response returned for invalid cursor parameters. * **Batch and fine-tuning job lists can now be sorted:** The v0.5 batch job list and v0.6 fine-tuning job list endpoints accept `sort` and `order` parameters. * **“Cancelled” is now spelled the British way throughout the Agent Service API:** Agent service identifiers now use British spelling (e.g., “cancelled”), matching the Job Orchestration Service. Check integrations that match on the old spelling. * **The platform Activity Monitor lens now runs on Newton C2.6:** The platform Activity Monitor lens has moved from C2.5 to C2.6, since the C2.5 model is no longer served in the Tokyo (ap-northeast-1) region. ## Agents * **Optimizations and Evals APIs have been added to the Agents API.** The Optimizations API takes a canonical blueprint and finds the best settings to use for your data. The Evals API scores that configuration once using test data you did not use for optimization, to let you judge the configuration's quality before deployment. For now, these are only supported with OSM blueprints. ## Console & UI * **The Agent Manager, File Library, and Batch Manager can now be sorted:** The Agent Manager has sortable column headers and a new `created_at` column. The file list can be sorted from its headers or a sort menu, and the batch manager now supports sorting too. * **Batch job input search now covers the whole job:** Searching the batch job Inputs tab now runs on the server, so it covers every input in the job instead of only the loaded page. * **The agent Runs tab now shows a run count:** The Runs tab on the agent page now shows how many runs an agent has. * **The side navigation account block is now a compact menu:** The account block in the side navigation now collapses to a menu that shows only your name. * **The Key ID column has been removed from the profile API keys list:** Users were mistaking the `key_` identifier for the API key itself. The column has been removed along with its copy button. * **The design system has been updated to 0.17.0:** The console now uses design system 0.17.0, which brings the paired type scale and an updated progress percentage display. ## Bug Fixes * **Fine-tuning jobs now report `finished_at`:** The `finished_at` field on fine-tuning jobs is now set when a job finishes, so it no longer always returns `null` and can be sorted on. * **Agents no longer go idle after a missed measurement:** A missed measurement no longer leaves an agent sitting idle. * **Lens latency and reliability fixes:** GPQ and session Redis calls in the Lens API no longer queue up behind a single lock, and `GlideManager.get_client()` no longer pings Redis while holding a lock. * **Video and RTSP windows now include FPS metadata:** Lens runner v2 now sends frame-rate (FPS) metadata with video and RTSP input windows. * **JOS now parks every interrupted job instead of resuming it immediately:** When a job is interrupted, JOS now parks it rather than trying to resume it on the spot. * **Blueprint “See example” cards no longer link to the prod playground:** The cards are now hidden unless the `playgroundApps` flag is on. Before, customer AWS deployments showed links to the standalone prod playground. ## **API & Services** * **All remaining list endpoints moved to cursor pagination**: The JOS registry lists and all eight v0.5 batch lists (jobs, events, inputs, inputs/progress, outputs, progress and both checkpoint lists) now use cursor pagination instead of the old `offset` and `total` response values. In addition, the per-entity array keys on the batch lists have been replaced by `data`. Each list keysets on `(created_at, id)` with new covering indexes, so deep pages stay fast and a row changing mid-scan neither skips nor repeats. * **The file list can be filtered by several MIME types at once**: `file_type` on `GET /v0.5/files/metadata` (and the internal metadata endpoint) now accepts a comma-separated list such as `image/png,image/jpeg` and returns files matching any entry. A single value behaves exactly as before, blank entries are ignored, and more than 50 types is rejected with an HTTP 400 response. * **The file list can be sorted**: `GET /v0.5/files/metadata` now lets you sort on creation timestamp, file size, file status, and file ID in either ascending or descending order. It uses sensible default sorting direction per field: newest and largest files first, statuses in lifecycle order, names A to Z. The `created_at` timestamp is now exposed in the public metadata as well. * **Stored file types are now derived from the filename, not the uploading client**: Every file upload path resolves `file_type` from the file extension, only falling back to the client-supplied type for unknown extensions, so two identical files can no longer exist under different types. `.json` and `.tsv` uploads are no longer rejected by the public upload handlers, and TSV attribute extraction still runs. Existing rows are not backfilled. * **The model list gained the filters a registry UI actually needs**: `GET /models` now accepts `model_family`, `scope` (`platform` | `org` | `all`), and a case-insensitive `search` over tag name, description, family and variant. All three AND with each other and with the pre-existing `variant` filter; an unknown `model_family` is a 400 rather than an empty page, and LIKE metacharacters in `search` are escaped so user text matches literally. * **Newton Omega 1.5 added as a platform model.** * **`GET /jobs` accepts the paused and interrupted statuses**: The v0.5 status parser rejected `PAUSED` and `INTERRUPTED` with a 400 while v0.6 accepted them; both versions now filter on the same status set. ## **Agents** * **The blueprint and bundle lists answer what the agent manager needs**: `GET /agents/blueprints?bundles_count=true` annotates each blueprint with the number of bundles visible to the caller's organization that are pinned to it, so a client can offer only blueprints that have agents. `GET /agents/bundles` accepts `sort` (with permitted values `created_at`, `last_run_at`, and `name`) and `order`, keeping the existing last-run-recency default. ## **Console & UI** * **Redesigned the UX for the Model Registry:** The grid of cards has been replaced with a table similar to the one used by the Batch Manager. Each row includes the parameters and context length (metadata not previously disclosed anywhere in the UX). Also added is support for search as well as model family and scope filters. The model details dialog has been redesigned as well, with better labeling and hierarchical structure. * **The Agent Manager can now be sorted**: A Sort menu sits between the search field and the view toggle, offering last run, created, and name as sorting options, with a second activation reversing the field and each direction named in the field's own words (Newest/Oldest for dates, A–Z for names). The Build Status filter is gone since it was rare for an agent’s status to be anything other than `Ready`, and the count was misleading due to the way it was calculated. * **The agents playground is embedded in the console**: A server-side reverse proxy serves the agents playground app under `/playground/agents`, injecting the caller's credentials as pass-through headers so the embedded app authenticates as the signed-in user. Cookies never cross the proxy in either direction, and path and query are forwarded untouched, so mounting a future playground app takes one list entry. * **The agents pages moved to a clearer URL hierarchy**: The agent gallery moves from `/dashboard/agents` to `/dashboard/blueprints`, joining the blueprint detail page already there, and the agent manager takes over `/dashboard/agents`. Bundle and run detail pages now nest under their parent, so a run reads as `/dashboard/agents/[id]/runs/[runId]`. Existing bookmarks to the old paths will need updating. * **The console side nav was consolidated**: The nav gains a stacked logo lockup and one flat nav list, and the account dropdown becomes an always-visible profile block at the bottom — an identity row (avatar, name, org · role, theme toggle) over a list of account rows, with Sign Out as a normal row rather than a separate destructive button. A full-bleed separator divides the block from the nav list above. * **Copy buttons behave the same everywhere**: Copying was implemented three ways across the Console, each with its own copied state, icons, delay and toast — or none, since seven places gave no feedback at all on success. Every call site now uses the design system's `copy-button` primitive, which owns copied state, feedback duration, toasting and click isolation, so every copy shows an inline check and a toast. * **Info tooltips render as a filled disc**: The console moved to design system 0.15.0 and adopted the new `Tooltip.Trigger variant="info"`, which draws its own mono `i` inside a filled 20px disc with the arrow centered on all four sides. Call sites that passed their own icon are unaffected, since children still take precedence. ## **Bug Fixes** * **A required checkpoint port is configurable in the Create Batch Job modal**: The modal folded a workflow's lone `checkpoint_ref` port into the `Model` select as a "Custom Checkpoint" option, which is right when the port is optional and wrong when it is required — `driving-behavior` needs a kNN classifier on the port *and* a summarizer through `model`, so folding them made the workflow impossible to configure. A required port now renders as its own control that can pick a promoted fine-tuned model from the registry, with a typed `ckp_` id as the fallback. * **The registry no longer offers dead links to fine-tuning jobs**: Models are org-scoped but fine-tuning jobs are owner-scoped, so a member could see a model and click through to a job they cannot open. Each lineage job is now looked up with the reader's own credentials when a model dialog opens; a 404 hides the Job row, while any other failure leaves it in place. * **A successful fine-tuning run no longer looks like a failure**: A run produces checkpoints, not a model, so the `fine_tuned_model` Overview row was empty until someone promoted a checkpoint — and it rendered as a bare em-dash, which reads as a job that failed. The row now says "Not promoted yet" with an info tooltip explaining that a checkpoint has to be promoted first, and the checkpoints table's Metrics column no longer collapses to 14px on the same page. ## API & Services * **Uploaded files now get a reliable integrity checksum on every upload path:** both the streaming/proxy upload path and the direct-to-cloud upload path now persist a CRC32C checksum on file metadata, closing a gap where the old MD5 checksum was only ever populated for the legacy streaming path. * **Job inputs can now be searched via the API:** `GET /jobs/{id}/inputs` accepts a case-insensitive substring `search` query parameter against a file's name or file ID, combinable with the existing port/status filters. This lets the console search a job's inputs server-side instead of filtering an already-loaded page. * **Jobs that get interrupted (e.g., by a pod eviction) can now recover automatically instead of staying stuck forever:** the job orchestration service will retry an interrupted job up to a configured retry budget, and will now actually fail a job once that budget is exhausted rather than leaving it parked indefinitely. * **The public Python client gained a runnable Anomaly Discovery example:** a new quick-start script mirrors the existing Operational State Monitoring and Rare Event Detection examples — it discovers the canonical Anomaly Discovery demo bundle, uploads sample sensor data, runs it, and reads back per-window anomaly scores — giving developers a working reference for building their own AD-based agents. ## Agents * **Agent bundles now configure models per slot instead of a single shared model:** the old `bundles.model` field has been replaced with `bundles.models`, a map from slot name to registry tag, so a bundle can pin a different model to each of its slots. This is a breaking change for any existing integration calling the public client's bundle-creation API with the old `model=` argument, which is now `models=`. * **Bundle creation now rejects broken model-slot references immediately instead of failing on every subsequent run:** creating or updating a bundle with a malformed `${models...}` override, or a slot name that can never actually be addressed, now returns a validation error at creation time. * **Agent artifact references now resolve correctly:** `agent://{id}` references to another agent's output are resolved more robustly at bundle-creation time. * **A new "driving behavior" analysis job type is now supported end to end:** a dedicated worker and pipeline ingest trip data together with a fine-tuned checkpoint and produce behavior summaries. * **Long-running agent activities can now report that they're still alive**, preventing legitimately long operations from being mistaken for a hang or failure. ## Console & UI * **The console's navigation was rebuilt around a single persistent sidebar, replacing the old top navigation bar:** every logged-in screen now shares one collapsible sidebar with a remembered collapse state and tooltips when collapsed, and account-management pages (profile, org admin, platform admin) get proper contextual navigation instead of unlabeled "back" buttons. * **Running certain agents now shows a progress bar during inference** instead of an unchanging spinner. * **The Agent Manager page now shows live run statuses** instead of only a static, last-known state. * **Anomaly Discovery and the Fusion models (Manual Generation Agent (MGA) and Task Verification Agent (TVA)) now walk you through running the agent on your own data, not just the built-in demo:** the "Try it out" flow for MGA and TVA leads with an install step and then creating/running an agent bundle against your own video, and Anomaly Discovery gained both a runnable example and a playground demo card. * **File Manager and Batch Manager terminology was clarified:** "Lenses" has been replaced with "agents" and "batch inference" is now "batch processing" in the File Manager UI, and a Batch Manager job-detail field was relabeled "Workflow key" to match the corresponding list-view column. * **The Agents page dropped a redundant "Agent" label and card outline** for a cleaner look. * **The agent configuration view now merges related configuration tables and shows reference defaults, and the bundle list is now ordered by last run** so recently-used bundles surface first. * **Several list views — batch jobs, fine-tuning jobs, and files — were migrated onto the newer design-system table component**, in some cases dropping an older grid view, for a more consistent look and better performance. * **The job-detail page now shows counts on its tab strips and groups its log feed by day**, making long-running jobs easier to scan. ## Security & Authentication * **API request validation is being hardened incrementally:** several job-orchestration endpoints now reject requests containing fields they don't recognize (previously such fields were silently ignored), and new declarative field validators plus organization-visibility checks are rolling out across services — some enforced immediately, others running in observe-only mode ahead of full enforcement. ## Bug Fixes * **Fixed the agent manager losing your blueprint filter (and other list state) when you navigated into an agent's detail page and back.** * **Fixed the public Python client's test installation and Python version requirements.** Installing the client's test extra (`pip install -e '.[test]'`) previously failed silently due to an invalid `setup.py` keyword; that's fixed, the client's stated minimum Python version was corrected to 3.10+ (matching what already worked in practice), and an incorrect upper bound that would have blocked installation on Python 3.14 was removed. * **Reliability fixes for agent memory usage and out-of-memory handling:** adjusted memory limits, added an additional memory-pages reclaim pass, and improved out-of-memory handling to reduce agent crashes under memory pressure. ## API & Services * **Introduced the new Agents API:** The Agents API lets you run and manage agents. Agents are bundles of resources that describe how to use Newton to perform a certain task. With an agent configured to perform a needed task, all you need to do is provide the input file or files and the agent will process your data and return the desired output. * **Updated the Python SDK with agent support and added examples for the five canonical agents:** Developers can now call these workflows directly using the Python public client library. * **Improved Fine-Tuning API support:** Fine-tuning jobs can now accept promoted fine-tuned models as input and track fine-tuning lineage on promoted models. ## Agents * Shipped our first five agents: * **Anomaly Discovery** * **Task Verification** * **Manual Generation** * **Operational State Monitoring** * **Rare Event Detection** * Use the Agents API to create new agents based on these agent blueprints, then run your agents either using the API or the Developer Console. ## Console & UI * **Added the Agent Gallery and Agent Manager dashboards:** View information about the canonical agent blueprints using the Agent Gallery, and use the Agent Manager to manage and run your agents from the Developer Console. * **A Model Registry UI was added to the Console, including card views, promotion, and deletion.** Users can browse registered models, promote a checkpoint to a model, and delete org-scoped models directly from the interface. * **Adopted a shared job-detail template across fine-tuning and agent runs:** Fine-tuning jobs and agent runs now share a consistent job-detail layout, including a health report view and a logs/events dialog on the runtime status page. ## Other * **Added CSV file format support to job processing:** Jobs can now ingest CSV-formatted input files. ## Bug Fixes * **Fixed a grammar issue in the File Manager UI:** Corrected a run-on sentence in the File Manager's upload help text. * **Fixed the CLI error output:** The `atai-cli` now shows the full error chain instead of only the outer context, making failures easier to diagnose. * **Fixed agent Jobs Orchestration Service status handling:** The JOS client now correctly handles `PAUSED` and `INTERRUPTED` job statuses. ## API & Services * **Fine-tuning and serving accept a registry model tag alongside the legacy keyword**: Newton fine-tuning, Newton batch serving (`activity-detection`, `manual-generation`), and Omega fine-tuning plus machine-state jobs all run dual-mode — a job that sends no tag behaves exactly as before. Profile-delivered config takes precedence over the legacy `model_variant`/`presets` lookup at a single branch point, and serving a promoted Omega head now loads directly from the registry bundle instead of the legacy `fine_tune_checkpoint` port. * **Create Job, Get Job, and List Jobs responses now return `workflow_key`**:These responses now carry the `workflow_key` property with the same value as `pipeline_key`, which is retained unchanged for backward compatibility. `workflow_key` is the preferred name going forward. The pipeline registry responses keep only `pipeline_key`. This completes changes introduced in v1.1.7. * **Lens v2 supports live RTSP cameras again**: A new RTSP pipeline drives a live camera through the same register → buffer → submit path as the file-video pipeline, wire-compatible with the legacy v1 stream configuration (`rtsp_url`, `target_frame_rate_hz`, `target_image_size`). Each connection gets a dedicated decode thread handing frames over a drop-oldest queue, so a stalled consumer keeps the freshest frames rather than compounding latency, and camera drops reconnect with exponential backoff. Session destroy is now honored by all four reader loops within about a second, so a destroyed session stops reconnecting instead of burning its backoff budget. * **JOS client supports the fine-tune API and KNN fine-tune jobs**: The client can submit Fine-Tuning API jobs and Omega KNN preparation jobs directly. ## Console & UI * **Job detail pages converge on one shared layout**: Job detail pages across most of the UI have converged on a single design. Progress moved out of the tab strip to the top of the page as a "now" block, so the status banner no longer duplicates the progress bar for healthy running or cleanly succeeded jobs. Config moved from a rail card into its own full-width tab. Fine-tuning jobs have not yet adopted the new look. * **Simplified and improved the profile and API key UI:** `/profile` now hosts profile details and API-key create/revoke together on one screen. ## Security & Authentication * **Platform admins can deactivate and reactivate users from the console**: Two new superadmin endpoints and matching buttons on the org members table close the gap that previously forced a superadmin to fall back to CLI plus port-forward plus master key. Actions are logged against the specific user’s `user_id` rather than a generic `"admin"` actor, and a superadmin cannot deactivate their own account. Reactivation deliberately does not restore revoked API keys — that would defeat the offboarding cascade — so users mint fresh keys via SSO. * **RTSP URL handling is hardened**: The URL scheme is now allowlisted to `rtsp`/`rtsps`. Loopback and link-local literal IPs are rejected to close off the cloud metadata endpoint and localhost side channels, while private LAN ranges stay allowed since VPN-reachable on-premises cameras are the primary real source. URL credentials are redacted from every log line and emitted event. ## Bug Fixes * **Batch-creation errors now include details about how to resolve the problem**: About 20 strings across the create modal, file upload, and file pickers were rewritten so every message names the problem *and* the resolution, dropping developer jargon like raw JSON pointers and status codes. * **Long agent names no longer hide the status badge**: The card header's flex wrapper is a grid item defaulting to `min-width:auto`, so it refused to shrink and pushed the badge past the card's clipped edge. Adding `min-w-0` lets the title truncate instead, and a `title` attribute makes the full name readable on hover. * **Fine-tuning metrics reach the console again**: The metric produced during MSJ inference over the fine-tune job was not saved alongside the checkpoint, so it never propagated to the UI. ## API & Services * **Fine-tuned checkpoints can now be promoted directly to fine-tuned models with base model tracking.** The base model tag is resolved and recorded at dispatch time, and both the checkpoint promotion and the resulting model responses now expose base model and tag information. * **Fine-tuning jobs no longer report success after an internal failure.** Previously the worker could swallow an error and mark a failed fine-tuning job as successful, which is now corrected. * **Batch inference now accepts a `workflow_key` parameter, deprecating the older `pipeline_type`/`pipeline_key` fields.** This simplifies how batch jobs specify which workflow to run. ## Console & UI * **The Console sidebar was collapsed into an icon rail.** The refresh also adopted secondary call-to-action alert actions from the updated design system. * **The Console service now validates its environment configuration on startup.** Misconfigured deployments fail fast with a clear error instead of surfacing confusing runtime issues later. ## Security & Authentication * **A wave of Critical/High severity CVEs has been remediated across non-PDM build surfaces.** The fix updates vulnerable dependencies as part of an ongoing security hardening effort. * **IAM now cascade-revokes a user's API keys when their account is deactivated.** A companion CLI command was added so operators can trigger the same revocation workflow manually. ## Bug Fixes * **Role checks on checkpoint promotion and model deletion were tightened.** This closes a gap that could allow insufficiently privileged users to perform these actions. * **Z-score computation for flatlined channels in omega\_1\_5 is now stable across different frameworks and hardware.** This fixes inconsistent results that previously varied depending on the runtime environment. ## API & Services * **Lens Runner v2 is now enabled by default.** * **GPQ now distinguishes cancelled queries from failed ones and fixes its default `max_frames` setting.** ## Console UI * **The Console UI underwent general normalization to bring a more cohesive feel to the interface.** * **Batch inference jobs in the Batch Manager can now take a checkpoint as an input.** This is shown using distinct UI treatment on the job's input files tab. ## IAM & Authentication * **Organization-admin and platform-admin capabilities have been added to IAM, gated by new JWT-scoped middleware.** A new route group requires a JWT with `sub_type=user` and `role=admin`, unblocking Console pages for full organization member and settings management as well as a platform-wide super-admin grant and bulk member creation. * **The `owner_user_id` predicate is now enforced on files, jobs, lenses, and sessions, scoping resource visibility to the requesting user.** This continues our work on per-user resource scoping and applies the same visibility predicate consistently across the data, JOS, and lens services. ## Fine-Tuning Service While most Archetype platform endpoints are under API version 0.5, the Fine-Tuning Service API is mounted under API version 0.6. * **A new v0.6 fine-tuning API has been introduced to JOS, providing a user-facing interface for creating and managing model training jobs.** The API is mounted at `/v0.6/fine_tuning` and supports Newton and Omega model discrimination, cursor-paginated job listings, checkpoint endpoints, and per-model hyperparameter schemas. It maps high-level fine-tuning requests onto internal JOS training jobs and mirrors the OpenAI fine-tuning job object shape in its responses. * **The dedicated fine-tuning runner node has been retired and replaced by the general-purpose training worker infrastructure.** This consolidates fine-tuning execution through the standard worker path and removes the now-obsolete standalone runner component from the platform manifest. *The Fine-Tuning Node API has been deprecated and is no longer available for use.* * **A fine-tuning dashboard has been added to the console for creating, managing, and monitoring training jobs.** The page is modeled after the existing Batch Manager and includes a job list/grid view and a create-job modal scoped to training pipelines. Batch Manager pipeline listings have been updated to filter out training pipelines so the two sections remain distinct. ## Job Orchestration Service * **Pause and Resume endpoints have been added to JOS along with new `Paused` and `Interrupted` job states.** Cancel has been made a terminal transition (the `Cancelled` state is now final), and Retry now returns a 501 directing callers to Pause instead. The new `Interrupted` state covers resumable worker failures separately from the non-resumable `Failed` state, and resume is permitted from `Interrupted`. * **Retry endpoint has been disabled.** The [Retry Job](/api-reference/batch/jobs/retry-job) endpoint has been deactivated for the time being. Using it results in a `501 Not Implemented` error. This endpoint will return with a future release. * **Completed Kubernetes Jobs are now torn down immediately upon completion to reclaim node disk space.** Previously only failed jobs triggered teardown, leaving model weight caches (\~16 GB per pod) on GPU nodes for up to an hour, which caused intermittent "Insufficient cache space" failures for subsequent fine-tuning jobs on single-node GPU pools. * **Upfront validation for JSONL and CSV job inputs has been added, checking files before job creation rather than at runtime.** File extension is now checked against the `text/plain` MIME type, and input selection validates types at the point of selection. * **A job outcome field has been added to JOS, and all jobs that finish execution are now marked `Completed` regardless of whether individual inputs had processing errors.** This separates jobs that completed their run from jobs that failed to run at all, giving a more accurate picture of job health. * **Processed bytes are now included in the progress summary returned with each job response.** This data powers the byte-based progress display in the Batch Manager job listing page. * **Status information for job outputs has been added to JOS job responses.** ## Console UI * **The Batch Manager has been significantly redesigned, introducing outcome modeling, a refreshed sidebar, a new job-details page, and byte-based progress tracking.** Banner-style callouts for job outcomes (succeeded, partially processed, failed, cancelled), and byte-level progress from the server are now surfaced in the job list view. * **Pause and Resume buttons have been added to the Batch Manager UI, allowing users to suspend and continue in-progress jobs.** The Cancel CTA has been restored alongside the new controls so all three lifecycle actions are available from the same interface. * **The "Task Type" label in the Batch Manager UI has been renamed to "Workflow Key" for clarity.** * **Byte-level progress information on the Batch Manager job listing page has been fixed to display accurate values.** ## IAM & Authentication * **Bulk-revocation of all active API keys for one or more orgs has been added to the IAM service and CLI.** A new master-key-protected endpoint (`POST /v1/iam/orgs/{org_id}/keys/revoke-all`) performs a single atomic update and emits per-key and summary audit events; the `atai iam org revoke-keys` CLI command defaults to a dry-run preview and requires `--execute` to apply changes. * **Structured audit events have been added across the full OIDC login flow in the console.** Every meaningful state transition — authorize start, callback received, state validation failure, KC/IAM exchange failures, and the existing success/failure events — now emits a structured event with a shared `flow_id` UUID that correlates all steps for a single login attempt. No raw secrets or token values are logged. * **The `owner_user_id` column has been added to files, lenses, sessions, and JOS jobs to track resource ownership at the user level.** ## API & Services * **The Jobs Orchestration Service (JOS) now supports chunked file outputs, exposing a single logical output file per input regardless of how many segments a worker produces.** Worker pods tag each segment result with a `chunk_of` field containing the chunk index, parent filename, and a final-chunk flag. Output URIs are rewritten to the authenticated `/files/download` endpoint, and files carry a `job_output.status` attribute (`partial` while in progress, `complete` when done) so users can track job state from the file library. * **JOS now detects and reports stuck jobs through a new background sweep and an OTel `jobs_stuck` gauge.** A job is now correctly marked `RUNNING` only when its first pod becomes `Ready`, so jobs queued without available GPU remain in `ADMITTED` rather than prematurely appearing active to users. The sweep detects two conditions — a job stuck in `ADMITTED` for over an hour and a `RUNNING` job with no emitted event or progress for over an hour — and exposes both counts via the new metric. * **JOS workers now exit gracefully on job cancellation by catching `SIGTERM`, checkpointing the current segment, and terminating cleanly.** The pod termination grace period has been raised from 30 seconds to 2 minutes by default to give workers sufficient time to complete a checkpoint before Kubernetes forcibly terminates the pod. The grace period is configurable per deployment. * **A manual-generation JOS pipeline has been added for producing structured procedural documentation from video.** The pipeline performs audio-grounded batch inference and is available as a new task type configured via a JOS seed deployed to the environment. ## Security & Authentication * **API keys can now be created with an optional TTL, and expired keys are automatically marked in the database on first use after expiry.** A new `--ttl-days` flag on the `atai iam key create` and `atai iam user key create` CLI commands computes an `expires_at` timestamp at creation time and passes it through to the IAM service. When an expired key is rejected, its status transitions from `active` to `expired`. No schema migration is required as the `expires_at` column already existed on the `api_keys` table. ## API & Services * **Chunked files can now be downloaded via the existing `/files/download` endpoint, with content streamed directly from S3 in chunk order:** The download path detects whether a file is chunked and assembles the response as a streaming byte sequence across all stored S3 objects, with no need for a separate endpoint or client-side logic. * **A new `SegmentedInferenceSession` abstraction has been added to the JOS worker client, enabling automatic checkpointing, progress reporting, and resilient resume for batch inference jobs:** Workers now iterate over "segments" (subsets of input files) rather than whole files, and the session handles checkpointing between segments, emitting file-started/completed events, and resuming from the last checkpoint on restart. Segment size is configurable with defaults of 50 MB of input or 10 minutes, whichever comes first. The Nano inference worker and the inference phase of the machine state job have been updated to use this abstraction. * **Stale file uploads stuck in the `UPLOADING` state are now automatically cleaned up:** A configurable scheduler (default: every 6 hours) aborts any upload older than a threshold (default: 24 hours) using the same logic as the `/abort` endpoint. * **A new `DatasetList` port mode and a `PortMode::Checkpoints` type have been added to JOS to support dataset listing and checkpoint upload workflows:** These additions enable workers to declare input/output ports that carry dataset lists and model checkpoints respectively, broadening the range of job types that can be expressed natively in JOS config. Checkpoint files are now staged under a non-tmpfs folder to avoid memory pressure. ## Inference & Model Updates * **The C2.6 model is now available with a new vLLM inference backend that delivers improved throughput over previous transformer-based inference:** Multi-image support has been added to Direct Query and the Nano engine, and GPU-specific YAML configurations allow fine-grained tuning per model and hardware combination. * **GPU memory budget calibration for C2.5 and C2.6 has been improved with a more accurate adaptive probe sweep across batch size and shape dimensions:** The calibration now accounts for padding-aware batch peaks, shrinks the memory budget incrementally after each OOM, and warms up the engine at max probe shapes before calibrating. This reduces spurious OOM events during production batch inference workloads. * **UFM training has been extended with variable-K Stage 1+2 resolution, `pad_mode=interpolate` retraining, Stage 3 sweep plumbing, and several stability fixes:** A deterministic eval fix and a PEP 479 `StopIteration` correction were also merged, along with pinning `flash-linear-attention` to avoid a \~3× training slowdown introduced by a dependency update. The UFM builder and model directories were refactored to align with the factory pattern introduced in the updated Nano engine. ## Observability & Telemetry * **OTel SQL tracing has been extended to cover database transactions via a new `TracedTransaction` wrapper, and rolled out to the Lens API and Data services:** This completes full OTel tracing coverage for `data_service` and `lens_api_service`; `iam_service` and `jos_service` will follow in subsequent releases. * **New Python `OtelMetricsBase` and `OtelWorkerMetricsBase` base classes have been introduced, and the first batch of active platform services has been migrated from Prometheus to OpenTelemetry metrics:** The new base classes use the global `MeterProvider` directly, dropping the per-service `CollectorRegistry` and `update()` chain used by the legacy Prometheus classes. Services migrated in this release include `api_service`, `lens_service`, and `gpq_service`; the previous `service_info` gauge is replaced by OTel resource attributes. * **Prometheus business metrics in `data_service`, `iam_service`, `jos_service`, `lens_api`, `health_service`, and `registry_service` have been migrated to the OTel push model:** This brings the Python service telemetry pipeline in line with the Rust services and enables unified metric collection through the OTLP exporter. Per-request `org_id` propagation has also been added to OTLP logs, and per-signal OTLP endpoint overrides are now supported for routing traces, metrics, and logs to different collectors. * **New Grafana dashboard panels have been added for JOS job counts, node pool sizes, total file counts and bytes, and the sync has been improved to include fixes for overcounting:** The panels provide visibility into per-org file storage volume and JOS queue depth and were synchronized with the cloud environment. A separate fix corrects an over-counting bug in the file count and bytes panels introduced during the initial rollout. ## Console & UI * **Filename search has been added to the files dashboard, backed by new database indexes for performant queries:** Users can now filter the file list by partial filename match directly in the UI, and the underlying data service database has been updated with the necessary indexes to keep query latency low even for large file tables. * **The Console login page, homepage, and top navigation have been migrated to the Archetype design system:** Light/dark mode persistence is preserved. * **The Console dashboard and workbench pages have been migrated to the design system:** Dashboard pages now use design system primitives, and the workbench has been updated while keeping all existing functionality intact. ## Bug Fixes * **vLLM batch job result ordering and crash recovery have been fixed to ensure JSONL output is always in input order and that fatal engine failures are handled cleanly:** When async vLLM workers complete out of order, results are now staged by submit position and flushed in contiguous runs, keeping output aligned with the original input. Per-record failure messages are sanitized to "inference error" so internal exception details never reach user-downloadable files. When the vLLM engine encounters a fatal error (such as CUDA out-of-memory), the worker now emits an `inference.engine_dead` event, cancels in-flight work, and exits cleanly so Kubernetes restarts the pod and JOS resumes from the last checkpoint. * **A TOCTOU race condition and stale counter bug in chunked file writes have been fixed, and chunk data and S3 objects are now properly cleaned up on file deletion:** Concurrent appenders previously could race on `chunk_index` assignment; the fix ensures all writes happen within a single locked transaction. Deleting a chunked file now removes all associated `file_chunks` rows and their corresponding S3 objects, preventing orphaned storage. ## API & Services * **`file_type` filter added to the `list-files` endpoint:** A new query parameter allows callers to filter the file listing by MIME type or file type category, making it easier to retrieve only the files relevant to a specific workflow. * **OpenAPI schema for `/query` expanded with full request/response documentation:** The OpenAPI spec for the `/query` endpoint now includes complete request and response schemas, improving SDK generation quality and developer documentation. * **`ATAI_CA_BUNDLE_PATH` environment variable renamed to `ATAI_CA_BUNDLE`:** The legacy environment variable name was simplified for consistency. Deployments using the old name will need to update their configuration. * **Per-org file count and byte total exposed as Prometheus metrics (PLDEV-784):** Two new Prometheus gauges track total file count and aggregate storage usage per organisation, enabling capacity planning and billing dashboards. * **The `jos seed apply` command now bundles seed YAMLs (PLDEV-909):** The `jos seed apply` CLI command was updated to ship seed YAML files directly with the binary, so applying default data seeds no longer requires a separate file distribution step. * **Example automatic migration scripts added for 1.0.9 → 1.1.1 and 1.1.1 → 1.1.2:** Reference migration examples were committed to the repository so operators have a concrete starting point for upgrading existing deployments across these version boundaries. ## Observability & Telemetry * **Full OpenTelemetry OTLP distributed tracing stack added to all Rust services:** The `atai_telemetry` crate now wires a complete three-signal OTel pipeline — distributed traces, log records with trace/span correlation, and push metrics — all exported via OTLP/gRPC when `OTEL_EXPORTER_OTLP_ENDPOINT` is set. HTTP spans follow OTel semantic conventions via `axum-tracing-opentelemetry`, with W3C `traceparent` extraction and propagation across all four Rust HTTP services. When the endpoint is unset, the crate behaves exactly as before with zero OTel overhead. * **OTLP log bridge and trace improvements added to `console_2_service`:** This PR wires the OTLP log bridge into `console_2_service` and improves trace context handling, including always-on W3C trace ID generation and `X-Request-Id` reflection in responses. Static asset requests are excluded from tracing noise, and root HTTP span naming now uses `METHOD /route/[param]` with SvelteKit route IDs. * **`init_tracer()` added to `atai_py` and wired into `initialize_service_logging`:** Python services can now initialize OpenTelemetry tracing with a single call, automatically reading `OTEL_EXPORTER_OTLP_ENDPOINT` and configuring the tracer pipeline (PLDEV-801). * **`PLATFORM_VERSION` is now propagated through logs and metrics:** The platform version string is attached as a resource attribute on all telemetry signals, making it easier to correlate observability data with specific release versions. * **Legacy `x-trace-id` header dropped in favor of the OTel `traceparent` standard:** The proprietary `x-trace-id` request/response header has been removed and all tracing correlation now relies on the W3C `traceparent` header (PLDEV-797). Any tooling or dashboards relying on `x-trace-id` will need to be updated. * **`atai_telemetry_reqwest` crate adds OTel HTTP client spans via `reqwest-middleware`:** Outgoing HTTP calls made through `reqwest` now produce properly attributed OTel client spans (PLDEV-798), enabling end-to-end trace stitching for calls leaving Rust services. ## Security & Authentication * **JWT exchange endpoint and JWKS added to the IAM service:** A new `POST /v1/iam/exchange` endpoint accepts an API key and returns a signed RS256 JWT containing Archetype claims (subject, org ID, role, auth method), laying the foundation for moving from per-request API key validation to JWT-based auth. A companion `GET /v1/iam/.well-known/jwks.json` endpoint serves the RSA public key so downstream services can validate tokens locally. The existing `/v1/iam/authenticate` endpoint is unchanged for backward compatibility. * **`UPLOADING` status is now exposed in the public file API (PLDEV-833):** Previously the `UPLOADING` state was hidden from the public-facing file status endpoint; it is now surfaced so clients can accurately track in-progress uploads. ## Data Integrity & Uploads * **End-to-end server-driven checksum verification added to the direct upload flow (PLDEV-663):** The server now selects the checksum algorithm at upload initiation and returns it in the `InitiateUploadResponse`; clients can optionally compute and submit a whole-file CRC32C in `CompleteUploadRequest`. If provided and mismatched, the file is marked `CORRUPT` and HTTP 422 is returned; if absent, the upload succeeds without verification, preserving backward compatibility. S3 `CreateMultipartUpload` is called with `ChecksumType: FullObject` so a single whole-object CRC32C is stored and retrievable via `HeadObject`. ## Inference & Model Features * **vLLM engine support added along with c26 improvements:** The vLLM inference engine backend was integrated, including model weight caching and related configuration changes for the c26 hardware generation. * **Stage 3 task classification expanded with MoteStrain and PAMAP2 datasets for UFM (fixed and variable):** The UFM task classification pipeline now supports MoteStrain and PAMAP2 benchmarks across both fixed and variable input configurations. * **Jobs now fail explicitly if any input fails (PLDEV-940):** Previously a job could silently succeed even if one or more of its inputs errored; the job runner now propagates input failures and marks the overall job as failed. ### Console & UI * **Autocomplete label suggestions added to the n-shot file picker (PLDEV-715):** As users enter class labels across n-shot files, a session-scoped vocabulary is built up and previously used labels are surfaced as autocomplete suggestions on subsequent inputs. The dropdown supports keyboard navigation (Arrow Up/Down, Enter, Escape), mouse selection, and auto-scrolls the active suggestion into view. * **Error tooltip in the console stays visible longer and supports text copying:** The tooltip that appears on API or service errors now remains on screen long enough to read and can have its content copied, improving the debugging experience for users (PLDEV-786). * **Content-aware column widths applied to batch manifest tables:** Columns in batch manifest views now size themselves based on their content rather than using fixed widths, improving readability for a wide range of payload shapes. * **Progress chart tooltip is now flipped when near the right edge (PLDEV-889):** The tooltip on progress charts was being clipped when the cursor was near the right boundary; it now flips to the left to stay fully visible. * **"Pipeline" label renamed to "Task Type" throughout the console (PLDEV-905):** The UI label used to describe processing pipelines has been standardized to "Task Type" for consistency with the rest of the product terminology. * **MSJ broken image display fixed:** A regression that caused broken image previews in the multi-sensor join UI was resolved. * **Wrong progress counter in MSJ fixed (RES-272):** A display bug that caused incorrect progress percentages to appear in the MSJ task view was corrected. ## New Features & Improvements * **Added direct-to-cloud file upload support to the Rust and Python SDKs (PLDEV-535, PLDEV-16):** Both the Rust and Python SDKs now support uploading files directly to cloud storage via presigned S3 URLs, bypassing the data service proxy. The Rust SDK introduces a new builder API (`UploadBuilder`) as the default path, with the proxy path still available via `.using_proxy()`; the Python SDK makes the direct path opt-in via `use_proxy=False`. Both implementations support concurrent multipart uploads with configurable worker counts, per-part retries with exponential backoff, progress callbacks, and cancellation. This enables uploads well beyond the proxy's previous 500 MB size limit. * **Added resumable upload support to the Rust and Python SDKs (PLDEV-551, PLDEV-778):** Clients that fail mid-upload can now resume from where they left off without re-uploading already-completed parts. A new server-side checkpoint endpoint stores completed part tokens, and the initiate call accepts a `resume_if_started` flag to reuse an in-progress upload for the same file. On the Rust SDK, resuming is enabled via `.with_resume(true)` on the upload builder, with checkpointing on by default; on the Python SDK, resuming is enabled by passing `allow_resume=True` to `upload()`, with checkpointing also on by default. If a progress callback is set, it will be called once with the already-uploaded byte count when a resume occurs. * **Increased the maximum upload file size to 250 GB:** The platform-wide maximum file size for uploads has been raised to 250 GB to accommodate large dataset and model artifact transfers. * **Added a session validation step to the Workbench (PLDEV-195, PLDEV-600):** The Workbench now sends an explicit `session.validate` event at the start of every lens session before entering the active streaming state. If validation fails, users receive a clear error notification even when the session log panel is collapsed, and error log entries are highlighted in red for quick visual identification. This addresses a recurring issue where heartbeat timeouts would cause sessions to continue in a degraded state without surfacing clear feedback to users. * **Added a read-only selected file name field to the Workbench lens tray (PLDEV-609):** The lens tray settings panel for the Activity Monitor and Machine State lenses now displays the name of the currently selected input file below the model version field. When no file has been chosen, the field shows "Not selected." * **Limited CSV table and graph rendering to 10,000 rows in the Workbench to prevent freezes on large datasets (PLDEV-186):** When an uploaded CSV file exceeds 10,000 rows, the Workbench now truncates the preview display and shows a banner informing users of the total row count and directing them to the API for full data access. CSV data is now truncated at the line-split stage before full parsing occurs, preventing memory pressure from very large files. * **Improved Workbench output panel autoscroll behavior (PLDEV-350):** The Workbench output panel now auto-scrolls to the latest response by default but pauses when the user manually scrolls up to review earlier results. A **NEWEST** button appears when the user has scrolled away from the bottom, and clicking it jumps back to the latest output and resumes auto-scrolling. Autoscroll state is reset at the start of each new session. * **Added drag-and-drop bulk file upload to the File Manager (ATAI-2938):** Users can now upload files to the File Manager by dragging and dropping them directly onto the file list page, or by using a new modal-based upload dialog triggered from the "Add files" button. The upload dialog shows per-file progress, supports individual file cancellation, and retains failed upload placeholders in the list so users can see which uploads did not complete. * **Added the Batch Manager to the Console with live job creation, listing, and detail pages (PLDEV-575, PLDEV-576, PLDEV-604, PLDEV-689, PLDEV-695):** A new Batch Manager page is available in the Console, allowing users to create and monitor batch jobs submitted to the Job Orchestration Service, and to download job artifacts. See the [Batch Manager documentation](https://docs.archetypeai.app/developer-console/batch-manager) for details. * **Added Python JOS clients for API access and job container use (PLDEV-348):** Two new Python clients for the Job Orchestration Service have been added. `JosApiClient` covers all 20 REST API endpoints (jobs, components, pipelines) with an async-first design and structured error handling. `JosWorkerClient` is for use inside JOS-managed pods and provides `InputPort`/`OutputPort` abstractions for reading JSONL manifests from S3, uploading outputs, reporting progress via Redis, and saving and restoring checkpoints. * **Synced CSV `window_size` and `step_size` from the Workbench lens tray to the input stream config (PLDEV-629):** When a user updates the `window_size` or `step_size` fields in the CSV lens tray, the values are now propagated to the underlying input stream config so that inference window boundaries correctly reflect the configured parameters. * **Added structured error responses to the data service (PLDEV-591):** The data service now returns structured, machine-readable error response bodies across its endpoints, replacing unstructured text errors. ## Bug Fixes * **Fixed lens worker crash loops from missing `model_parameters` and stale Redis events (PLDEV-610):** A cascading failure was identified where missing `model_parameters` in a lens config caused a `KeyError` crash on worker nodes, and stale Redis queue events from crashed sessions caused nodes to re-enter crash loops on restart. Five targeted fixes prevent the `KeyError`, drain stale Redis events on node restart, skip unknown-session events, and garbage-collect stuck sessions. * **Fixed narrator memory not being initialized for direct `model.query` calls without a video stream (PLDEV-632):** When `model.query` was called without a preceding `stream.start` event — for example, for non-video file inputs — the narrator's internal memory and buffer fields were uninitialized, causing failures. * **Fixed deleted files returning stale data from the Files API (PLDEV-614, PLDEV-605):** The `GET /files/metadata/{id}` endpoint now returns 404 Not Found on deleted files instead of the old record with an "unknown" status, and the download endpoint also returns 404 instead of 400 on deleted files. Re-uploading a file to a previously deleted file key is now permitted. * **Fixed multipart upload completion not accepting unsorted parts (PLDEV-670):** The `/files/uploads/{id}/complete` endpoint no longer requires the uploaded parts list to be submitted in sorted order. * **Fixed the `window_size` and `step_size` values not being returned by the console-2-service (PLDEV-600):** The backend was not including `window_size` and `step_size` in its responses, causing the lens tray to display stale or missing values after a session was initialized. * **Fixed the console CSV config tooltip width and wrapping:** The tooltip for CSV configuration settings in the console was overflowing its container; width and text-wrapping constraints have been applied. * **Fixed the console-2-service to correctly apply schema default values for config templates:** The console frontend now correctly applies schema-defined default values when rendering config template fields, rather than leaving them empty. ## New Features & Improvements * **Added the Fine-Tuning Node to perform fine tuning jobs on dedicated GPUs:** The new Fine-Tuning Node offers an API to create, manage, and monitor fine-tuning jobs for your organization. Each Fine-Tuning Node runs a fine-tuning job on its assigned GPU, acting like a worker that trains a model using the provided dataset and configuration. This produces a fine-tuned model and training metrics. * **Added the Batch Manager to the Console with live job creation and listing (PLDEV-575, PLDEV-576):** A new Batch Manager page is now available in the Console (behind the `CONSOLE_FLAG_SHOW_BATCH_MANAGER` feature flag), allowing users to create and monitor batch jobs submitted to the Job Orchestration Service. The Batch Manager supports creating jobs with file input selection and YAML/JSON config validation, displays submitted jobs with status badges and relative timestamps, and fetches job and pipeline data server-side. * **Added a session validation step to the Workbench (PLDEV-195, PLDEV-600):** The Workbench now runs an explicit `session.validate` event at the start of every lens session before entering the active streaming state. If validation fails, users receive a clear error notification even when the session log panel is collapsed, and error log entries are highlighted in red for quick identification. * **Added a read-only selected file name field to the Workbench lens tray (PLDEV-609):** The lens tray settings panel for the Activity Monitor and Machine State lenses now displays the name of the currently selected input file below the model version field. When no file has been chosen, the field shows "Not selected." * **Limited CSV table and graph rendering to 10,000 rows in the Workbench to prevent freezes on large datasets (PLDEV-186):** When an uploaded CSV file exceeds 10,000 rows, the Workbench now truncates the preview display and shows a banner informing users of the total row count and directing them to the API for full data access. * **Improved Workbench output panel autoscroll behavior (PLDEV-350):** The Workbench output panel now auto-scrolls to the latest response by default but pauses scrolling when the user manually scrolls up to review earlier results. A "NEWEST" button appears when the user has scrolled away from the bottom, allowing them to jump back to the latest output and resume auto-scrolling. Autoscroll state is reset at the start of each new session. * **Added drag-and-drop bulk file upload to the File Manager (ATAI-2938):** Users can now upload files to the File Manager by dragging and dropping them directly onto the file list page or by using the new modal-based upload dialog. The upload dialog supports multiple concurrent file uploads, individual cancellation, progress tracking per file, and persists failed upload placeholders in the file list so users can see which uploads did not complete. * **Implemented the Machine State Job (RES-226):** A new batch job for machine state classification has been added, built on the fine-tuned Omega 1.3 model. The job can run on both CPU and GPU, processes sensor CSV data, and supports n-shot input files for healthy and faulty reference examples. * **Synced CSV `window_size` and `step_size` from the Workbench lens tray to the input stream config (PLDEV-629):** When a user updates the `window_size` or `step_size` fields in the CSV lens tray configuration, the values are now propagated to the underlying input stream config so that the inference window boundaries correctly reflect the configured parameters. ## Bug Fixes * **Fixed narrator memory not being initialized for direct `model.query` calls without a video stream:** When `model.query` was called without a preceding `stream.start` event (e.g., with non-video file inputs), the narrator's memory and buffer fields were uninitialized, causing the lens service to fail. * **Fixed deleted files returning stale data from the Files API (PLDEV-614, PLDEV-605):** The `GET /files/metadata/{id}` endpoint now returns a `404 Not Found` response when called on a deleted file, rather than returning the old file record with an "unknown" status. The `GET /files/download/{id}` endpoint similarly now returns `404` on deleted files instead of a `400` error. Additionally, the Files API now allows re-uploading a new file over a previously deleted file's key. * **Fixed the console CSV config tooltip width and wrapping:** The tooltip for CSV configuration settings in the console was overflowing its container; width and text-wrapping constraints have been applied. # Error Codes Source: https://docs.archetypeai.app/support/error-codes Canonical list of platform error codes with meanings, causes, and which API surface emits them. # Error Message Format Most API errors across the Archetype platform return errors in the following JSON format to help you understand and resolve the error: ``` { "errors": [ { "code": "missing_parameter", "message": "Failed to find key: some_key", "suggestion": "Resubmit your query with the expected parameters.", "error_uid": "err-abc123", } ] } ``` Each error has the following structure: * **code**: a specific error code, which is listed in the table below * **message**: an error message describing the problem behind the error * **suggestion**: a suggestion on how to potentially resolve or mitigate the error * **error\_uid**: a unique error ID for every error, you can share this error with the Archetype team to help debug the issue Note that there may be more than one error reported, such as a missing parameter and an invalid parameter value. Each error will return a specific code, message, suggestion, and error\_uid. The following table describes Archetype error codes. # Error Codes | Code | Description | API or Service | | - | - | - | | `invalid_file_type` | The uploaded file type is not supported. See the [File Types page](/core-concepts/files/files#files-api) for the supported types. | Files API | | `invalid_file_size` | File size is outside the acceptable range. See the [File Types page](/core-concepts/files/files#files-api) for the supported size. | Files API | | `capacity_reached` | The file service has reached memory capacity. Delete files or wait for inactive files to be removed. | Files API | | `file_backup_failed` | The file service failed to backup the file after upload. | Files API | | `internal_logic_error` | An internal platform logic error occurred (e.g., missing org\_id, api\_key, or query\_id). Report this error to support. | Lens API | | `invalid_model_parameter` | A model parameter has an invalid value. Either `sensor_buffer_size` is `<= 0 or `input\_frame\_step\_size` is <= 0`. | Lens API | | `sensor_log_conversion_error` | Failed to convert input sensor logs to YAML format. Validate your sensor logs are YAML safe. | Lens API | | `empty_sensor_log_error` | Sensor logs appear to be empty. Check your sensor log data is not empty. | Lens API | | `max_query_size_exceeded` | Query size exceeds the maximum limit (default 255 MB). Decrease JSON event size or sensor buffer size. | Lens API | | `session_ttl_reached` | The session has reached its time-to-live limit. Restart your session and increase the TTL if needed. | Lens API | For supported files types and more details, refer to the [File types](/core-concepts/files/files#file-formats). # Request Access Source: https://docs.archetypeai.app/support/request-access Request a free trial API key for the Archetype platform. You'll need an API key to access the Archetype platform. ## Request a Free Trial Interested in trying the Archetype platform? [Request a free trial](https://forms.gle/yTu6xp7CCEvAYLqB9) to get an API key and register your interest in a hands-on workshop. ## Support For support with existing API keys, please contact [**support@archetypeai.dev**](mailto:support@archetypeai.dev). # Support Source: https://docs.archetypeai.app/support/support This page covers common issues you might encounter when working with the Archetype API and provides step-by-step solutions. ## Reporting Issues Please gather the following information and send directly to [support@archetypeai.dev](mailto:support@archetypeai.dev): * **Error messages:** Complete error responses with codes * **Request details:** URLs, headers, and request bodies (remove API keys) * **Timestamps:** When the issues occurred * **Environment:** Programming language, OS, network setup * **Steps to reproduce:** Detailed steps that trigger the issue * **Expected vs actual behavior:** What you expected vs what happened This information helps our support team diagnose and resolve issues quickly. # Troubleshooting Source: https://docs.archetypeai.app/support/troubleshooting Common issues and solutions when working with Archetype's APIs ## Common Errors ### Python Version Error If you see an error like: ``` TypeError: unsupported operand type(s) for |: 'type' and 'type' ``` This means your Python version is below 3.10. The Archetype AI client requires **Python 3.10 or higher**. Create a new environment with: ```bash theme={"system"} conda create -n archetype python=3.10 conda activate archetype pip install archetypeai ``` ## Troubleshooting Checklist Ensure you have the latest version of the Python client installed. See the [Python client documentation](/libraries/python#upgrade-python-client) for full installation and upgrade instructions. Show your installed version: ```bash theme={"system"} pip show archetypeai ``` Upgrade to the latest version: ```bash theme={"system"} pip install --upgrade archetypeai ``` * Check API key format: `Bearer YOUR_API_KEY` * Verify key hasn't been revoked in Developer Console * Ensure correct environment (dev/prod) * Validate required parameters are included * Verify JSON formatting for POST requests * Check file formats and sizes for uploads * Read error code and message carefully * Check details object for additional context * Look for retry\_after values for rate limits * Use exponential backoff for server errors * Respect rate limit retry\_after values * Don't retry client errors (4xx except 429) * Log all errors with context * Set up alerts for high error rates * Track error patterns over time ## Getting Help If you're still experiencing issues after following this guide: View current system status and incidents Request API access if you don't have it yet Get help from our technical support team at [support@archetypeai.dev](mailto:support@archetypeai.dev) Browse additional support documentation When contacting support, please include: * Error codes and messages * Request/response examples * Timestamps of errors * Your organization ID * Steps to reproduce the issue