Skip to main content
Import top-level functions and public types from automate.ax. Most operators also have a fluent form on Signal, KeyedSignal, or GlobalSignal. Signals compose synchronously during planning and materialize during durable execution. Transformer, predicate, key, and section callbacks must be synchronous. Put external work in actions.

Choose an operator family

merge and race answer different questions. merge forms one stream from independent roots and emits every occurrence. race selects one alternative within a shared activation boundary. Dependency and structure operators—dependentOn, withPrerequisites, scope, and group—compose with every family.

Property access

Reading a non-function property returns another signal. Chained access works across objects, arrays, and primitives:
The derived signal closes or fails with its source. Accessing a property after the source resolves to null or undefined fails with TypeError. Signal methods reserve their names, and function-valued payload properties aren’t projected as callable values. Use transform to call a value method such as names.join(", ").

transform

Creates a derived signal from one or more inputs.
The transformer runs after every input emits and must be pure. An input failure fails the result; an input closure closes it. A thrown transformer error fails with code expression_failed and doesn’t consume an action retry. Arbitrary transforms don’t preserve keyBy or globally annotations.

t

Builds a Signal<string> from a tagged template containing at least one signal:
Static interpolations add no dependency. Automate.ax converts interpolated values to text after every signal emits. Calling t without a signal interpolation throws TypeError during planning. Use transform for conditional logic, value methods, or non-string output.

isSignal

Narrows an unknown value to Signal:
It returns true only for objects implementing the Automate.ax signal protocol. Action inputs already accept compatible signals; use this guard in helpers that accept both in-memory values and signals.

keyBy

Returns an immutable KeyedSignal<T> whose cross-context operations use the encoded key as their partition:
The key function must be pure and return an encoded Automate.ax value. Calling keyBy replaces an existing keyed or global annotation.

globally

Returns a GlobalSignal<T> whose cross-context operations share one partition:
Calling globally replaces an existing keyed or global annotation. Use keyBy when one entity’s occurrences must not reset another entity’s timer or enter the same batch.

timestamp

Returns the stable platform time at which an occurrence emitted:
Both forms return Signal<Date>. Trigger timestamps use ingestion time, action timestamps use completion time, and coordinated signals use their persisted decision time. A pure derivation uses the most recent contributing durable boundary. Use a provider timestamp when its domain time is the required value.

correlationId

Returns a stable keyed Signal<string> derived from an occurrence’s durable boundary:
perDeclaration defaults to true, so separate declarations anchored to one occurrence receive independent IDs. Pass false to derive the ID only from the durable dependency boundary. Prefer a provider’s domain ID when it already identifies the entity or conversation.

correlate

Matches one occurrence from every keyed stream by exact encoded key:
Each input defaults to { selection: "oldest", consumption: "consume" }. Set selection: "latest" to discard older eligible occurrences for that input. Set consumption: "retain" to reuse the selected occurrence in later matches: oldest retention behaves like a latch, while latest retention behaves like an updating register. Retained occurrences remain operational state until superseded, expired by occurrenceTtl, or the automation is removed. The child context contains every selected parent history, so downstream work can consume the original keyed signals. The returned Signal<null> exposes the match boundary. Reusing one durable signal origin in several positions throws TypeError; collect distinct occurrences first when one stream must fill several roles.

merge

Combines independent occurrence streams without matching or consuming them together:
Every successful input occurrence emits once in its own child context. Inputs don’t wait for or consume one another, and arrival order doesn’t suppress any occurrence. The result is the union of the input value types. Use correlate when related streams must meet by key, or race when alternatives within one causal occurrence compete to finish first.

collect

Consumes a fixed number of keyed or global occurrences in arrival order:
count accepts a positive integer or Signal<number>. Invalid literal counts throw during planning. Signal-derived counts match only occurrences whose resolved counts are equal. The result is a partition-preserving NonEmptyArray<T>.

once and take

