Code Action
ImplementedThe code action is the escape hatch. When JigSpec's built-in actions can't do what you need — parsing a custom format, calling an API with unusual auth, doing math that a language model would get wrong — you drop into arbitrary code.
Most pipelines never need it. But when you do, it's there.
The basics
- name: parse_csv
action: code
input:
raw: "{{ fetch.body }}"
run: |
const rows = input.raw.split('\n').map(row => row.split(','))
const headers = rows[0]
const data = rows.slice(1).map(row =>
Object.fromEntries(headers.map((h, i) => [h, row[i]]))
)
return { rows: data }
outputs:
- rowsAfter this step, parse_csv.rows contains the parsed data.
Fields
| Field | Required | Description |
|---|---|---|
run | yes | The code to execute (JavaScript) |
input | no | Named inputs available as input.field in your code |
outputs | yes | List of output names your code returns |
runtime | no | Execution environment (default: node) |
The run field
Write JavaScript. Your code runs in a sandboxed Node.js context. You have access to:
input— the step's input mapsecrets— pipeline secretsenv— environment variables
Return an object with the keys listed in outputs:
- name: calculate
action: code
input:
items: "{{ extract.data.line_items }}"
run: |
const total = input.items.reduce((sum, item) => sum + item.price * item.quantity, 0)
const tax = total * 0.08
return { total, tax, grand_total: total + tax }
outputs:
- total
- tax
- grand_totalThe outputs field
You must declare the output names your code returns. This lets JigSpec validate that your code produced what it promised and makes the data flow explicit:
outputs:
- body
- status
- headersAfter the step, use step_name.body, step_name.status, etc.
The runtime field
Currently only node is supported. Future versions may add Python and other runtimes.
- name: process
action: code
runtime: node # default, can be omitted
run: |
// ...Code runs in a Node.js subprocess, so each step gets process isolation — a crash in your run block cannot take the rest of the pipeline down. The subprocess is spawned with the step's workspace directory as the working directory, so relative file paths in your code resolve next to the step's outputs.
When to use code
Reach for code when you need:
- Arithmetic (language models are unreliable for math)
- Parsing custom formats (CSV, binary, proprietary APIs)
- Calling APIs with complex auth that can't be templated
- Any logic that must be deterministic and testable
For everything else, use ai.