Workflow Templates

A Workflow Template is a reusable blueprint that defines the structure of a workflow — its tasks, dependencies, and role slots — without running it. Each time you need a new execution of the same workflow shape, you create a WorkflowInstance from the template.

Planning v2 availability. Merged to main and deployed to production (platform.clockwork-co.com; F1 to F7 and F9 to F11 on 2026-10-09, F12 pool assignment and the security fixes on 2026-10-12). The platform flag CLOCKWORK_PLANNING_V2 is currently on globally, in production and in preview, as of 2026-10-12: every organization gets planning-v2 behavior, and with the flag off the planning-v2 endpoints answer 404. Per-organization gating (CLOCKWORK_PLANNING_V2=orgs) is merged but not enabled in production, so the global flag is the only access control in effect. Exact dates and commits: Changelog. Template overrides, excludes and role bindings (F8) are merged (#275, 2026-10-12) but not yet deployed to production: the production deployment of that merge failed on Vercel and is awaiting a retry. The rest of this page is live.

Templates are versioned immutably. Publishing a new version never modifies past instances.

When to use client.workflowTemplates

  • Defining standard operating procedures (e.g., "Customer Onboarding", "Contract Review")
  • Building a template library that your team can instantiate on demand
  • Rolling back to a prior template version when a change introduces problems
  • Pinning instances to specific template versions via aliases like "stable"

Methods

MethodDescription
create(input)Create a template (optionally with a v1 manifest and role slots)
get(templateId)Fetch a template
update(templateId, input)Update name or description
delete(templateId)Delete template and all its versions
list(opts?)List templates in a project
publish(templateId, input)Publish a new version with an updated manifest
listVersions(templateId)List immutable version history
diffVersions(templateId, v1, v2)Compare two versions
rollback(templateId, targetVersion)Roll back to a prior version (creates a new version)
listAliases(templateId)List named aliases
putAlias(templateId, alias, input)Point an alias at a specific version
deleteAlias(templateId, alias)Delete an alias

workflowTemplates.create(input)

Parameters

ParameterTypeRequiredDescription
namestringyesTemplate name
descriptionstringnoHuman-readable description
projectIdstringnoDefaults to your personal project
manifestRecord<string, unknown>noInitial graph snapshot (nodes/edges)
rolesRoleSlotInput[]noRole slots for version 1

Example

typescript
const { data: template } = await client.workflowTemplates.create({
  name: 'Customer Onboarding',
  description: 'Standard new-customer workflow',
  roles: [
    { slotName: 'account-manager', required: true, description: 'Leads the onboarding' },
    { slotName: 'technical-lead', required: false },
  ],
})
 
console.log(template.id, template.version) // tmpl_... 1

workflowTemplates.publish(templateId, input)

Publishes a new immutable version. Existing instances are unaffected.

typescript
await client.workflowTemplates.publish('tmpl_abc123', {
  manifest: {
    nodes: [
      { id: 'task-1', name: 'Send welcome email', durationMinutes: 15 },
      { id: 'task-2', name: 'Schedule kickoff call', durationMinutes: 30 },
    ],
    edges: [{ from: 'task-1', to: 'task-2' }],
  },
  roles: [
    { slotName: 'account-manager', required: true },
  ],
})

Instantiating a template

A template is turned into a running job with workflowInstances.create({ templateId, anchorDate }). Each manifest node becomes a task starting at anchorDate + its offsetFromAnchorMin; each edge becomes a dependency.

Behind CLOCKWORK_PLANNING_V2 you can customise one instantiation without publishing a new version: overrides (per node key: title, description, durationMinutes, bufferAfterMinutes, isFixed, offsetFromAnchorMin; per "from->to": lagMinutes), exclude (node keys to skip, with excludeMode: 'bridge' | 'drop' for the dependencies around them) and roleBindings (slot name -> resource id). Node keys are the key fields of the manifest nodes ({ key, title, durationMinutes, offsetFromAnchorMin, roleSlot, ... }); an unknown key is a 422 that lists it. Only fields that exist on a manifest node can be overridden. See Instantiate a template with overrides for the exact semantics, response and errors.

typescript
const { data: job } = await client.workflowTemplates.create({
  name: 'Brochure run',
  manifest: {
    kind: 'clockwork.workflow-manifest',
    schemaVersion: 1,
    nodes: [
      { key: 'prep', title: 'Prepare plates', durationMinutes: 30, offsetFromAnchorMin: 0 },
      { key: 'run', title: 'Run press', durationMinutes: 60, offsetFromAnchorMin: 0, roleSlot: 'operator' },
      { key: 'pack', title: 'Pack and label', durationMinutes: 20, offsetFromAnchorMin: 0 },
    ],
    edges: [{ from: 'prep', to: 'run', lagMinutes: 10 }, { from: 'run', to: 'pack', lagMinutes: 15 }],
  },
  roles: [{ slotName: 'operator' }],
}).then(({ data: t }) =>
  client.workflowInstances.create({
    templateId: t.id,
    exclude: ['pack'],
    overrides: { run: { durationMinutes: 90 } },
    roleBindings: { operator: operatorResourceId },
  }),
)

workflowTemplates.rollback(templateId, targetVersion)

Creates a new version that is a copy of the target version. Never mutates history.

typescript
const { data: newVersion } = await client.workflowTemplates.rollback('tmpl_abc123', 3)
console.log(newVersion.version) // 7 (current version after rollback)

workflowTemplates.putAlias(templateId, alias, input)

Points a named alias at a specific version. Useful for deployment pipelines:

typescript
await client.workflowTemplates.putAlias('tmpl_abc123', 'stable', { version: 5 })
await client.workflowTemplates.putAlias('tmpl_abc123', 'latest', { version: 6 })

workflowTemplates.diffVersions(templateId, version, against)

typescript
const { data: diff } = await client.workflowTemplates.diffVersions('tmpl_abc123', 5, 6)
console.log(diff.added, diff.removed, diff.changed)

Type reference

typescript
interface WorkflowTemplate {
  id: string
  projectId: string
  name: string
  description: string | null
  version: number
  metadata: Record<string, unknown> | null
  createdAt: string
  updatedAt: string
}
 
interface RoleSlotInput {
  slotName: string
  description?: string
  required?: boolean
  constraints?: Record<string, unknown>
}
  • Workflow Instances — run a template as a live instance, with overrides, excludes and role bindings
  • Roles — fill role slots when instantiating a template