Custom Code Patterns

The Custom Code Agent extends the Ema Builder Platform with arbitrary logic that cannot be expressed through the standard agent library. When a workflow requires data transformation, custom validation, mathematical computation, or integration with a proprietary algorithm, the Custom Code Agent provides a sandboxed JavaScript or TypeScript execution environment within the workflow pipeline.

This page covers common patterns for using the Custom Code Agent effectively, including data transformation, conditional routing, and hybrid workflows that combine custom code with standard agents. For the full API reference, see Custom Code Agent.

When to Use Custom Code

Use the Custom Code Agent when:

  • You need to parse, filter, or reshape data (CSV, JSON, text) with precise control over the output format.
  • You need custom mathematical or statistical computation (scoring algorithms, weighted averages, threshold calculations).
  • You need deterministic branching or conditional logic that is more complex than what trigger-when conditions support.
  • You need to parse or restructure data from an external API response before passing it to a downstream agent.

Pattern 1: Data Transformation and Computation

Problem

You have data -- a CSV file, a JSON structure, a block of text -- that needs to be parsed, filtered, reshaped, or computed on. Examples include parsing CSV into structured rows, filtering by criteria, computing aggregates (totals, averages, weighted scores), or reformatting data for a specific output.

Approach

  1. Pass the data into the Custom Code Agent as a named input.
  2. Write code that parses, transforms, or computes on the input and returns the result as a string.

Example

// Parse CSV, filter rows with score >= 80, compute total and return summary
function main(inputs) {
  var rows = Papa.parse(inputs.csv_data[0].text, { header: true, skipEmptyLines: true }).data;
  var high = rows.filter(function(r) { return parseInt(r.score, 10) >= 80; });
  var total = high.reduce(function(sum, r) { return sum + parseInt(r.score, 10); }, 0);
  return JSON.stringify({ count: high.length, total: total, names: high.map(function(r) { return r.name; }) });
}

Pattern 2: Custom Scoring and Routing

Problem

You need to apply a proprietary scoring algorithm to data extracted by an upstream agent, then route the workflow based on the score. For example, a lead scoring model that weighs multiple factors in a custom formula, or a risk assessment that applies domain-specific rules beyond what the Rule Validation agent supports.

Components

Extract Entities Agent
 --> Custom Code Agent (compute score)
 --> Categorizer (route based on score threshold)
 --> [high score] --> Branch A
 --> [low score] --> Branch B

Approach

  1. Extract the relevant data points with an upstream agent.
  2. In the Custom Code Agent, implement your scoring formula. Return the score as a structured output.
  3. Use the Categorizer agent downstream to route the workflow based on the score value.

Watch Out For

  • Keep the code simple. Complex algorithms with many dependencies are hard to debug in a sandboxed environment. If the scoring logic is highly complex, consider calling an external API via call_ema_connector() or using the External Tool Caller agent instead.
  • Test with edge cases. Scores of zero, negative values, missing input fields, and extreme outliers should all produce reasonable behavior.

Pattern 3: Hybrid Workflows

Problem

Some workflows require a mix of AI-driven steps (search, summarization, classification) and deterministic logic (date calculations, format validation, lookup tables). The Custom Code Agent lets you insert deterministic steps into an otherwise AI-driven pipeline.

Approach

  1. Use standard agents for tasks they excel at: search, summarization, classification, tool calling.
  2. Insert Custom Code Agent steps where you need deterministic, reproducible logic: date math, format validation, lookup tables, conditional formatting.
  3. Use call_llm() within the same script when you need both deterministic logic and LLM reasoning in a single step -- for example, transforming data and then summarizing the result.

Example

// Filter high-value rows, then ask the LLM to summarize
function main(inputs) {
  var parsed = Papa.parse(inputs.csv_data[0].text, { header: true, skipEmptyLines: true });
  var high = parsed.data.filter(function(row) { return parseFloat(row.amount) >= 1000; });
  if (high.length === 0) return "No high-value transactions found.";
  var summary = call_llm(
    "Summarize the following transactions:\n\n" + JSON.stringify(high),
    "You are a financial analyst. Return a concise 2-3 sentence summary."
  );
  return summary;
}

Watch Out For

  • Do not hand-write NLP logic in code. If you find yourself implementing text classification or entity extraction manually, use call_llm() within the script or a dedicated agent like Categorizer instead.
  • Keep code stateless. Each Custom Code Agent execution is independent. Do not rely on state from a previous execution -- pass all required data through the workflow.

Tips

  • Always return a string. Returning an object produces "[object Object]". Use JSON.stringify() for structured data.
  • Guard against null inputs. If an upstream agent was skipped or returned nothing, the input is null. Check before accessing properties.
  • Use log.info() to debug. Log messages appear in the Show Work panel -- more useful than code comments for tracing execution.
  • Test with real data. Copy inputs from a previous workflow run (Show Work → Execution logs → Script Inputs) and paste them into the test modal.

Last updated: Jul 3, 2026