Skip to main content

Built-in Core Activities

Three activities with no external dependency: read the clock, pause, and run a whole workflow inside a single activity.

The rest of the builtin.* namespace is documented separately — state, secret, event and deploy.

Defaults

ActivityTimeoutMax attemptsLocal
builtin.now1yes
builtin.delay1yes
builtin.execute_workflow86400 s (1 day)1no

builtin.now and builtin.delay run locally by default because a trip to a worker queue would cost more than the work itself.


builtin.now

Returns the current timestamp on the worker.

Input

None.

Output

A datetime value (not an object with fields). Assign it with output_name and use it directly.

Example

From moco-examples/moco-workflow-demo/src/activity-options-demo.yaml:

- activity:
name: get-timestamp
type: builtin.now
output_name: started_at
- transform:
output_data:
- run_label: "{{ started_at.strftime('%Y-%m-%d') }}"
- elapsed_sec: "{{ (finished_at - started_at).total_seconds() }}"
Determinism

builtin.now reads the worker's clock at execution time. On the Temporal runtime the value is recorded in workflow history, so a replay sees the original timestamp rather than the clock of the replaying worker.


builtin.delay

Pauses the workflow for a given duration.

Input

FieldTypeRequiredDefaultDescription
durationstr | numbernonullHow long to wait. A number is seconds; a string is a pandas-style interval such as 5s, 10min, 1h30m. Omitting it is a no-op

Output

true when a delay was performed, null when duration was omitted.

Example

- activity:
name: wait_5_seconds
description: Delay execution for 5 seconds
type: builtin.delay
input_data:
duration: 5s

A polling loop:

- iteration:
input_data: "{{ range(max_polls) }}"
body:
sequence:
elements:
- activity:
type: http.request
input_data:
method: GET
url: "{{ status_url }}"
output_json: true
output_name: status
- abort:
condition: "{{ status['json']['state'] == 'done' }}"
type: break_iteration
- activity:
type: builtin.delay
input_data:
duration: 30s
Long waits belong in wait_for

builtin.delay holds an activity slot for its whole duration. To pause for hours or days, or until something happens, use a wait_for statement or a state machine instead — see Events.


builtin.execute_workflow

Runs an entire workflow in memory, inside one activity, using an embedded engine.

Reach for it when a workflow moves large data between steps. On the Temporal runtime every activity input and output crosses the wire and is capped at 2 MB; an embedded run keeps intermediate data in the worker's process, so neither limit nor marshalling cost applies.

The trade is observability: steps inside the embedded workflow are not individual Temporal activities, so they get no per-step history and no per-step retry. The whole embedded run succeeds or fails as one unit.

Input

FieldTypeRequiredDefaultDescription
wfspecWorkflowSpecInfoyesWhich workflow to run
input_dataanynonullInput passed to that workflow
optionsWorkflowExecuteOptionsnonullExecution options

WorkflowSpecInfo

Identify a deployed workflow by name (plus optional version), or supply the spec inline as content. Inline content is how a dynamically generated workflow is run without deploying it.

FieldTypeRequiredDefaultDescription
namestrnonullName of a deployed workflowspec
versionstrnolatestVersion to run
contentstr | list[str]nonullThe workflowspec YAML itself

WorkflowExecuteOptions

The commonly used fields; all are optional.

FieldTypeDescription
debug_modeboolPublish debug events for the embedded run
catch_exceptionboolReturn the error instead of failing the activity
trace_idstrCorrelate the embedded run with the caller's trace
workflow_idstrIdentifier for the embedded run
tierstrExecution tier
child_modestrHow the run relates to its parent
execute_modestrin-memory, standalone-activity or workflow
retry_policydictTimeout and retry settings for the embedded run
enable_otel_traceboolEmit OpenTelemetry spans

Output

The embedded workflow's own output, unchanged.

Example

From moco-examples/trade-simulator/src/single-security-monitor.yaml:

- activity:
name: run-signal-analysis
type: builtin.execute_workflow
input_data:
wfspec:
name: multi-timeframe-trading-signal
input_data:
symbol: "{{ symbol }}"
confluence_threshold: "{{ confluence_threshold }}"
hourly_prices: "{{ hist_candles }}"
output_name: last_result

Running an inline spec:

- activity:
name: run-generated-spec
type: builtin.execute_workflow
input_data:
wfspec:
content: "{{ generated_yaml }}"
input_data:
rows: "{{ dataset }}"
options:
catch_exception: true
output_name: result
What the embedded workflow can call

It sees the activities of the worker it runs on. On the base worker that is the core provider set; on the agent worker it additionally includes claude_agent.*. It cannot reach activities served by a different worker type.

Not retried

builtin.execute_workflow ships max_attempts: 1 — a retry would re-run every side effect inside the embedded workflow. It heartbeats every 20 seconds so Temporal detects a dead worker within a minute rather than waiting out the one-day timeout.