Activities and actions
Activities represent work in a stage. Actions let callers and triggers update workflow state, queue effects, and resolve that work.
Prerelease
Editorial Workflows is a prerelease, built in public. Read How the prerelease works before you rely on it.
An activity is a unit of work scoped to one stage visit. Its actions are the named responses available while that work is active. A caller invokes an action; the engine fires an action with a condition as an automated trigger. See Stages and transitions for how activities fit into a stage visit.
Firing an action commits its operations atomically. It may also set an activity outcome in that commit. Transitions evaluate the resulting state; actions do not move the instance directly. Effects run after the commit for external work.
Define an activity
Declare the work, when it applies, when it is ready, and the actions available while it is active:
defineActivity({
name: 'review',
title: 'Review article',
filter: '$fields.needsReview',
requirements: {assigned: 'defined($fields.reviewer)'},
actions: [
defineAction({name: 'approve', status: 'done'}),
],
})Existence and readiness
An activity filter decides whether the activity exists for a stage visit. Ordered GROQ requirements keep an existing activity visible while blocking its caller-fired actions until every requirement passes.
defineActivity({
name: 'review',
requirements: [
{
type: 'groq',
name: 'assigned-reviewer',
title: 'Assigned reviewer required',
query: '$assigned',
},
],
actions: [defineAction({name: 'approve', status: 'done'})],
})Both properties use conditions, but they answer different questions.
filter
Condition
Controls whether the activity belongs to a stage visit. An excluded activity is recorded as skipped and does not block completion.
requirements
GroqRequirement[]
Ordered named readiness gates. Unmet requirements keep the activity visible but block caller-fired actions.
An included activity remains active until an action resolves it as done, skipped, or failed. Resolving an activity does not move the instance; a transition controls movement.
Define actions
Actions are commands attached to an activity. They can change workflow state, queue external work, start child workflows, and optionally resolve the activity.
Omit when for a caller-fired action. Add when for an automated trigger.
The first example records approval, resolves the review, and queues a notification. The second adds a condition so the engine can trigger it automatically:
defineAction({
name: 'approve',
ops: [
{type: 'field.set', target: {field: 'approval'}, value: {type: 'actor'}},
],
effects: [
{
name: 'notify-reviewer',
bindings: {to: '$fields.reviewer'},
input: {body: 'Your article was approved'},
},
],
status: 'done',
})
defineAction({
name: 'escalate',
when: '$fields.dueDate < $now',
effects: [{name: 'notify-editor', bindings: {to: '$fields.editor'}}],
})Caller actions and automation
Without when
Caller-fired action
A caller invokes it through fireAction. A UI may present it as a control.
With when
Automated trigger
The engine fires it automatically when its condition becomes true.
Triggers run in declaration order. Re-entering the stage starts a new visit and allows them to fire again.
Resolve an activity
Use status for the outcome of the work, not the business decision:
done— the work completed, including approve, decline, send back, or hold.skipped— the work did not apply.failed— the work could not complete.
For a business decision, resolve the activity as done and write the decision to a field that a transition condition reads.
What actions can do
Actions can combine immediate operations, queued effects, child workflows, and an optional activity status.
Preview an action’s flow consequence
Action evaluation can preview what firing a caller action would do to the flow in the current state. Use it to place or label controls without duplicating transition logic.
const evaluation = await engine.evaluate({instanceId})
const approve = evaluation.currentStage.activities
.flatMap(({actions}) => actions)
.find(({action}) => action.name === 'approve')
if (approve?.firing?.exitsStage) {
console.log(`Approve exits through ${approve.firing.transition}`)
}exitsStage
boolean
True when the replayed action and cascade leave the current stage.
transition
string | undefined
The selected transition name when exitsStage is true.
The preview is advisory and describes the current projection. It is omitted when a faithful replay needs unavailable inputs, including caller parameters or dataset-driven spawn results, and for automated triggers.
Condition variables
Activity and action conditions use the GROQ variables defined by Conditions. Caller-fired sites can also bind the current actor and permissions; cascade-fired sites cannot.
All sites
Instance variables
Workflow state such as $fields, $stage, $activities, and $context.
Caller-bound sites
$actor, $assigned, $can
Available to activity requirements and caller-fired action filters.
Cascade sites
No caller variables
Activity filters and triggered action conditions run without a caller.
Reference
Activity declaration
This is the object passed to defineActivity(...) in a stage’s activities array.
name
string
Required stable activity name.
title
string
Optional display label.
description
string
Optional explanation.
groups
Group[]
Groups declared for this activity’s fields and actions.
group
string | string[]
Groups this activity joins.
target
ManualTarget
Optional deep link for work performed outside Editorial Workflows.
filter
Condition
Existence condition evaluated at stage entry.
requirements
GroqRequirement[]
Ordered named readiness gates; all must pass before caller-fired actions are executable.
actions
Action[]
Actions that can resolve work or change instance state.
fields
Field[]
Activity-scoped fields resolved at stage entry.
Action declaration
This is the object passed to defineAction(...) in an activity’s actions array.
name
string
Required stable action name.
title
string
Optional display label.
description
string
Optional explanation.
group
string | string[]
Groups this action joins.
when
Condition
When present, makes this a cascade-fired trigger; otherwise callers use
fireAction.filter
Condition
Existence condition for the action.
roles
string[]
Advisory role requirement; trigger roles also pin cascade execution.
params
ActionParam[]
Caller-supplied values validated before the action commits.
ops
Operation[]
Synchronous instance mutations committed with the firing.
effects
Effect[]
External work queued by the firing.
spawn
Subworkflows
Child workflows spawned by the firing.
status
done | skipped | failed
Authoring shorthand for a final
status.seton the firing activity.semantics
Array<'decision.accept' | 'decision.decline'>
Optional advisory decision meaning for ordinary actions; accepts at most one value.
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.