Orkestia
Blog
SDKs

Workflows SDK — Node / TypeScript

Typed ESM client for every Orkestia workflow — one autocompleted binding per type, SSE streaming, and wait-for-terminal

@ltinteg/workflows-sdk is the canonical typed client for the workflow engine. It is generated from the same catalog as reference.orkestia.dev: one start… binding per workflow, plus a small hand-written runtime for auth, retries, and SSE.

Requires Node ≥ 20. ESM only.

Install

npm i @ltinteg/workflows-sdk

Start a run

import { LtIntegWorkflowsClient, aws } from "@ltinteg/workflows-sdk"

const client = new LtIntegWorkflowsClient({
  baseUrl: "https://workflow-api.orkestia.dev",
  token: process.env.ORKESTIA_TOKEN, // org-member or end-user Bearer
})

// Optional: discover before you call
await client.catalog.listTypes({ prefix: "aws." })
await client.catalog.getSchema("aws.s3.create_bucket")

const run = await aws.s3.startCreateBucket(client, {
  bucket: "my-app-assets",
  connection_uuid: "…",
  region: "us-east-1",
})

console.log(run.workflowId, run.stateName)
const output = await run.wait()

Do not pass organization_uuid. The server resolves it from the token.

The aws.s3.create_bucket call above is illustrative. Resolve the live type name and input fields from the catalog or client.catalog.getSchema() before you ship.

Stream transitions

run.events() opens GET /api/workflows/{id}/stream and yields typed events until the run is terminal.

for await (const evt of run.events({ streamTimeoutSecs: 600 })) {
  if (evt.type === "transition") console.log(evt.from, "->", evt.to)
  if (evt.type === "completed") break
  if (evt.type === "failed") throw new Error(evt.error.message)
}

run.wait() (alias run.result()) consumes that stream and resolves to the terminal state_data, or throws WorkflowFailedError.

import { WorkflowFailedError } from "@ltinteg/workflows-sdk/errors"

try {
  const output = await run.wait()
} catch (err) {
  if (err instanceof WorkflowFailedError) console.error(err.failure)
}

AbortSignal is honored on start, get, and stream:

const ac = new AbortController()
setTimeout(() => ac.abort(), 5_000)
for await (const evt of run.events({ signal: ac.signal })) { /* … */ }

Catalog and lifecycle

CallREST equivalentPurpose
client.catalog.listTypes({ prefix })GET /api/workflows/typesDiscover types
client.catalog.getSchema(type)GET /api/workflows/types/{type}/schemaInput / output + has_prerequisites
client.catalog.getDefinition(type)definition endpointFull registered definition
client.workflows.get(id)GET /api/workflows/{id}Current state
client.workflows.history(id)GET /api/workflows/{id}/historyEvent-sourced log
client.workflows.retry(id)POST /api/workflows/{id}/retryRe-drive a FAILED run
client.workflows.list({ workflowType })GET /api/workflows/findFind runs of one type

Generated bindings (aws.s3.startCreateBucket, github.startValidateToken, …) are thin wrappers over client.start(...) that add typed inputs and return a WorkflowRunHandle.

client.workflows.cancel() throws WorkflowNotImplementedError — the deployed API has no cancel endpoint. The method exists so call sites type-check.

Errors

Every error extends WorkflowError (a real Error subclass, so instanceof works) and carries requestId when the server sent X-Request-Id.

ClassWhen
WorkflowStartErrorStart rejected (validation, auth, prerequisites)
WorkflowNotFoundErrorUnknown workflow_id
WorkflowTimeoutErrorStream / wait exceeded the timeout
WorkflowFailedErrorRun reached FAILED
WorkflowStreamErrorSSE transport failed
WorkflowNotImplementedErrorCalled a method the API does not expose
WorkflowCancelledErrorAborted via AbortSignal
import { WorkflowStartError } from "@ltinteg/workflows-sdk/errors"

Auth

Pass either token kind into the client. For browser apps acting as an end-user, take the JWT from @orkestia/auth and do not embed an org-member token in the page.

import { createOrkestiaAuth } from "@orkestia/auth"
import { LtIntegWorkflowsClient } from "@ltinteg/workflows-sdk"

const auth = createOrkestiaAuth({ clientKey: "orkestia_…" })
const session = auth.getSession()

const client = new LtIntegWorkflowsClient({
  baseUrl: "https://workflow-api.orkestia.dev",
  token: session.token,
  credentials: "include", // browsers only; omit in Node
})

See API & tooling for the two-token model.

Python SDK

The same catalog, in Python.

Auth SDK

Mint the end-user JWT this client can hold.

REST surface

Raw HTTP if you are not in Node.