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_idvalues and canonicalasset://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_idcorrelates one WebSocket command with exactly onerpc_response. It is client-generated, non-empty, and not a durable job key.client_request_idcorrelates application logs and submission attempts. It is echoed by the submission acknowledgement.idempotency_keyidentifies one logical submission within the authenticated user/workspace scope and advertised retention period.job_id,workflow_id,workspace_id, andasset_idare 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
sequenceis 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:
- discard duplicate sequences;
- process known events in sequence order;
- safely advance past unknown event types;
- request a fresh snapshot if replay is expired or a sequence gap cannot be filled;
- 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
cancelledimmediately; - 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.