Skip to main content
JavaScript modules let you write inline processing logic that runs in the platform’s Go-based scripting runtime. Unlike Python modules which require a separate container, JavaScript modules execute directly in the kodexa/go-scripting-runtime — making them fast to deploy and ideal for:
  • Document metadata enrichment
  • Conditional routing and classification
  • Lightweight data transformations
  • Calling external APIs via service bridges
  • LLM-assisted processing

Module Definition

Create a module.yml with scriptLanguage: "javascript" and inline your script in the script field:
slug: my-js-module
version: 1.0.0
orgSlug: my-org
type: store
storeType: MODEL
name: My JavaScript Module
metadata:
  moduleRuntimeRef: kodexa/go-scripting-runtime
  type: module
  scriptLanguage: javascript
  script: |
    log("info", "Hello from JavaScript module");
    var greeting = parameters.greeting || "Hello";
    log("info", greeting + " world");
    return { result: "done" };
Key fields:
  • slug: Unique identifier within your organization
  • orgSlug: Your Kodexa organization slug
  • moduleRuntimeRef: Must be kodexa/go-scripting-runtime for JavaScript modules
  • scriptLanguage: Must be javascript (or js)
  • script: Your inline JavaScript code

Script Structure

Scripts run in a Goja JavaScript runtime (ES5+ compatible). The script is automatically wrapped in an IIFE (Immediately Invoked Function Expression), so you can use return at the top level to produce an output value:
// This is valid — the runtime wraps your code in (function() { ... })()
var result = doSomeWork();
return { status: "completed", output: result };
The return value is serialized as JSON and passed back to the platform as the step’s output event.

Available APIs

Parameters

A parameters global object is available containing:
  • Any module options configured for the execution (from inferenceOptions or step config)
  • The execution_id for the current execution
  • The pipeline_context with execution context metadata
var threshold = parameters.confidence_threshold || 0.8;
var execId = parameters.execution_id;
log("info", "Running execution " + execId + " with threshold " + threshold);

Logging

Two logging APIs are available:
// Structured log with level — levels: "debug", "info", "warn", "error"
log("info", "Processing started");
log("warn", "Threshold is very low: " + threshold);
log("error", "Something went wrong");

// Console-style logging (always logs at info level)
console.log("Debug output:", someValue);

Module Dependencies

JavaScript modules can load other JavaScript modules as dependencies using the moduleSidecars field in module.yml. Dependencies are fetched and executed in order before your main script runs, making their functions and variables available in global scope.
metadata:
  moduleRuntimeRef: kodexa/go-scripting-runtime
  type: module
  scriptLanguage: javascript
  moduleSidecars:
    - my-org/string-utils
    - my-org/validation-helpers
  script: |
    // Functions from string-utils and validation-helpers are available here
    var cleaned = cleanText(parameters.rawInput);
    var isValid = validateEmail(cleaned);
    return { valid: isValid };
Each sidecar module must also be a JavaScript module with an inline script. Sidecar scripts run in global scope (not wrapped in an IIFE), so any functions or variables they declare are available to subsequent sidecars and your main script.
A maximum of 10 module pre-loads are allowed per execution. Exceeding this limit will cause a startup error.

Document API (when used in script steps)

When your JavaScript module is used as a script step in a plan workflow, the full document API is available — including loadDocument(), node traversal, tagging, data object creation, and more. See the Script Steps guide for complete documentation.

Service Bridges (when used in script steps)

Script steps can call external APIs through project-scoped service bridges using serviceBridge.list() and serviceBridge.call(). See the Script Steps guide for details.

LLM Invocation (when used in script steps)

Script steps can invoke the platform’s LLM service using llm.invoke() and llm.invokeWithPromptRef(). See the Script Steps guide for details.

Limits

LimitValue
Script timeout60 seconds
Max module pre-loads10

Deployment

Deploy with the KDX CLI:
kdx apply -f module.yml
This will:
  1. Create or update the module metadata in the platform
  2. Store the inline script in the module metadata
  3. Make the module available for use in assistants, pipelines, and as a sidecar dependency
To inspect a deployed module’s metadata:
kdx get module my-org/my-js-module -o yaml

Example: Document Classifier

Here is a complete example of a JavaScript module that classifies documents based on metadata:

module.yml

slug: js-document-classifier
version: 1.0.0
orgSlug: my-org
type: store
storeType: MODEL
name: JS Document Classifier
metadata:
  moduleRuntimeRef: kodexa/go-scripting-runtime
  type: module
  scriptLanguage: javascript
  inferenceOptions:
    - name: default_category
      type: string
      default: "general"
      description: "Default category when no match is found"
  script: |
    var category = parameters.default_category || "general";
    var context = parameters.pipeline_context || {};

    log("info", "Classifying document with default: " + category);

    // Check pipeline context for hints
    var filename = (context.filename || "").toLowerCase();

    if (filename.indexOf("invoice") !== -1) {
      category = "invoice";
    } else if (filename.indexOf("contract") !== -1) {
      category = "contract";
    } else if (filename.indexOf("receipt") !== -1) {
      category = "receipt";
    }

    log("info", "Classified as: " + category);
    return { category: category };

Example: Reusable Utility Module

This module is designed to be used as a sidecar dependency. It defines utility functions in global scope that other modules can call:

module.yml

slug: string-utils
version: 1.0.0
orgSlug: my-org
type: store
storeType: MODEL
name: String Utilities
metadata:
  moduleRuntimeRef: kodexa/go-scripting-runtime
  type: module
  scriptLanguage: javascript
  script: |
    function cleanText(text) {
      if (!text) return "";
      return text.replace(/\s+/g, " ").trim();
    }

    function extractEmails(text) {
      var pattern = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
      return (text.match(pattern) || []);
    }

    function truncate(text, maxLen) {
      maxLen = maxLen || 200;
      if (text.length <= maxLen) return text;
      return text.substring(0, maxLen) + "...";
    }
Other modules can then reference this as a sidecar:
metadata:
  moduleSidecars:
    - my-org/string-utils
  script: |
    // cleanText, extractEmails, truncate are all available
    var cleaned = cleanText(parameters.rawInput);
    var emails = extractEmails(cleaned);
    log("info", "Found " + emails.length + " email addresses");
    return { emails: emails, summary: truncate(cleaned) };

Using Your Module

Once deployed, your JavaScript module can be:
  • Added to an Assistant in your project through Studio
  • Referenced as a sidecar by other JavaScript modules
  • Used in scheduled jobs and pipelines
See Working with Modules for more details.

Troubleshooting

Script syntax errors

  • JavaScript modules use ES5+ syntax. Features like let, const, arrow functions, and template literals are supported, but some ES2015+ features may not be available.
  • Check that your script does not contain syntax errors by testing locally with Node.js.

Module sidecar not found

  • Verify the sidecar module exists and has been deployed with kdx get module my-org/sidecar-slug
  • Ensure the sidecar module has a script field in its metadata
  • Check that the sidecar reference uses the correct orgSlug/moduleSlug format

Script timeout

  • The default timeout is 60 seconds. Long-running scripts will be interrupted.
  • Optimize loops and avoid blocking operations.
  • Consider breaking complex logic into multiple steps.

Deployment failures

  • Verify KDX CLI is configured: kdx config --list
  • Check the orgSlug in module.yml matches your organization
  • Ensure module.yml is valid YAML (watch for indentation in the script block)
  • Run kdx apply from the directory containing module.yml