Admit a bounded number of occurrences from each keyed or global partition:
once(signal, options?) is take(signal, 1, options?). Without ttl, the count remains claimed permanently. With ttl, the claim starts when the first occurrence is admitted and the complete count resets when it expires. The result preserves the source partition.

rateLimit

Admit at most a fixed number of occurrences in each rolling interval:
overflow defaults to "wait", which queues excess occurrences FIFO until rolling capacity returns. "drop" closes excess occurrences without emitting. Every key has independent capacity; globally() creates one shared limit.

each

Creates one durable child context per array item:
Returning a signal produces Signal<TResult[]> in source-array order. A failed item fails the gathered result, a closed item closes it, and an empty source gathers to []. Returning nothing produces void and doesn’t join the item contexts.

gate

Preserves a value only when a separate boolean signal emits true:
false or a closed condition closes the result without materializing the value. A failed condition fails it. The result preserves a keyed or global annotation carried by the value.

filter

Preserves a value only when a synchronous predicate returns true:
The boolean-predicate overload preserves the input type. The type-guard overload narrows it. A value that fails the predicate closes the result; a thrown predicate fails with code expression_failed. The result preserves a keyed or global source annotation.

partition

Splits one signal into complementary matching and remaining paths:
Exactly one output emits the original value; the other closes. A type-guard predicate narrows the matching output and excludes that type from the other output. Both outputs preserve a keyed or global source annotation.

dependentOn

Preserves one signal value while adding prerequisites to its downstream dependency chain:
The result closes or fails when a prerequisite does. It preserves a keyed or global annotation carried by the primary signal. The operator doesn’t delay the declaration that produced the primary signal; it changes only the returned signal’s dependencies.

withPrerequisites

Applies one signal or a nonempty tuple to every durable declaration in a synchronous section:
Nested sections combine their prerequisites. A directly returned signal also inherits them; other return values pass through unchanged. Don’t declare triggers inside withPrerequisites or branch. A trigger starts an independent root context.

branch

Declares complementary synchronous sections selected by boolean signals:
Later conditions materialize only after every earlier condition is false. When every selected section returns a signal, branch returns the selected result. With only a true section, its result closes when the condition is false. Sections must be synchronous and can’t declare triggers.

race

Selects the first causally related signal to emit or fail:
Inputs must descend from the same activation-boundary occurrence. Failure wins like emission. Closed inputs leave the race, which closes only when every input closes. The selected result creates the closest child boundary for downstream actions. Independent roots can’t race; use merge when either of several triggers should start the same flow.

serialize

Runs one structured work region at a time in each keyed or global partition:
The source signal has three roles: each emission enters the queue, its key selects the queue, and its value and provenance remain available inside the section. Use globally() for one queue across all occurrences. The section creates an isolated structured-concurrency region. Independent declarations inside it can run concurrently; declaration order doesn’t serialize them. The next occurrence in the same partition starts only after every context and unmatched coordination offer created by the current region becomes terminal. Other partitions continue independently. The callback doesn’t return a completion signal. If it returns a signal, that value remains unavailable downstream until the whole region closes. Returning nothing is valid when only the enclosed effects matter. Sections must be synchronous and can’t declare triggers.

concurrent

Runs up to a fixed number of structured work regions in each partition:
concurrent has the same section and completion semantics as serialize, but admits up to limit active regions per key. Additional occurrences wait FIFO. serialize(stream, section) is the capacity-one form.

delay

Resumes a value or synchronous section after a durable relative delay:
Duration accepts nonnegative milliseconds, a compact duration string, or a compatible signal. A value-carrying delay preserves the source’s keyed or global annotation. The timer-only form declares a hidden delivery trigger; scope it to its initiating occurrence with withPrerequisites when the automation has another possible root.

timeout

Mirrors a signal unless a durable relative deadline wins:
The deadline accepts Duration. If it wins, the result fails with name: "TimeoutError" and message "Signal timed out.". Source closure leaves the deadline active. A timeout can span execution jobs but doesn’t interrupt an action handler already running. The result preserves the source’s keyed or global annotation.

