# Code Node

The Code Node lets you write and run custom **Python** or **TypeScript** code directly inside a Stack AI workflow, with the help from an AI code assistant.&#x20;

### Differences between Code Node and Python Node

{% columns %}
{% column %}
**Code Node**

* Supports Python and Typescript
* Allows importing custom libraries
* Allows custom expressions
* Reads input data from all upstream nodes
  {% endcolumn %}

{% column %}
**Python Node**

* Supports Python
* Restricted to [pre-imported libraries](/workflow-builder/utils-logic-and-others/logic/python-code.md#pre-imported-python-libraries)
* Does not allow [unsafe expressions](/workflow-builder/utils-logic-and-others/logic/python-code.md#unsafe-expressions)
* Reads data from the most immediate proceeding nodes
  {% endcolumn %}
  {% endcolumns %}

### How the Code Node Works

The Code Node offers a fullscreen editor with an AI code assistant.

<figure><img src="/files/T0PaOCCGGlBiV9RWGHC2" alt=""><figcaption></figcaption></figure>

#### Set Dependencies

<figure><img src="/files/hUqshtKl03zSBsJnSFv6" alt=""><figcaption></figcaption></figure>

The Dependencies field is a list of package names that get installed into the sandbox before your code runs.

Dependencies are optional. When no dependencies are declared, the sandbox will run your code directly, which is a faster startup.

#### Reference Input Variables

<figure><img src="/files/bup1o4FfVFtjWyR51lpM" alt=""><figcaption><p>Select a specific field within a variable</p></figcaption></figure>

The left panel lists all upstream variables connected to the Code Node.&#x20;

You can select a variable by hovering over the field and click "+Insert". The value selected will automatically populate in the code editor. The advanced expression gives the flexibility to select specific fields within a nested JSON, such as the "value" field in the example above.

#### Write Code

You can ask the code assistant to help you update the code. Changes proposed by the assistant are highlighted.

<figure><img src="/files/q7joSj4g37Gfwnw69N8r" alt=""><figcaption></figcaption></figure>

The code must include a `main(args)` function, which is pre-populated in the template. This function is where the logic lives. The output returned by  `main()` becomes the output of the node, available to all downstream nodes.&#x20;

{% hint style="info" %}
The output of the Code Node must be returned in **JSON** forma&#x74;**.**&#x20;
{% endhint %}

You can format the output in two ways:

* Returning a Python dictionary that represents a JSON object

```python
Return {"Result":result_variable}
```

* Explicitly serializing the result using `json.dumps()`

```python
Return json.dumps(result_variable)
```

#### Test Code

Testing code is easy. You can run the code directly from the editor.&#x20;

<figure><img src="/files/D6RPQhgD53W2rjazTUVw" alt=""><figcaption></figcaption></figure>

The test run will use the most recent values. This means that you need to run the upstream nodes at least once in the Builder view for the code editor to have access to test values.

#### Error Handling

If something goes wrong, the Code Node will surface an error message. Common errors include:

* Dependency install failed: a declared package couldn't be installed. Check the package name/version.
* Sandbox timed out: the environment took too long to start. Try again.
* Code execution failed: an unhandled exception in your code. Check the Error output for details.

If you've connected a failure branch to the node, errors will automatically route there instead of stopping the workflow.

### How to Generate a File with the Code Node

The Code Node can produce files as outputs. Anything you write to the sandbox's `/home/user` directory during execution is automatically captured, uploaded, and exposed as a pre-signed download URL in the node's output. This is the recommended way to generate CSVs, PDFs, and any other files via the code node.

#### How it works <a href="#id-76ce3b4e-5c5c-429f-85d7-6f85cd92f973" id="id-76ce3b4e-5c5c-429f-85d7-6f85cd92f973"></a>

Every Code Node run executes inside an isolated sandbox with `/home/user` as the working directory. When `main()` returns, Stack AI:

1. Scans `/home/user` for any files you created or modified during the run.
2. Uploads each file to secure object storage.
3. Issues a short-lived, pre-signed `download_url` for each file.
4. Appends them to the node's output under `files.elements[]`.

You don't need to return the file from `main()` — saving it to disk is enough. The return value is still passed through as `result`, so you can return structured metadata alongside the file (row counts, summaries, the file name, etc.).

#### Minimal example <a href="#id-48c86391-e784-430e-995f-ea8451ae3413" id="id-48c86391-e784-430e-995f-ea8451ae3413"></a>

```
def main(args):
    file_path = "/home/user/sample_download_test.txt"

    with open(file_path, "w") as f:
        f.write("Hello! This is a sample file for testing download_url.")

    return {} # Note: no need to return anything
```

After the node runs, its output looks like this:

```
{
  "result": {},
  "exit_code": 0,
  "logs": "",
  "error": "",
  "files": {
    "elements": [
      {
        "id": "db6d004a-e43e-448b-b755-ac2328...",
        "name": "sample_download_test.txt",
        "download_url": "https://sb.stack-ai.com/storag..."
      }
    ]
  }
}
```

#### Using the file downstream <a href="#d2f834e7-bc12-46ec-b524-ca234e463c3d" id="d2f834e7-bc12-46ec-b524-ca234e463c3d"></a>

Reference the URL or file metadata from any downstream node using an "advanced expression", e.g. `{ code-0.files.elements[0].download_url }`. Common patterns:

* **Email**: paste the `download_url` directly into a attachments field of an Outlook / Gmail Send Email node.
* **Output node**: surface the URL to the end user as part of the workflow's response in the chat / form UIs.
* **Loop / merge nodes**: when generating multiple files, each element in `files.elements[]` gets its own `download_url`, and you can iterate over them just like any other array.

#### Generating multiple files <a href="#be2999e0-3425-4845-8811-c44bb1744951" id="be2999e0-3425-4845-8811-c44bb1744951"></a>

You can drop multiple files into `/home/user`. They all show up as separate entries in `files.elements[]`, in the order they were written:

```
import csv

def main(args):
    for region in ["us", "eu", "apac"]:
        with open(f"/home/user/sales_{region}.csv", "w", newline="") as f:
            writer = csv.writer(f)
            writer.writerow(["product", "units"])
            writer.writerow(["widget", 42])

    return {"generated": 3}
```

#### Binary files <a href="#ceb5dd46-e4ae-4a2b-82f5-8fba63c7945d" id="ceb5dd46-e4ae-4a2b-82f5-8fba63c7945d"></a>

Write binary files the same way — open in binary mode and the upload step will preserve content type:

```
from PIL import Image

def main(args):
    img = Image.new("RGB", (256, 256), color=(73, 109, 137))
    img.save("/home/user/swatch.png")
    return {}
```

PDFs, Excel files, ZIPs, audio, and any other binary format work identically.

#### Notes <a href="#id-0a805cda-2b80-4226-b4d9-68e1b7efbb47" id="id-0a805cda-2b80-4226-b4d9-68e1b7efbb47"></a>

* **Only** `/home/user` **is scanned.** Files written to `/tmp`, `/var`, or any other path are discarded when the sandbox terminates. Always write to `/home/user/...`.
* **Pre-signed URLs are short-lived.** They're suitable for immediate downstream consumption or sharing with end users in the moment, but they're not permanent storage links — re-run the node to regenerate them, or persist the file to your own storage (S3, Google Drive, etc.) via a downstream node if you need long-term access.
* **TypeScript works the same way.** Use `fs.writeFileSync("/home/user/output.csv", ...)` (or any other Node.js file API) and the same auto-capture behavior applies.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.stackai.com/workflow-builder/utils-logic-and-others/logic/code-node.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
