Skip to main content
The Execute code block (Calculations) runs custom JavaScript inside a workflow and exposes the value it returns to later blocks. Reach for it when a Formula or Aggregate values block cannot express the change you need. Common cases are reshaping incoming data into the format a later block expects, building a score from several attributes, or cleaning up inconsistent source data. The block runs your code with a 100-second timeout. That makes it a good fit for short transformations, not long-running jobs.

Inputs

The block passes every variable you map into it as one inputs object. Whatever main returns becomes the block’s output. A minimal function reads its inputs and returns a plain object:

Outputs

Reference the returned value in a later block as {{ steps.execute_code.result }}. If main returns an object, address each field by its key, such as {{ steps.execute_code.result.score }}.

Behavior

The block runs the exported main function once per run and waits for it to finish before continuing. An async function is awaited, so you can await inside main. The work still has to finish within the 100-second timeout. Code that runs past the timeout fails the block instead of returning a partial result. The return value passes through exactly as written, including null, an empty object, or an empty array. Downstream blocks receive exactly what main returned, so a missing field reads as undefined rather than an error. The credit cost is variable and complexity-based, so heavier code costs more than a light transformation. Keep functions small and single-purpose.

Gotchas

  • The function must be named main. The block calls main(inputs) by name. An unnamed function, a differently named export, or a default export will not run. Export main exactly, and read your data through its inputs parameter rather than from any outer scope.
  • A thrown error fails the whole block. Any uncaught exception inside main stops the run at this block, so a single bad field can halt the workflow. Wrap risky parsing in a try/catch and return a marker value, such as { error: true }, that a later If block can branch on.
  • Non-deterministic code makes runs hard to trust. Non-deterministic means the same input can produce a different result. When the result drives a write, calls to Date.now(), Math.random(), or an external service can each return a different value on every run and every retry. Keep code that controls writes deterministic. Move randomness to the Random number block so the value is recorded in run history.
  • Long jobs hit the 100-second timeout. The block stops at 100 seconds and fails, so polling loops and large batch loops are the wrong fit. Split the work across a Loop block, or call an external service with Send HTTP request.

Examples

Normalizing a lead source field

This function maps inconsistent source labels onto one canonical value before the workflow writes the record. Canonical means the single agreed-on spelling you store, such as Paid search for every variant of that source.
With inputs.source set to LI Ads, the block returns { "source": "Social" }. An Update record block then writes that value to the lead’s source attribute as {{ steps.execute_code.result.source }}.

Scoring a record from several attributes

This function combines three mapped variables into one explainable score for a deal owned by Priya Sharma.
The block returns { "score": 70 }. A downstream If block reads it as {{ steps.execute_code.result.score }} to route deals scoring 50 or higher to a sales-ready stage.

Credit cost worked example

Execute code is priced as Variable (complexity-based), so there is no single fixed-per-run figure. A heavier function costs more than a light one. To estimate spend, sample a few real runs in run history. Then multiply the cost you observe by your monthly volume. Take a lead-normalization workflow that fires on 2,000 inbound leads a month. Measure the cost of one representative run and multiply by 2,000. Compare that total to your monthly allowance on Credits & pricing explained. Logic and lookup blocks elsewhere in the same workflow stay free. Only the Execute code step and any write blocks add to the total.

Source

Attio Workflows block library. Last reviewed against the Attio Help Center, June 2026.

See also