Orchestration Overview
Prod path: the orchestration packages are currently pre-1.0 (
0.0.2) in this worktree. Start with Jobs and Orchestration if you are evaluating whether to adopt them.
Slingshot orchestration is a portable runtime for two related concepts:
- Tasks: named, retryable units of work
- Workflows: ordered sequences of tasks with optional parallel branches and durable sleeps
The point of the abstraction is that application code should not care whether runs execute in memory, SQLite, or BullMQ. You define the work once, then swap adapters as infrastructure changes.
Packages
Section titled “Packages”| Package | Role |
|---|---|
@lastshotlabs/slingshot-orchestration-engine | Portable task/workflow definitions, runtime, memory adapter, SQLite adapter |
@lastshotlabs/slingshot-orchestration | Slingshot plugin integration, runtime lookup helpers, HTTP routes |
@lastshotlabs/slingshot-orchestration-bullmq | BullMQ-backed adapter for Redis deployments |
@lastshotlabs/slingshot-orchestration-temporal | Temporal-backed adapter and worker supervisor for distributed orchestration |
Current support
Section titled “Current support”| Adapter / Provider | Status | Notes |
|---|---|---|
| Memory | Supported | In-process, non-durable |
| SQLite | Supported | Durable single-node execution |
| BullMQ | Supported | Redis-backed queues, scheduling, progress |
| Temporal | Supported | Distributed workers, schedules, signals |
| Manifest mode | Supported | Handlers-file task/workflow discovery |
| Trigger.dev | Not shipped yet | Planned follow-up provider |
| Step Functions | Not shipped yet | Planned follow-up provider |
Current provider support now includes @lastshotlabs/slingshot-orchestration-temporal.
Trigger.dev and the other cloud-provider adapters are still follow-up work, but Temporal support
is implemented in this worktree.
Define tasks and workflows in TypeScript, then compose them into a runtime or Slingshot plugin.
import { z } from 'zod';import { createMemoryAdapter, createOrchestrationRuntime, defineTask,} from '@lastshotlabs/slingshot-orchestration-engine';
const resizeImage = defineTask({ name: 'resize-image', input: z.object({ assetId: z.string() }), output: z.object({ ok: z.boolean() }), async handler(input) { return { ok: true }; },});
const runtime = createOrchestrationRuntime({ adapter: createMemoryAdapter({ concurrency: 10 }), tasks: [resizeImage],});For Slingshot integration:
import type { MiddlewareHandler } from 'hono';import { z } from 'zod';import { createOrchestrationPackage } from '@lastshotlabs/slingshot-orchestration';import { createMemoryAdapter, defineTask } from '@lastshotlabs/slingshot-orchestration-engine';
const resizeImage = defineTask({ name: 'resize-image', input: z.object({ assetId: z.string() }), output: z.object({ ok: z.boolean() }), async handler() { return { ok: true }; },});
const requireAdmin: MiddlewareHandler = async (_c, next) => { await next();};
const orchestrationPlugin = createOrchestrationPackage({ adapter: createMemoryAdapter({ concurrency: 10 }), tasks: [resizeImage], workflows: [], routes: true, routeMiddleware: [requireAdmin],});When the adapter is passed directly into createOrchestrationRuntime(), the built-in adapters are
ready to use immediately. Memory and SQLite still manage their own lifecycle as before, and the
BullMQ adapter now lazily starts itself on first use so direct runtime composition is
safe.
Handlers and manifest status
Section titled “Handlers and manifest status”Manifest-driven orchestration is now supported.
- You can still define tasks and workflows directly in TypeScript and pass them into the runtime.
createServer()loadsResolvedTaskandResolvedWorkflowexports from the handlers file or handlers directory.- The built-in
slingshot-orchestration-engineplugin resolves task and workflow names from that registry before the plugin is instantiated.
That means orchestration definitions stay in code alongside the rest of the app config.
Design boundary
Section titled “Design boundary”The orchestration domain owns:
- task and workflow definitions
- retries, timeouts, cancellation, progress, and run state
- provider adapter contracts
Outer integration layers own:
- Slingshot plugin lifecycle
- HTTP routes
- manifest bootstrap
- provider SDK wiring
That split is deliberate. It keeps the runtime transport-neutral and makes future providers possible without rewriting application code.