1. Goal

  • Build n8n-nodes-zyra, a custom n8n node package that:

    • Wraps Zyra FastAPI calls.

    • Exposes one node type per CLI module: Acquire, Process, Visualize, Decimate.

    • Dynamically loads available commands for each module from the API.

    • Returns execution logs and exit codes to the workflow.

    • Enables conditional branching and error handling in n8n.


2. Node Package Structure

n8n-nodes-zyra/
    package.json
    credentials/
        zyraApi.credentials.ts
    nodes/
        Acquire.node.ts
        Process.node.ts
        Visualize.node.ts
        Decimate.node.ts
    README.md

3. Credentials

zyraApi.credentials.ts

  • Stores:

    • Base URL of the FastAPI service.

    • API key (if authentication enabled).

  • Used in all node types.


4. Node Types

4.1 Acquire Node

  • Dropdown: command list from /cli/commands?stage=acquire.

  • Dynamic parameter fields based on selected command.

  • Sends POST to /cli/run with stage="acquire".

4.2 Process Node

  • Dropdown: /cli/commands?stage=process.

  • Conditional parameter UI.

  • Sends POST with stage="process".

4.3 Visualize Node

  • Dropdown: /cli/commands?stage=visualize.

  • Visualization-specific args shown dynamically.

  • Sends POST with stage="visualize".

4.4 Decimate Node

  • Dropdown: /cli/commands?stage=decimate.

  • Destination-specific args shown dynamically.

  • Sends POST with stage="decimate".


5. Execution Logic with Logs & Exit Code

Each node:

  • Calls /cli/run (sync or async mode).

  • Receives:

{
  "status": "success",
  "stdout": "...",
  "stderr": "...",
  "exit_code": 0
}
  • Returns this to n8n output as:

{
  "stage": "process",
  "command": "decode-grib2",
  "args": {...},
  "exit_code": 0,
  "stdout": "...",
  "stderr": "...",
  "timestamp": "2025-08-12T15:32:10Z"
}

Example execute() snippet:

const creds = await this.getCredentials('zyraApi');
const response = await this.helpers.httpRequest({
    method: 'POST',
    url: `${creds.baseUrl}/cli/run`,
    headers: { Authorization: `Bearer ${creds.apiKey}` },
    body: {
        stage: 'process',
        command: this.getNodeParameter('command', 0),
        args: this.getNodeParameter('args', 0, {}),
        mode: 'sync'
    },
    json: true
});

return [this.helpers.returnJsonArray({
    stage: 'process',
    command: this.getNodeParameter('command', 0),
    args: this.getNodeParameter('args', 0, {}),
    exit_code: response.exit_code,
    stdout: response.stdout,
    stderr: response.stderr,
    timestamp: new Date().toISOString()
})];

6. Dynamic Command Loading

  • API endpoint /cli/commands:

{
  "acquire": ["http", "s3", "ftp", "vimeo"],
  "process": ["decode-grib2", "convert-format", "extract-variable"],
  "visualize": ["plot", "colormap"],
  "decimate": ["local", "s3", "ftp"]
}
  • n8n node fetches commands for its stage when rendering parameter dropdown.


7. Debugging in n8n

  • Branch on Success/Failure:

    • Use If node to check exit_code.

  • View Logs:

    • stdout and stderr appear in n8n execution data.

  • Error Notifications:

    • Connect failure branch to Slack, Email, etc.


8. Bonus Features

  • Async Job Mode:

    • Node triggers /cli/run with mode="async".

    • Poll /jobs/{job_id} until complete.

  • Upload Node:

    • Wrap /upload endpoint for local file ingestion.

  • Pipeline Runner Node:

    • Send entire pipeline YAML to /run.


9. Advantages of One Node Per Module

  • Minimal number of nodes (4 core types).

  • Easy to maintain β€” adding a CLI command only updates API output.

  • Dynamic parameters keep UI relevant and avoid clutter.

  • Clear mapping to Zyra CLI structure.


10. Future Extension

  • Auto-generate β€œshortcut” nodes for high-use functions.

  • Allow saving n8n workflows as Zyra pipeline configs.

Visualization Node

Purpose: Render visual outputs from processed or raw data using the Zyra visualization module.

CLI Stage: visualize

Supported Commands: Dynamically fetched from /cli/commands?stage=visualize, e.g.:

  • heatmap

  • contour

  • timeseries

  • wind-particles (future)

  • animate (future)

Parameters:

  • Input file (input)

  • Output path (output)

  • Visualization type-specific parameters (--var, --levels, --cmap, --map-type, etc.)

Example API Payload:

{
    "stage": "visualize",
    "command": "heatmap",
    "params": {
        "input": "processed.nc",
        "var": "temperature",
        "output": "heatmap.png",
        "cmap": "viridis"
    }
}

Output:

  • Image or animation file path.

  • Logs and exit code captured for debugging.