---
title: "SDK Lifecycle v1 Draft"
description: "Local-first visual environment for building and running AI workflows. Build agents visually, deploy anywhere, privacy by design."
canonical: https://docs.nodetool.ai/sdk/lifecycle-v1-draft
markdown: https://docs.nodetool.ai/sdk/lifecycle-v1-draft.md
product: NodeTool
source: https://github.com/nodetool-ai/nodetool/blob/main/docs/sdk/lifecycle-v1-draft.md
---

# SDK Lifecycle v1 Draft

# SDK Lifecycle v1 Draft

## Implementation status

Capabilities and preflight are implemented as feature-flagged production HTTP
and correlated WebSocket operations. The remaining job lifecycle operations
in this draft are planned. The server contains transport-independent,
schema-validating builders for:

- capability responses;
- static preflight using the existing graph/per-node validator;
- workflow etag and graph-derived input validation;
- cost summaries using the existing workflow cost estimator;
- deterministic credential, runtime, provider, model, and asset requirement
  discovery;
- availability preflight through injected read-only probes, with conservative
  runnable decisions and redacted probe failures;
- execution preflight composition for worker, target, capacity, and queue
  readiness, again through injected read-only probes;
- one transport-neutral orchestrator and an adapter over NodeTool's existing
  owner/public/collaborator workflow authorization and graph-derived
  interface service;
- a principal-bound NodeTool service that reuses per-user credential,
  registered-provider, and owner-scoped asset checks;
- locally authoritative Node/TypeScript, hydrated Python bridge, and
  allow-listed FFmpeg/FFprobe runtime probes;
- asset requirement discovery from both structured `asset_id` values and
  canonical `asset://` or `/api/storage/` references nested in inputs;
- a read-only view of the exact authenticated live runner's real admission
  counters and execution readiness composition that reports likely queueing
  without reserving work;
- explicit local, attached-worker, and live-runner execution targets without
  attaching, provisioning, or falling back to a different target.

`GET /api/sdk/v1/capabilities`, `POST /api/sdk/v1/preflight`,
`POST /api/sdk/v1/assets/temporary`, `get_capabilities`, and
`preflight_workflow` are available by default. A deployment can disable them with
`NODETOOL_DISABLE_SDK_LIFECYCLE_V1=1`. Their HTTP and WebSocket adapters share
the same providers and authenticated principal. Submission, snapshot,
subscription, and lifecycle cancellation operations remain planned.

This document defines the language-neutral lifecycle profile that the server,
C# base, VL, Unity, and future SDKs will share. The schemas are published now;
operations marked `x-nodetool-implementation: planned` are not server
endpoints. AsyncAPI lifecycle operations are marked `partial` while their
capability and preflight variants are implemented and later variants remain
planned.

The capability profile `temporary_asset_upload = available` advertises the
multipart temporary-input route. It writes directly to configured temporary
storage and returns a runtime-resolvable URI. It deliberately creates no Asset
row, thumbnail, asset-list entry, or durable provenance record. The temporary
store's retention policy owns cleanup. SDK execution defaults generated-asset
persistence to `temporary`; callers explicitly request `auto` when normal
asset autosave is required. Unannotated non-SDK `run_job` behavior remains
`auto`.

## Identifiers and time

- `request_id` correlates one WebSocket command with exactly one
  `rpc_response`. It is client-generated, non-empty, and not a durable job key.
- `client_request_id` correlates application logs and submission attempts. It
  is echoed by the submission acknowledgement.
- `idempotency_key` identifies one logical submission within the authenticated
  user/workspace scope and advertised retention period.
- `job_id`, `workflow_id`, `workspace_id`, and `asset_id` are opaque strings.
  Clients must not derive routing, ownership, or time from their format.
- Timestamps are RFC 3339 strings with an explicit offset. The server emits
  UTC. Clients compare instants, not timestamp text.
- Event `sequence` is a positive, monotonically increasing integer scoped to
  one job. Sequence zero means no event has yet been persisted.

Retrying a submission with the same idempotency key and equivalent normalized
request returns the original job. Reusing the key with a different workflow,
revision, workspace, or inputs is a conflict. The server advertises the
retention window before idempotent submission becomes available.