funnel

Applies one timing and output policy to each keyed or global partition:
Durations accept Duration. An end emission requires minQuietPeriod, maxBurstDuration, or until. Start-only mode emits immediately and ignores the rest of the burst, so it doesn’t accept select or buffer. The result preserves the source partition; locally closed paths contribute no occurrence. Minimum-gap memory belongs to the durable partition and remains effective after older execution values leave retention.

debounce

Emits the latest keyed or global occurrence after its partition remains quiet:
duration accepts Duration. Each occurrence resets only its partition’s timer. This is the selecting funnel preset { minQuietPeriod: duration }, and the result preserves the source partition.

window

Buffers keyed or global occurrences until a relative or absolute deadline:
The relative form accepts Duration. The first occurrence opens the window. The partition-preserving result is a NonEmptyArray<T> in arrival order.

outcome

Converts every terminal state into a tagged value and always succeeds after the source terminates:
The result is Signal<SignalOutcome<T>>. Unlike value-preserving operators, outcome doesn’t retain a keyed or global annotation.

succeeded

Emits whether a signal terminated successfully with a value:
The result is true for success and false for failure or closure. The predicate itself succeeds after any terminal state.

failed

Emits whether a signal terminated with an automation error:
The result is true for failure and false for success or closure. The predicate itself succeeds after any terminal state.

closed

Emits whether a signal closed without a value:
The result is true for closure and false for success or failure. Failure isn’t closure. The predicate itself succeeds after any terminal state.

onSuccess

Selects a signal’s successful value and closes for failure or closure:
The section overload applies the selected value as a prerequisite and returns the section result. The value form preserves a keyed or global source annotation.

onFailure

Selects a signal’s normalized AutomationError and closes for success or closure:
The section overload applies the failure as a prerequisite and returns the section result. AutomationError contains author-safe details, not raw errors or stacks.

onClose

Selects closure as Signal<null> and closes for success or failure:
The section overload applies the closure as a prerequisite and returns the section result.

markSignificant

Marks the connected run significant only when the selected signal emits, then returns the original signal:
Recent runs hides runs without an emitted marked signal by default. Show insignificant runs reveals them as dimmed rows. Closure or failure doesn’t mark the run significant.

scope

Gives a synchronous section its own durable hook namespace:
Adding or removing declarations inside the scope doesn’t renumber hooks after it. scope adds no prerequisite or presentation metadata. branch, each, and delay create internal scopes for the same isolation.

group

Names a synchronous declaration group and gives it an isolated hook namespace:
Like scope, group doesn’t add a prerequisite. It returns the section result.

Types and errors

| Type | Contract | | --- | --- | --- | | Signal<T> | Symbolic value that materializes during execution. | | KeyedSignal<T> | Signal<T> with an encoded partition key from keyBy. | | GlobalSignal<T> | Signal<T> with one shared cross-context partition from globally. | | NonEmptyArray<T> | [T, ...T[]]. Complete collections and windows return this type. | | Duration | Milliseconds, a compact DurationString, or a compatible signal carrying either. | | Deadline | Date | Signal<Date>. | | CorrelationOptions | Options accepted by correlate. | | CorrelationInput | A keyed signal or { signal, selection?, consumption? }. | | AdmissionOptions | Optional claim ttl accepted by once and take. | | RateLimitOptions | Rolling limit, interval, and overflow behavior. | | ConcurrencyOptions | Positive active-region limit accepted by concurrent. | | ValueInheritanceOptions | Parent-value selection accepted by collect and window. | | WindowUntilOptions | ValueInheritanceOptions & { until: Deadline }. | | GroupOptions | Options accepted by group. | | FunnelOptions | Type-checked timing, edge, selection, and buffering combinations accepted by funnel. | SignalOutcome<T> is mutually exclusive:
AutomationError contains author-safe failure data:
code is the stable machine-readable classification. message, optional name, JSON details, and a depth-limited cause are safe to expose to automation authors. Raw errors and stacks don’t enter signal values.