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
mainand 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 flagCLOCKWORK_PLANNING_V2is 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 answer404. 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
| Method | Description |
|---|---|
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
| Parameter | Type | Required | Description |
|---|---|---|---|
name | string | yes | Template name |
description | string | no | Human-readable description |
projectId | string | no | Defaults to your personal project |
manifest | Record<string, unknown> | no | Initial graph snapshot (nodes/edges) |
roles | RoleSlotInput[] | no | Role slots for version 1 |
Example
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_... 1workflowTemplates.publish(templateId, input)
Publishes a new immutable version. Existing instances are unaffected.
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.
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.
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:
await client.workflowTemplates.putAlias('tmpl_abc123', 'stable', { version: 5 })
await client.workflowTemplates.putAlias('tmpl_abc123', 'latest', { version: 6 })workflowTemplates.diffVersions(templateId, version, against)
const { data: diff } = await client.workflowTemplates.diffVersions('tmpl_abc123', 5, 6)
console.log(diff.added, diff.removed, diff.changed)Type reference
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>
}Related
- Workflow Instances — run a template as a live instance, with overrides, excludes and role bindings
- Roles — fill role slots when instantiating a template