Overview
getRun() retrieves a Run object for an existing workflow execution, allowing you to check status, read results, access streams, and control execution.
Usage
import { getRun } from 'workflow/runtime' ;
const run = getRun ( 'wrun_123' );
const status = await run . status ;
Signature
function getRun < TResult >( runId : string ) : Run < TResult >
The workflow run ID (format: wrun_{ulid})
Returns: Run<TResult> - A Run instance for interacting with the workflow
Run Class
The Run class provides methods and properties for workflow interaction:
Properties
The unique identifier for this workflow run
status
Promise<WorkflowRunStatus>
Current status: 'pending', 'running', 'completed', 'failed', or 'cancelled'
The workflow’s return value. Polls until completion. Throws:
WorkflowRunFailedError if the workflow failed
WorkflowRunCancelledError if the workflow was cancelled
The name of the workflow function
Timestamp when the workflow run was created
startedAt
Promise<Date | undefined>
Timestamp when execution started, or undefined if not started yet
completedAt
Promise<Date | undefined>
Timestamp when execution completed, or undefined if not completed yet
The default readable stream for this workflow. Reads chunks written via getWritable().
Methods
getReadable()
Get a readable stream for this workflow run.
run . getReadable < R >( options ?: WorkflowReadableStreamOptions ): ReadableStream < R >
options
WorkflowReadableStreamOptions
Stream namespace to distinguish multiple streams
Starting chunk index (0-based)
Operations to complete before environment termination
Global object for hydrating types (defaults to globalThis)
wakeUp()
Interrupt pending sleep() calls. See Run.wakeUp() .
run . wakeUp ( options ?: StopSleepOptions ): Promise < StopSleepResult >
cancel()
Cancel the workflow execution.
run . cancel (): Promise < void >
Examples
Check Status
import { getRun } from 'workflow/runtime' ;
const run = getRun ( 'wrun_123' );
const status = await run . status ;
switch ( status ) {
case 'pending' :
console . log ( 'Workflow queued but not started' );
break ;
case 'running' :
console . log ( 'Workflow executing' );
break ;
case 'completed' :
console . log ( 'Workflow finished successfully' );
break ;
case 'failed' :
console . log ( 'Workflow encountered an error' );
break ;
case 'cancelled' :
console . log ( 'Workflow was cancelled' );
break ;
}
Get Return Value
import { getRun } from 'workflow/runtime' ;
import {
WorkflowRunFailedError ,
WorkflowRunCancelledError
} from '@workflow/errors' ;
const run = getRun ( 'wrun_123' );
try {
const result = await run . returnValue ;
console . log ( 'Workflow result:' , result );
} catch ( error ) {
if ( WorkflowRunFailedError . is ( error )) {
console . error ( 'Workflow failed:' , error . message );
console . error ( 'Run ID:' , error . runId );
} else if ( WorkflowRunCancelledError . is ( error )) {
console . log ( 'Workflow was cancelled' );
}
}
Stream Results
import { getRun } from 'workflow/runtime' ;
const run = getRun ( 'wrun_123' );
const reader = run . readable . getReader ();
try {
while ( true ) {
const { done , value } = await reader . read ();
if ( done ) break ;
console . log ( 'Received:' , value );
}
} finally {
reader . releaseLock ();
}
Multiple Streams
import { getRun } from 'workflow/runtime' ;
const run = getRun ( 'wrun_123' );
// Read from different stream namespaces
const progressStream = run . getReadable ({ namespace: 'progress' });
const logsStream = run . getReadable ({ namespace: 'logs' });
// Process streams independently
const progressReader = progressStream . getReader ();
const logsReader = logsStream . getReader ();
Cancel Workflow
import { getRun } from 'workflow/runtime' ;
const run = getRun ( 'wrun_123' );
// Cancel the workflow
await run . cancel ();
const status = await run . status ;
console . log ( status ); // 'cancelled'
import { getRun } from 'workflow/runtime' ;
const run = getRun ( 'wrun_123' );
const [ name , created , started , completed ] = await Promise . all ([
run . workflowName ,
run . createdAt ,
run . startedAt ,
run . completedAt ,
]);
console . log ( 'Workflow:' , name );
console . log ( 'Created:' , created );
console . log ( 'Started:' , started );
console . log ( 'Completed:' , completed );
if ( started && completed ) {
const duration = completed . getTime () - started . getTime ();
console . log ( 'Duration:' , duration , 'ms' );
}
Resume from Stream Position
import { getRun } from 'workflow/runtime' ;
const run = getRun ( 'wrun_123' );
// Start reading from chunk 100
const stream = run . getReadable ({ startIndex: 100 });
const reader = stream . getReader ();
while ( true ) {
const { done , value } = await reader . read ();
if ( done ) break ;
processChunk ( value );
}
API Route Handler
// app/api/workflow/[runId]/route.ts
import { getRun } from 'workflow/runtime' ;
export async function GET (
request : Request ,
{ params } : { params : { runId : string } }
) {
const run = getRun ( params . runId );
const [ status , name , createdAt ] = await Promise . all ([
run . status ,
run . workflowName ,
run . createdAt ,
]);
return Response . json ({
runId: run . runId ,
status ,
workflowName: name ,
createdAt ,
});
}
Streaming Response
// app/api/workflow/[runId]/stream/route.ts
import { getRun } from 'workflow/runtime' ;
export async function GET (
request : Request ,
{ params } : { params : { runId : string } }
) {
const run = getRun ( params . runId );
// Pipe workflow stream to response
return new Response ( run . readable , {
headers: {
'Content-Type' : 'text/event-stream' ,
'Cache-Control' : 'no-cache' ,
'Connection' : 'keep-alive' ,
},
});
}
Poll for Completion
import { getRun } from 'workflow/runtime' ;
const run = getRun ( 'wrun_123' );
// Poll every second until completed
while ( true ) {
const status = await run . status ;
if ( status === 'completed' || status === 'failed' || status === 'cancelled' ) {
break ;
}
await new Promise ( resolve => setTimeout ( resolve , 1000 ));
}
console . log ( 'Workflow finished' );
Error Handling
WorkflowRunFailedError
import { getRun } from 'workflow/runtime' ;
import { WorkflowRunFailedError } from '@workflow/errors' ;
const run = getRun ( 'wrun_123' );
try {
const result = await run . returnValue ;
} catch ( error ) {
if ( WorkflowRunFailedError . is ( error )) {
console . error ( 'Workflow failed' );
console . error ( 'Run ID:' , error . runId );
console . error ( 'Error:' , error . workflowError ?. message );
console . error ( 'Stack:' , error . workflowError ?. stack );
}
}
WorkflowRunCancelledError
import { getRun } from 'workflow/runtime' ;
import { WorkflowRunCancelledError } from '@workflow/errors' ;
const run = getRun ( 'wrun_123' );
try {
const result = await run . returnValue ;
} catch ( error ) {
if ( WorkflowRunCancelledError . is ( error )) {
console . log ( 'Workflow was cancelled' );
console . log ( 'Run ID:' , error . runId );
}
}
WorkflowRunNotFoundError
import { getRun } from 'workflow/runtime' ;
import { WorkflowRunNotFoundError } from '@workflow/errors' ;
const run = getRun ( 'wrun_invalid' );
try {
const status = await run . status ;
} catch ( error ) {
if ( WorkflowRunNotFoundError . is ( error )) {
console . error ( 'Run not found:' , error . runId );
}
}
Type Safety
import { getRun } from 'workflow/runtime' ;
// Define workflow return type
interface WorkflowResult {
success : boolean ;
data : string [];
}
// Type-safe run instance
const run = getRun < WorkflowResult >( 'wrun_123' );
// Return value is typed
const result = await run . returnValue ;
console . log ( result . success ); // ✓ TypeScript knows the shape
console . log ( result . data ); // ✓ Typed as string[]
Best Practices
Type the result : Use getRun<TResult>() for type-safe return values
Handle all error cases : Check for failed, cancelled, and not-found errors
Use streams for real-time updates : Don’t poll status, use streams instead
Store run IDs : Persist run IDs in your database for later retrieval
Check status before actions : Verify workflow state before cancel/wakeUp operations
Clean up readers : Always release stream readers when done
See Also