Attributes
setAttributes attaches plaintext string metadata to the current workflow run. These attributes appear in the Workflow CLI and web UI, and you can search and filter runs by them from either the CLI or the Analytics API.
You can also seed any attributes directly when starting a run:
Usage
Call setAttributes from a "use workflow" function or a "use step" function. Plain application code is not supported because there is no active workflow run to attach attributes to.
Values must be strings. Pass undefined to remove a key:
Attribute keys must be 1-256 characters, values must be strings up to 256 bytes, and each run can have up to 64 attributes. Keys that start with $ are reserved for framework and library code.
Each setAttributes call also writes one attr_set event, and that event's complete data (keys, values, and writer metadata) must fit in 8192 UTF-8 JSON bytes (8KiB). Split large updates across several calls; the calls still share the 64-attribute limit. A call that exceeds a limit rejects with FatalError before anything is written, so catch it when the metadata is best-effort.
Reserved keys
When start() is called from inside a running workflow or step, the new run is automatically tagged with two reserved attributes:
$parentRunId: the run that started it.$rootRunId: the root of the chain. It is inherited, so every run in a daisy chain or fan-out shares one root id.
Top-level runs (started outside any workflow or step) are not tagged.
Viewing attributes
The run details panel in the observability UI shows the run's current attributes as key-value rows. Reserved $-prefixed keys are marked with a badge and sorted after user keys:

Each setAttributes call appears on the trace timeline as a diamond marker at the moment the attributes were written:

Expanding an attr_set event (in the run sidebar or the Events tab) shows the changed keys, removed keys, and whether the write came from the workflow body or a step (with the attempt number):

Searching and filtering by attributes
From the CLI
workflow inspect attributes lists the keys recorded on this project's runs,
with how many runs carry each and when it was first and last seen:
Pass one or more --attribute key=value pairs to inspect runs to list the
runs carrying them. Repeatable up to 8 times:
Both require a backend with the analytics read path. --attribute is ignored
with a warning on backends without one, and inspect attributes reports that
it is unavailable.
From the Analytics API
The Analytics API can discover which attribute keys exist and filter run listings by them. The analytics namespace is optional on World, so feature-detect it before use; it is absent on local, Postgres, and other custom Worlds:
Matching is latest-write-wins: once the run above writes phase: "complete", it stops matching phase: "received".
Behavior
- Attributes require a World implementing spec version 4 or later.
- Writes from workflow and step bodies append native
attr_setevents and immediately materializerun.attributes. - Storage errors surface rather than being silently ignored: transient errors on workflow-body writes are retried, and a write the World rejects as invalid (for example, exceeding the per-run attribute cap across multiple calls) fails the run with the validation error.
- Step-body storage errors throw from
setAttributeslike any other step-side network write. Catch the error inside the step if the attribute is best-effort. - Reading and querying: each run's current attributes are returned on the run objects from the Storage and Analytics APIs, and the Analytics API supports discovering attribute keys and filtering run listings by key=value pairs (see Searching and filtering by attributes). On Worlds without the optional
analyticsnamespace, attributes are readable on run objects but not searchable.