Editorial Workflows

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

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 where expressions.

  • Acting action

    $actor, $assigned

    Available when an acting token rides the action.

  • Unavailable on operations fired by cascade actions.

  • 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.

  • Merges an object into rows selected by where. Valid only for array fields; merged rows must retain the declared shape, and the merge cannot write _key or _type.

  • field.removeWhere

    Any list field

    Removes rows selected by where. Valid for every list field, including doc.refs.

  • status.set

    Activity

    Sets an activity to active, done, skipped, or failed. 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?

Was this page helpful?