Code — Run custom Python logic against one explicit input value

Run arbitrary Python logic inside a workflow node. The Code node gives you a full Python function body with access to the upstream input value and workflow context.

When to Use

Use Code when:

  • You need logic that cannot be expressed with Transform, If, or Switch (loops, calculations, string manipulation, data processing)
  • You want to use a Python standard library module that is not available as a built-in plugin
  • You need to transform arrays, perform arithmetic, or build complex conditional logic
  • You want full control over the output object shape

Inputs

HandleTypeDescription
inputanyThe upstream value passed into your function as the input variable. Optional — if nothing is connected, input is None.

Output

HandleTypeDescription
resultobjectThe dictionary returned by your Python code on the success path.

The result is accessed in downstream nodes as {{ code.* }}. Reference fields from the returned dict directly (e.g., {{ code.message }}, {{ code.url }}).

Settings

SettingTypeDefaultDescription
languageenumpythonExecution language. Currently only python is supported.
codecode editor (Python)See belowPython function body. Must return a dictionary. The input and ctx variables are pre-injected.

Default code:

# input is available as the upstream value
# ctx.workflow_id and ctx.run_id are available
return {"result": input}

Available variables

Your code runs inside an async Python function. The following variables are available:

VariableTypeDescription
inputanyThe value connected to the input handle
ctx.workflow_idstringThe current workflow's ID
ctx.run_idstringThe current execution run's ID

Return a dictionary with the fields you want downstream nodes to access:

return {
  "result": input["amount"] * 1.1,
  "formatted": f"${input['amount'] / 100:.2f}"
}

Environment variables and imports

Access environment variables with the standard library:

import os
api_key = os.environ.get("MY_API_KEY", "")

Only Python standard library imports are allowed in managed execution. Packages listed in the workflow's Python dependencies are installed automatically at runtime — add them through workflow settings, not inside the code node.

Example

Canvas

Extract the most recent commit from a GitHub push event and format a Slack message:

Webhook → Code → Slack Send Message

Code settings:

commits = input.get("commits", [])
if not commits:
    return {"message": "No commits in this push."}

latest = commits[0]
return {
    "message": f"New commit by {latest['author']['name']}: {latest['message'][:80]}",
    "url": latest["url"],
    "author": latest["author"]["name"]
}

Downstream nodes reference {{ code.message }}, {{ code.url }}, and {{ code.author }}.

TSL

import webhook from @tensorify/webhook-trigger:4.0.0
import code_node from @tensorify/code:3.0.0
import http_request from @tensorify/http-request:3.0.0

node trigger @tensorify/webhook-trigger:4.0.0 {
    path = "/github/push"
    method = "POST"
    provider = "github"
}

node format @tensorify/code:3.0.0 {
    language = "python"
    code = "commits = input.get(\"commits\", [])\nif not commits:\n    return {\"message\": \"No commits.\"}\nlatest = commits[0]\nreturn {\"message\": latest[\"message\"], \"author\": latest[\"author\"][\"name\"]}"
}

node notify @tensorify/http-request:3.0.0 {
    method = "POST"
    url = "https://hooks.slack.com/services/{{ env.SLACK_WEBHOOK_PATH }}"
}

trigger.payload -> format.input
format.result -> notify.body

Error Handling

Code has a hidden On Error control output branch. Enable it via the "Error output handle" toggle at the bottom of the settings panel, or connect an edge to error in TSL (which enables it automatically).

The error branch fires when:

  • The code setting is empty or missing
  • An unhandled exception occurs during execution
  • The return value is not a dictionary (e.g., returning a string, list, or None)
  • An unsupported language is configured

When the error branch executes, downstream nodes can access the error details via {{ <nodeId>__error }}:

FieldTypeDescription
errorstringHuman-readable error message (e.g., Code execution failed: ...)
nodeIdstringThe ID of the node that failed

If the error branch is not connected, any of the above failures halt execution on that path.

Use try/except inside your code for expected failures you want to handle inline, and reserve the error branch for unexpected runtime failures.

TSL with error branch

import code_node from @tensorify/code:3.0.0
import stop from @tensorify/stop:3.0.0

node process @tensorify/code:3.0.0 {
    code = "return {\"total\": sum(input[\"values\"])}"
}

node halt @tensorify/stop:3.0.0

process.error -> halt.input

Common Gotchas

  • Return type: Your code must return a dictionary. Returning None, a string, a list, or forgetting the return statement triggers the error branch.
  • Async context: The function context is async. You can use await for async operations; standard synchronous code works without it.
  • Input is optional: If nothing is connected to the input handle, input is None. Guard against this with input or {} or an explicit check.
  • Standard library only: Third-party imports (e.g., requests, pandas) are rejected unless listed in the workflow's Python dependencies. Use built-in plugins like HTTP Request for common integrations.
  • No eval/exec: Dynamic code execution builtins are blocked for security.

See Also

On this page