Pre-release Harn is pre-1.0 — the language, standard library, and CLI may change between releases. See the release notes

Model-job reference

Import std/model_job for the public model-job, media-asset, ComfyUI, and test APIs.

import {
  ModelBackend,
  ModelJobRequest,
  ModelJobRunOptions,
  model_job_run_result,
} from "std/model_job"

The model-job explanation describes why this boundary exists. This page lists its contracts.

Request

ModelJobRequest has these fields:

FieldTypeMeaning
idstringCaller-generated request ID.
taskModelTaskimage.generate, image.edit, audio.generate, video.generate, embedding, or custom.
promptstringRequired except for embedding.
outputModelOutputSpecRequired MIME type and optional width, height, duration, or count.
modelstring?Model selected by the caller.
inputslist<MediaAsset>?Input assets for editing or other conditional work.
seedint?Reproducible random seed when the backend supports one.
paramsdict?Backend-specific settings.
metadatadict?Application data carried with the request.

model_job_request_result validates the common fields before the backend is called. model_job_request_digest hashes the fields that affect model output. Replay requires the same digest.

Backend

A backend has one ID and three functions:

type ModelBackend = {
  id: string,
  submit: fn(Harness, ModelJobRequest) -> Result<ModelJobObservation, ModelJobError>,
  inspect: fn(Harness, ModelJob) -> Result<ModelJobObservation, ModelJobError>,
  cancel: fn(Harness, ModelJob) -> Result<ModelJobObservation, ModelJobError>,
}

submit returns the first observation. inspect returns the latest provider state. cancel requests cancellation and returns the resulting observation. The backend may use harness.net, a connector, or a local process.

Map every provider status through model_job_state_result. An unknown status is an invalid_state error, not a running job.

State transitions

The closed state set is queued, running, succeeded, failed, and canceled.

Current stateAllowed next states
queuedrunning, succeeded, failed, canceled
runningsucceeded, failed, canceled
terminal statethe same state only

succeeded, failed, and canceled are terminal. A canceled job cannot later succeed. model_job_transition_result enforces this rule for all backends.

Run options and events

model_job_run_result(harness, backend, request, options) submits and polls one job. ModelJobRunOptions accepts:

FieldDefaultMeaning
timeout_ms300000Total polling deadline.
interval_ms500Delay between inspections.
max_attempts0Inspection limit; 0 has no attempt limit.
asset_rootruntime asset rootContent-addressed output directory.
session_idnoneAgent session that receives model_job transcript events.
on_eventnoneCallback for UI or CLI progress.

Events are ordered. Their kinds are submitted, state_changed, progress, output, and failed. Every event includes the request ID, job ID, backend, state, and monotonic timestamp.

After submission, polling, timeout, transition, and asset-storage errors emit a terminal failed event before model_job_run_result returns the typed error. This gives transcript and UI consumers a terminal state even when no receipt is created.

Receipt and media asset

A successful ModelJobReceipt contains the final job, ordered events, request digest, backend ID, and verified assets.

Each MediaAsset includes:

  • an asset://sha256/<digest> URI and SHA-256 digest;
  • MIME type, byte size, kind, and current path;
  • optional dimensions, duration, producing job, and metadata.

media_asset_store_result rejects bytes whose signature does not match the declared MIME type. media_asset_verify_result re-reads the file and rejects a changed digest, size, MIME type, or identity.

Test and replay backends

model_job_fake_backend(id, observations) consumes a fixed observation list. It has no network effects. Use it for lifecycle and UI tests.

model_job_replay_backend(receipt) replays recorded states and asset paths. It rejects a different request digest and never falls back to the live provider.

comfyui_backend(endpoint, build_workflow, options) implements the same interface over ComfyUI. Its graph builder is separate, so any API-format ComfyUI workflow can use the adapter. comfyui_flux2_klein_workflow is the included text-to-image graph.

openai_responses_image_backend(options) completes generation or editing in its submit call. It uses the OpenAI Responses API image-generation tool, accepts verified media assets as edit inputs, and returns base64 output as normal model-job assets. The API key is a required option and is never added to events or receipts.

Run the local backend with the ComfyUI how-to guide, or run the hosted backend with the OpenAI image how-to guide.