> Source: https://builder.ema.ai/v2/agent-reference/code-agent
> Title: Code Agent

# Code Agent

The Code Agent (`code_execution`) runs TypeScript (or JavaScript) you write in a sandboxed runtime. It receives typed inputs from the upstream nodes wired into it, can call LLMs and log progress as it runs, and returns whatever structured value your code produces. Reach for it when a step is easier to express as code than as Instructions — deterministic data transformation, conditional logic, reshaping one node's output into the exact shape the next node needs, or orchestrating LLM calls programmatically.

The Code Agent belongs to the **Frequently Used** group in the agent library.

Unlike the LLM-based agent types, the Code Agent **does not run the agentic loop**. Your script is dispatched to the script-executor sandbox, runs to completion (calling the LLM as many times as you ask it to), and returns. There is no system prompt and no Instructions field — your logic lives entirely in the script.

## When to use it

-   You need a **deterministic** transformation: parse a CSV, normalize dates, compute a total, filter a list.
-   You need to **reshape** an upstream agent's output to match a downstream node's input schema.
-   You want to **call an LLM from code** — for example, loop over rows and classify each one, or summarize several inputs and combine the results — with full control over prompts and control flow.
-   The logic is conditional or iterative in a way that is awkward to express as Instructions.

For open-ended reasoning, tool use, and knowledge-base retrieval, use a [Custom Agent](/builder/v2/agent-reference/custom) or one of the specialized LLM types instead.

## The script contract

Your code defines a `main` function that receives the node's inputs and returns the output:

```typescript
function main(inputs: Inputs) {
  // your logic here
  return { /* structured output */ };
}
```

-   The single `inputs` argument is an object whose fields are the node's inputs, wired from upstream nodes via `input_mapping`. The builder generates an `Inputs` TypeScript type from the node's `input_schema` so the editor offers autocomplete on `inputs.<field>`.
-   Whatever `main` returns becomes the node's output. Return an object, array, or scalar — downstream nodes reference it via `{{node_<id>.output.<field>}}`.
-   The default language is **TypeScript**, transpiled before execution; **JavaScript** is also supported.

### Built-in functions and libraries

The sandbox exposes a small, fixed set of host functions and bundled libraries as globals — you do not import them:

Global

Signature

Purpose

`call_llm`

`call_llm(user_prompt, system_prompt?) → string`

Calls an LLM and returns the completion text. Honors the node's model selection.

`log.info` / `log.warning` / `log.error`

`log.info(msg)`

Records a log line that appears in the execution trace shown to the builder.

`_`

lodash

Utility functions for arrays, objects, and collections.

`Papa`

papaparse

CSV parsing and generation.

`uuid`

uuid

UUID generation.

`base64`

base64-js

Base64 encode/decode.

`call_llm` is capped per run. By default a script may make up to **20** `call_llm` calls; override the cap with `type_config.max_llm_calls`.

### Calling attached integrations

If you attach integrations to the Code Agent node, the sandbox exposes them under a frozen `integrations` namespace keyed by the integration's name, which you pass to `call_integration`:

```typescript
function main(inputs: Inputs) {
  const result = call_integration(integrations["hubspot_crm"], {
    method: "GET",
    path: "/crm/v3/objects/contacts",
  });
  return result.body;
}
```

`call_integration` returns `{ ok, status, headers, body }`. An upstream 4xx/5xx is not a thrown error — it comes back with `ok: false` and the status so your code can branch on it. The `call_integration` global is only present when the node has at least one integration attached; a script that calls it on a node with no attachments gets a clean reference error. Each connection is pinned at configuration time, and credential resolution, SSRF protection, and PII handling are enforced by the integrations service on every call.

## Configuration

You configure the Code Agent through `agent_config.type_config`.

```json
{
  "language": "typescript",
  "script": "function main(inputs) {\n  const total = inputs.amounts.reduce((a, b) => a + b, 0);\n  log.info(`summing ${inputs.amounts.length} amounts`);\n  return { total, count: inputs.amounts.length };\n}\n",
  "max_llm_calls": 20,
  "output_schema": {
    "type": "object",
    "properties": {
      "total": { "type": "number" },
      "count": { "type": "integer" }
    },
    "required": ["total", "count"]
  }
}
```

Field

Required

Purpose

`script`

Yes

The source to run. Must define `main(inputs)`.

`language`

No

`"typescript"` (default) or `"javascript"`. Any other value is rejected with a validation error.

`max_llm_calls`

No

Cap on `call_llm` invocations per run. Defaults to 20.

`output_schema`

No

JSON Schema documenting the shape your script returns. Used to type downstream nodes that read this node's output; the Code Agent has no implicit default output schema.

`integration_attachments`

No

The integrations and connections bound to the node, exposed in code via the `integrations` namespace.

The model selection used by `call_llm` is resolved with the same priority the LLM types use: the agent-level model config first, then the workflow's EmaFusion™ config, then a fallback to the platform default.

## Inputs and output

**Inputs** are the fields you wire into the node, available as `inputs.<field>` in your script. For the example above, an upstream node would supply:

```json
{ "amounts": [120.5, 80, 250] }
```

**Output** is the return value of `main`. For the example:

```json
{ "total": 450.5, "count": 3 }
```

The execution response also carries:

-   **`execution_trace`** — the structured trace of the run, grouped into steps. Each entry is either a `log` entry (your `log.info` / `log.warning` / `log.error` lines) or an `llm_call` entry (the prompt, response, model, and token counts for each `call_llm`). The builder renders this so you can see exactly what the script did.
-   **`tokens_used`** — total tokens consumed by `call_llm` during the run.
-   **`execution_error`** — on failure, the user-visible error message. For TypeScript it is source-mapped, so line numbers point at your original code rather than the transpiled output. When this is set, the node's status is `failed`.

## Testing a Code Agent

You can test a Code Agent node from the builder before publishing. The test panel auto-generates sample inputs from the node's `input_schema` (which you can edit or replace with real values from run history), runs the script through the same dispatch path the workflow uses, and returns the output, any error, token usage, and the inline execution log. Code Agent nodes skip the system-prompt validation that other types require, since their logic lives in `script` rather than in Instructions.

> [INFO]
> **Dispatch-only, like the other custom variants.** `code_execution` runs in the script-executor sandbox and is not part of the live/deprecated agent-type catalog lifecycle — there are no platform-managed versions to pin. See the [Agent Reference overview](/builder/v2/agent-reference#the-agent-type-catalog).

## What's next

-   [Agent Reference overview](/builder/v2/agent-reference) — how agents work, the catalog, the four builder groups, and the shared execution engine.
-   [Custom Agent](/builder/v2/agent-reference/custom) — when you want an agentic loop with Tools and a knowledge base instead of raw code.
-   [Data Extractor Agent](/builder/v2/agent-reference/extraction) — pull structured fields out of unstructured text with a schema.
