> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tela.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Code Execution

> Transform data between steps with a small execute(input) function, with libraries and credentials

**Code Execution** runs a piece of JavaScript (or TypeScript) on the data of the run. It is the step for everything a model should not be asked to do: arithmetic, formatting, merging the results of a Map, calling an external system, deciding something deterministic.

You do not need to be a developer to use it for simple things, and the editor has an **AI Code Assistant** (`⌘ L` on macOS, `Ctrl L` elsewhere) that writes or changes the code from a description. This page explains what the code receives and what it must return, so you can read and check what the assistant produces.

In the running example, **Normalize Values** sits after Extract Data and turns the extracted number into a formatted amount, builds an approval code and flags contracts above the threshold.

![Code Execution step with the code editor, the Available Libraries bar and the Terminal](https://mintcdn.com/meistrari/M2w7BduKZAFA1Sbx/images/workflow/code-execution.png?fit=max\&auto=format\&n=M2w7BduKZAFA1Sbx\&q=85\&s=5a9c11b48c0a025e670dcc31480678c2)

## The execute function

The code must declare a function named `execute` that receives `input` and returns the step's output. The step is created with this template:

```typescript theme={null}
/**
 * Required main execution function that processes the workflow state data.
 */
async function execute(input: TelaInput) {
    return 'Tela'
}
```

Whatever `execute` returns becomes the output of the step: a text, a number, an object or a list. Return an **object with named fields** when later steps need to pick values from it; those fields show up in the `@` menu of the next steps.

```javascript theme={null}
// Normalize the values extracted by Extract Data for the routing and the letter.
async function execute(input) {
  const data = input["Extract Data"]
  const total = Number(data.total_value) || 0

  return {
    total_value: total,
    total_formatted: total.toLocaleString("en-US", { style: "currency", currency: "USD" }),
    is_high_value: total > 100000,
    approval_code: `CT-${new Date().getFullYear()}-${String(data.counterparty).slice(0, 3).toUpperCase()}`,
  }
}
```

Start the code with a short comment that says what the step does, which inputs it uses and what it returns. Whoever opens the Workflow later, including the AI assistant, reads it before the code.

A function that is missing or not named `execute` fails the step with the message: *The `execute(input)` function was not found in the code and is required.*

## What `input` contains

`input` is an object with one key per Input of the Workflow and one key per step that ran before this one, **using their names exactly as written in the editor**:

| Key | Value |
| - | - |
| `input["contract"]` (a file Input) | an object with `files`, a list of the uploaded files: `{ name, mimeType, fileUrl, vaultReference }` |
| `input["requester"]` (a text Input) | the text |
| `input["Extract Data"]` (an AI Module with Output Format) | the object with its attributes: `input["Extract Data"].total_value` |
| `input["Draft Note"]` (an AI Module without Output Format) | the text |
| `input["Route by value"]` (a Condition) | the name of the case that matched, or `"Default"` |
| `input["Split contract"]` (a Split or Crop) | the list of pieces, each with `file`, `originalFile`, `pages`... |
| `input["Extract Page"]` (a step inside a Map that already finished) | a list, one entry per iteration |
| `input["page"]` (inside a Map, the Map Variable) | the current item |

Names with spaces need the bracket form, `input["Extract Data"]`; names without spaces can use `input.requester`. The editor knows the shape of what each previous step returns and offers completion while you type, so `input["Extract Data"].` lists the attributes of its Output Format.

> [!TIP]
>
> Add a `console.log(JSON.stringify(input, null, 2))` on the first run. The **Terminal** below the editor shows everything the code writes to stdout and stderr, with the exit code, so you can see the real shape of the data before writing the logic.

## Returning values

* Return an **object** to expose named fields: `{ total_value, is_high_value }`. Each field is selectable by later steps and by a Condition.
* Return a **list** to feed a Map.
* Return a **text** or **number** for a single value.
* Returning nothing (`undefined`) produces an empty output; the step still succeeds.
* Throw an error (`throw new Error("Missing total")`) to fail the step on purpose. The run fails at that step and the message appears in the result pane and in Debug.

A Code Execution step has no Output Format to fill in: the fields of the object you return are its output format. The editor infers them from the code so the next steps can offer them in the `@` menu.

## Working with files

File values arrive as metadata, not as bytes. To read a file's content, use the libraries available in the step:

* `@meistrari/document-sdk` to parse documents;
* `@meistrari/vault-sdk` to read and write files in the Vault;
* `@meistrari/tela-sdk-js` to call the Tela API (for example run a Canvas) from the code.

These three are installed by default and listed under **Available Libraries**. To add another package (for example `xlsx` to read a spreadsheet or `pdf-lib` to assemble a PDF), type its name in **Add a library** and click **Install**. Installation takes a few seconds and the package is then available with `import` or `require`.

> [!NOTE]
>
> How to produce a file as the output of a Code Execution step (for example upload a generated spreadsheet to the Vault and return its reference) depends on the Vault SDK and is not documented here. For generating documents from a template, use the [Document Templater](https://docs.tela.com/en/workflow/reusing-canvases-agents-and-templates.md#document-templater) instead.

## Using credentials

Never paste an API key in the code. Store it as a [Credential](https://docs.tela.com/en/credentials.md) and read it at run time:

```javascript theme={null}
async function execute(input) {
  const token = credential("CRM_API_TOKEN")
  const response = await fetch("https://crm.example.com/api/contracts", {
    method: "POST",
    headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json" },
    body: JSON.stringify({
      counterparty: input["Extract Data"].counterparty,
      total: input["Normalize Values"].total_value,
    }),
  })
  if (!response.ok) throw new Error(`CRM answered ${response.status}`)
  return await response.json()
}
```

`credential("NAME")` returns the value of a Workspace or Workflow-scoped credential. A missing credential fails the step with `missing_credential`. Values are redacted from logs, but anything you `console.log` explicitly may still show, so do not print them. Admins can restrict which credentials a Workflow may use from the **Credentials** button in the header; see [Credentials](https://docs.tela.com/en/credentials.md#credentials-allowlist).

## Limits

| Limit | Value |
| - | - |
| Language | JavaScript or TypeScript (TypeScript is transpiled before running) |
| Time | up to 80 minutes per execution by default |
| Memory | 128 MB |
| Network | outgoing HTTPS calls to public addresses are allowed; private, local and link-local addresses are blocked |
| Processes | the code cannot start other programs |
| Result | whatever `execute` returns, serialized as JSON |

A Code Execution step is never cached: it runs on every execution of the Workflow. A run that makes no progress for 3 hours is marked as timed out, so keep long waits out of the code; a wait of hours belongs to a schedule, not to a step.

## Debugging

After a run, the step's section in the result pane shows the returned value, and **Debug** adds the **Terminal** (stdout, stderr and exit code) and the error message when the code threw. When a Code Execution step fails, fix the code and use **Run Step N** on it to re-run from the start up to that step without touching the steps after it. See [Running, testing and publishing](https://docs.tela.com/en/workflow/running-testing-and-publishing.md#running-a-single-step).

> [!NOTE]
>
> For developers: the step accepts `code`, `language` (`javascript` default; `typescript` is accepted) and `libraries` (npm package specifiers). The sandbox exposes the run state as globals, so `input` is built from the Inputs (text unwrapped to its content, files as `{ files: [...] }`) and the outputs of previous steps keyed by **step name**. `{{step://…}}` references are not expanded inside code.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.