Operations
The write vocabulary: a small set of ops that mutate an instance’s fields and statuses, carried by actions and by effect completions.
Prerelease
Editorial Workflows is a prerelease, built in public. Read How the prerelease works before you rely on it.
Operations are the small, declarative state changes carried by actions. Author each operation with defineOp(...) so its shape is validated where it is declared. Conditions decide whether something can happen; operations record what happened.
They formalize the same idea as Sanity mutations, but they are not raw mutations sent directly to the Content Lake. The engine resolves their targets and values, validates the result against the workflow definition, records history, and applies the change to the instance.
Every operation carried by one action or effect completion executes in declaration order inside the same atomic transaction. The operations, activity status, queued effects, history, and idempotency record either commit together or do not commit at all.
defineAction({
name: 'approve',
ops: [
defineOp({
type: 'field.set',
target: {field: 'approvedBy'},
value: {type: 'actor'},
}),
],
status: 'done',
})The action above records the acting identity and completes its activity in the same engine commit. Later conditions immediately see the new field value.
Values are expressions
An operation’s value is a serializable expression, not necessarily a fixed value. The engine resolves it when the operation runs, so definitions can copy fields, consume action parameters, stamp the actor or time, and construct nested objects without application code assembling the final value.
const recordDecision = defineOp({
type: 'field.set',
target: {field: 'decision'},
value: {
type: 'object',
fields: {
approved: {type: 'fieldRead', field: 'approved'},
reason: {type: 'param', param: 'reason'},
decidedBy: {type: 'actor'},
decidedAt: {type: 'now'},
},
},
})Set and clear fields
Use field.set to replace a field value and field.unset to clear it. Values may be literals or expressions resolved when the action runs.
defineAction({
name: 'change-deadline',
params: [{name: 'deadline', type: 'datetime', required: true}],
ops: [
defineOp({
type: 'field.set',
target: {field: 'deadline'},
value: {type: 'param', param: 'deadline'},
}),
defineOp({type: 'field.unset', target: {field: 'reminderSentAt'}}),
],
})Common value expressions read an action parameter, another field, the actor, the current time, stage, or instance reference. The complete operation and value forms are listed in Reference.
Append to a list
Use field.append for notes, audit rows, and other list entries.
defineAction({
name: 'add-note',
params: [{name: 'body', type: 'string', required: true}],
ops: [
defineOp({
type: 'field.append',
target: {field: 'notes'},
value: {
type: 'object',
fields: {
body: {type: 'param', param: 'body'},
actor: {type: 'actor'},
at: {type: 'now'},
},
},
}),
],
})The audit authoring shorthand is a stamped append: it adds the acting identity and time to the row it writes.
Update or remove matching rows
field.updateWhere merges into matching rows of an array field. field.removeWhere removes matching rows from any list field.
defineAction({
name: 'complete-item',
params: [{name: 'itemKey', type: 'string', required: true}],
ops: [
defineOp({
type: 'field.updateWhere',
target: {field: 'todoList'},
where: '$row._key == $params.itemKey',
value: {
type: 'object',
fields: {
status: {type: 'literal', value: 'done'},
},
},
}),
defineOp({
type: 'field.removeWhere',
target: {field: 'watchers'},
where: '$row.id == $actor.id',
}),
],
})Always available
$row, $self, $fields, $parent, $ancestors, $stage, $now, $context, $effects, $effectStatus, $activities, $allActivitiesDone, $anyActivityFailed, $subworkflows
All operation
whereexpressions.Acting action
$actor, $assigned
Available when an acting token rides the action.
Caller-fired action
$params
Unavailable on operations fired by cascade actions.
Unavailable
$can
Never bound in
where. See Conditions.
Actions and effect completions
Actions may use every operation, including status.set. The status authoring key is shorthand for setting the firing activity’s status.
A successful effect completion returns runtime result data, so its five supported field.* operations are written directly rather than with the definition-authoring helper defineOp(...). Completion targets must name their workflow or stage scope explicitly, and completions can never use status.set: effects report field state, while actions and transitions decide what that result means.
return {
ops: [
{
type: 'field.set',
target: {scope: 'stage', field: 'generatedDocument'},
value: {type: 'literal', value: documentRef},
},
],
}Operations only change instance state. External work belongs in Effects and runtimes. Every accepted operation commits with its action or effect completion, so subsequent conditions evaluate the committed result.
Recover a terminal activity
Use resetActivity when work in the current stage has failed or otherwise reached a terminal status. Reset to active to rerun it, or to skipped to bypass it. The engine records the change and continues the transition cascade.
await engine.resetActivity({
instanceId,
activity: 'publish',
})
await engine.resetActivity({
instanceId,
activity: 'publish',
to: 'skipped',
})Reference
Operation catalogue
Use these objects in an action’s ops array with defineOp(...). Successful effect completions may return the five field.* forms directly as runtime result data.
field.set
Any field
Replaces the field value with a resolved value expression. Runtime-written references must target a declared resource.
field.unset
Any field
Clears the field value.
field.append
List field
Appends a resolved value to a list field. The value must match the declared member shape.
field.updateWhere
array
Merges an object into rows selected by
where. Valid only forarrayfields; merged rows must retain the declared shape, and the merge cannot write_keyor_type.field.removeWhere
Any list field
Removes rows selected by
where. Valid for every list field, includingdoc.refs.status.set
Activity
Sets an activity to
active,done,skipped, orfailed. Available to actions, not effect completions; it defaults to the firing activity but may name a sibling activity.
Value expressions
Set one of these serializable objects as an operation’s value. The engine resolves it when the operation executes.
literal
{type: ‘literal’, value}
Uses a fixed value authored in the definition or supplied by a trusted completion result.
fieldRead
{type: ‘fieldRead’, field, scope?, path?}
Reads another field or one of its nested paths.
param
{type: ‘param’, param}
Reads a parameter supplied to the firing action.
actor
{type: ‘actor’}
Uses the acting identity.
now
{type: ‘now’}
Uses the shared timestamp for the engine operation.
self
{type: ‘self’}
Uses the current instance’s global document reference.
stage
{type: ‘stage’}
Uses the current stage name.
object
{type: ‘object’, fields}
Builds an object recursively from other value expressions.
Visiting agent?
Editorial Workflows includes an MCP server for inspecting, operating, authoring, validating, and deploying workflows. Ask your human to set up the MCP server.