Skip to content

WorkflowClientlf.workflows

Manage and execute multi-node AI workflows. All methods require an authenticated client (apiKey in createClient).


lf.workflows.browse(options?)

List workflows visible to the authenticated user. Calls fn_mcp_workflow_list.

Parameters

ParameterTypeDefaultDescription
options.limitnumber20Max workflows to return.
options.offsetnumber0Records to skip.
options.visibilitystringnullFilter by visibility ('public', 'community', 'private'). null returns all accessible.

Returns Promise<SdkWorkflowSummary[]>

ts
const workflows = await lf.workflows.browse({ limit: 10, visibility: 'public' })
for (const w of workflows) {
  console.log(w.id, w.title)
}

SdkWorkflowSummary

FieldTypeDescription
idstringUUID of the workflow.
titlestringDisplay name.
descriptionstring | nullOptional description.
visibilitystring'public' | 'community' | 'private'
createdAtstringISO 8601 timestamp.

lf.workflows.getById(workflowId)

Fetch full detail for a single workflow. Calls fn_mcp_workflow_get.

Parameters

ParameterTypeDescription
workflowIdstringUUID of the workflow.

Returns Promise<SdkWorkflowDetail | null>

Returns null if not found or not accessible to the caller.

ts
const workflow = await lf.workflows.getById('550e8400-e29b-41d4-a716-446655440000')
if (workflow) {
  console.log(workflow.title, workflow.updatedAt)
}

SdkWorkflowDetail extends SdkWorkflowSummary:

Additional fieldTypeDescription
updatedAtstringISO 8601 timestamp of the last update.

lf.workflows.startRun(workflowId, inputs?, options?)

Start a workflow run asynchronously. Returns immediately with a run ID and pending status. The actual execution happens on the server — use getRunStatus to poll or awaitRun to block until completion.

Calls fn_mcp_workflow_run_start. Requires an authenticated client.

Parameters

ParameterTypeDefaultDescription
workflowIdstringUUID of the workflow to run.
inputsRecord<string, unknown>{}Named input values passed to the first node.
options.idempotencyKeystringnullOptional deduplication key. Submitting the same key twice returns the first run instead of creating a second one.
options.modelIdstringnullOverride the model used by all nodes in this run.

Returns Promise<SdkWorkflowRun>

ts
const run = await lf.workflows.startRun(
  workflowId,
  { topic: 'TypeScript generics', depth: 'intermediate' },
  { idempotencyKey: `run-${Date.now()}` },
)
console.log(run.id, run.status)  // status is 'pending' immediately after start

SdkWorkflowRun

FieldTypeDescription
idstringUUID of the run. Use this to poll or fetch logs.
statusSdkWorkflowRunStatusInitial status — always 'pending' on return from startRun.
createdAtstringISO 8601 timestamp.

lf.workflows.getRunStatus(runId)

Poll the current status of a workflow run. Calls fn_mcp_workflow_run_status.

Parameters

ParameterTypeDescription
runIdstringUUID of the run (from startRun or awaitRun).

Returns Promise<SdkWorkflowRunState>

Throws if runId is not found.

ts
const state = await lf.workflows.getRunStatus(run.id)
console.log(state.status)         // 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'
console.log(state.activeNodeId)   // which node is currently executing, or null
console.log(state.creditsSpent)   // credits consumed so far

SdkWorkflowRunState

FieldTypeDescription
idstringRun UUID.
statusSdkWorkflowRunStatusCurrent lifecycle status.
activeNodeIdstring | nullThe node currently executing. null when idle or finished.
creditsSpentnumberCumulative credits consumed by this run.

SdkWorkflowRunStatus values: 'pending''running''completed' | 'failed' | 'cancelled'


lf.workflows.getRunLogs(runId)

Fetch per-node execution logs for a completed run. Calls fn_mcp_workflow_run_logs. Calling this before the run reaches a terminal state returns partial or empty results.

Parameters

ParameterTypeDescription
runIdstringUUID of the run.

Returns Promise<SdkWorkflowRunLog[]>

ts
const logs = await lf.workflows.getRunLogs(run.id)
for (const log of logs) {
  console.log(`Node ${log.nodeId}: ${log.status} — ${log.durationMs}ms`)
  if (log.result) console.log('  result:', JSON.stringify(log.result).slice(0, 200))
  if (log.error) console.error('  error:', log.error)
}

SdkWorkflowRunLog

FieldTypeDescription
nodeIdstringUUID of the workflow node.
statusstringNode-level status: 'completed', 'failed', etc.
resultunknown | nullOutput produced by the node (arbitrary JSON).
errorstring | nullError message if the node failed.
durationMsnumberWall-clock time the node took to execute.
tokenCountnumberTotal tokens consumed by this node (0 for non-LLM nodes).

lf.workflows.awaitRun(workflowId, inputs?, options?)

Start a run and block until it reaches a terminal state, then return the execution logs. Internally calls startRun, then polls getRunStatus every 3 seconds, and calls getRunLogs on success.

Use this for simple fire-and-forget execution where you want results synchronously.

Parameters

ParameterTypeDefaultDescription
workflowIdstringUUID of the workflow to run.
inputsRecord<string, unknown>{}Named inputs for the first node.
options.idempotencyKeystringnullOptional dedup key (same as startRun).
options.modelIdstringnullModel override (same as startRun).
options.timeoutMsnumber120000Maximum milliseconds to wait before throwing a timeout error.

Returns Promise<SdkWorkflowRunLog[]>

Throws if:

  • The run ends with status 'failed' or 'cancelled'.
  • The timeout elapses before a terminal state is reached.
ts
// Fire and await in one call
const logs = await lf.workflows.awaitRun(
  workflowId,
  { topic: 'AI safety' },
  { timeoutMs: 60_000 },
)

console.log(`Run completed. ${logs.length} nodes executed.`)
for (const log of logs) {
  console.log(`  ${log.nodeId}: ${log.status}  (${log.durationMs}ms)`)
}

When to use startRun vs awaitRun

Use awaitRun for simple scripts and short-lived server functions. Use startRun + getRunStatus when you need to store the runId in a database, display progress in a UI, or handle timeouts and retries yourself.


Full example — run a workflow and print results

ts
import { createClient } from '@lenserfight/sdk'

const lf = createClient({
  url: process.env.LF_URL!,
  anonKey: process.env.LF_ANON_KEY!,
  apiKey: process.env.LF_API_KEY!,
})

// List available workflows
const workflows = await lf.workflows.browse({ visibility: 'public' })
const target = workflows.find(w => w.title.includes('Research'))
if (!target) throw new Error('Workflow not found')

// Start and wait
try {
  const logs = await lf.workflows.awaitRun(
    target.id,
    { query: 'renewable energy storage breakthroughs 2025' },
    { timeoutMs: 90_000 },
  )
  console.log('Done!', logs.map(l => `${l.nodeId}: ${l.status}`))
} catch (err) {
  console.error('Workflow failed or timed out:', err)
}