## Public job states

The public states are:

| State              | Terminal | Meaning                                            |
| ------------------ | -------- | -------------------------------------------------- |
| `accepted`         | No       | Persisted and admitted, before queue or execution  |
| `queued`           | No       | Waiting for capacity; `queue_position` is present  |
| `running`          | No       | Actively executing                                 |
| `suspended`        | No       | Paused on a resumable workflow condition           |
| `recovering`       | No       | Server is reconciling execution after interruption |
| `cancel_requested` | No       | Cancellation accepted but execution not terminal   |
| `completed`        | Yes      | Authoritative result manifest is persisted         |
| `failed`           | Yes      | Safe public error is persisted                     |
| `cancelled`        | Yes      | Execution is durably cancelled                     |

Internal `scheduled`/`pending` states map to `accepted`. Internal `paused` maps
to `suspended`. Internal error aliases map to `failed`. These mappings do not
change the existing database vocabulary.

Terminal states are immutable. A job cannot be observed as `completed` until
its final outputs, asset references, cost, and provenance manifest are
persisted. The runtime schema enforces a non-null result for `completed` and
forbids a terminal result on non-terminal snapshots.

## Preflight and submission

`preflight_workflow` is side-effect free. It does not create a job, reserve a
provider request, download a model without explicit approval, or start paid
work. It reports:

- graph, pin, and type issues;
- provider, credential, model, node-pack, runtime, asset, worker, and approval
  requirements;
- whether each requirement blocks execution;
- estimated, partial, exact, or unknown cost confidence.

`submit_job` requires a successful-enough authoritative preflight, a workflow
interface version, workflow etag, `client_request_id`, and `idempotency_key`.
The server persists the accepted/queued job and idempotency record before
returning acknowledgement. Submission acknowledgement is separate from the
event stream.

## Snapshots, events, and reconnect

`get_job_snapshot` is authoritative. A snapshot contains current state,
timestamps, last persisted sequence, preflight summary, and terminal result or
error when applicable.

`subscribe_job(job_id, after_sequence)` first establishes an authoritative
snapshot, then replays retained events after the requested sequence and
continues with live events. Every event carries job ID, workflow ID, workspace
ID, timestamp, and sequence.

Clients must:

1. discard duplicate sequences;
2. process known events in sequence order;
3. safely advance past unknown event types;
4. request a fresh snapshot if replay is expired or a sequence gap cannot be
   filled;
5. treat the snapshot as authoritative when provisional events disagree.

Reconnect to queued, running, suspended, recovering, or cancel-requested jobs
returns their current snapshot and replay range. Reconnect to a terminal job
returns the persisted terminal snapshot. Missing, inaccessible, and
cross-workspace jobs share the same not-found response. Expired jobs use a
stable expiry code without revealing another tenant's resources.

## Cancellation

Cancellation is idempotent:

- queued work can become `cancelled` immediately;
- active work first becomes `cancel_requested`;
- a provider may finish before cancellation takes effect;
- cancellation after a terminal state returns the existing terminal snapshot.

Clients must not treat a cancellation acknowledgement as terminal unless the
returned snapshot is `cancelled`.

## Results and assets

The result manifest contains JSON-safe output values plus an explicit list of
every durable asset referenced by those outputs. Each asset reference carries
an opaque ID, canonical URI, MIME type, optional size and SHA-256 checksum,
and an optional expiring download URL.

Large image, audio, video, document, and model data travels by asset reference,
not inline WebSocket payload. `outputs` may contain scalar or structured JSON;
the `assets` bindings identify the output name and nested path at which each
durable asset is materialized.

Provenance contains normalized/redacted inputs, workflow revision, providers,
models, seed, and reconciled cost. It never contains credentials,
authorization headers, provider secrets, or unbounded inline media.

## Ownership

All preflight, submission, snapshot, subscription, cancellation, result, and
asset operations use the same authenticated user/workspace authorization.
Caller-supplied identity headers are not trusted. A job and every result asset
inherit the accepted submission's ownership scope.
