Code tools

Run custom JavaScript logic directly on ElevenLabs' infrastructure.

Code tools let your agent run custom JavaScript in a sandboxed server-side environment, without you having to stand up and host your own webhook endpoint. Write the logic once in the built-in code editor, and ElevenLabs executes it whenever the agent calls the tool.

This is an enterprise-only feature.

Overview

A code tool is a JavaScript function that runs when the agent calls it. You write the whole function body, so the tool can do as much or as little as the task requires:

  • Custom calculations: apply pricing rules, unit conversions, scoring logic, or date math using only the tool-call parameters. No network access required.
  • Calling external APIs: fetch from allowlisted domains, with workspace secrets and auth connections injected into the function’s context.
  • Combining multiple sources: call two or three APIs and merge, compare, or reconcile their results before returning a single answer.
  • Conditional branching: run different logic depending on the tool-call parameters, without needing a separate tool per branch.
  • Reshaping data: return exactly the structure you want the agent to see, rather than a raw upstream response.

For a single external API call with no custom logic, webhook tools are usually simpler to set up. To trigger actions in a user’s browser or app, use client tools instead.

How it works

Your code is a JavaScript module that exports a single default async function. The function receives a ctx object and returns the tool’s result:

1export default async (ctx) => {
2 // ctx.args.<paramName> — the parameters the agent passed to this tool call
3 const { city } = ctx.args;
4
5 return { message: `Hello from ${city}!` };
6};

The value you return becomes the tool’s result. It’s passed back to the agent, shown in the conversation transcript, and can be used for dynamic variable assignment.

The ctx object

ctx is your entry point to everything the tool can access at call time. The parameters the agent provides always arrive in ctx.args; secrets, config values, and auth connections are optional, and appear only if you map them in the tool’s Context object section.

PropertyDescription
ctx.argsThe tool-call parameters the agent provided.
ctx.configPlain string variables you’ve mapped into this tool’s context.
ctx.secretsWorkspace secrets you’ve mapped into this tool’s context for use in request headers. The raw secret is never exposed to your code; injection happens on egress and exclusively in the headers.
ctx.auth_connectionsReferences to configured auth connections you’ve mapped into this tool’s context, for use in the X-With-Auth-Connection request header. The underlying credential is never exposed to your code; injection happens on egress and exclusively in the headers.

Only ctx.args is visible to the agent when it calls the tool. Secrets, config values, and auth connections are never revealed to the agent.

Configuring parameters

Parameters are the values the agent supplies when it calls the tool, and they arrive in ctx.args. Define them in the Parameters section of the tool configuration form, or in the code editor under the Params tab, in the Define Params sub-tab. Each parameter takes a data type, an identifier, and a description that the agent uses to determine the correct value from the conversation. Your code reads that value under the identifier, such as ctx.args.appointment_datetime below.

Defining a code tool parameter

Configuring the context object

Add secrets, config values, and auth connections in the tool’s Context object section. Each entry takes a type and a name. The panel shows the exact accessor for each entry, such as ctx.secrets.DEMO_KEY below.

Mapping a workspace secret into a code tool's context object

Network access

Code running in the sandbox can only reach domains your workspace has explicitly allowed. Add the domains your code needs to call in your workspace’s General Settings, under Code tool allowed domains. A request to any other domain fails.

Editing the Code tool allowed domains list requires Workspace admin permissions.

Execution limits

  • Timeout: each run must complete within the tool’s configured response timeout, from 1 up to 30 seconds.
  • No external packages: code tools currently run without npm dependencies.

Testing your code

Before saving, use Run in the code editor to execute your code with sample parameter values:

  • Params — set test values for each parameter your tool defines.
  • Output — see the returned result, or the error if execution failed.
  • Logs — see anything written with console.log, console.warn, or console.error, plus build and execution timing.

Guide

In this guide, we’ll create a code tool that converts a temperature and returns a friendly, formatted string:

1

Create a new code tool

On the Agent section of your agent settings page, choose Add Tool. Select Code as the Tool Type, then set a name and description:

FieldValue
Nameconvert_temperature
DescriptionConverts a temperature between Celsius and Fahrenheit
2

Define the parameters

Add two parameters so the LLM knows what to provide:

Data TypeIdentifierRequiredDescription
numbervaluetrueThe temperature value to convert
stringfrom_unittrueThe unit to convert from: "C" or "F"
3

Write the code

Open the code editor and replace the default source with:

1export default async (ctx) => {
2 const { value, from_unit } = ctx.args;
3
4 if (from_unit === "C") {
5 const fahrenheit = (value * 9) / 5 + 32;
6 return { result: `${value}°C is ${fahrenheit.toFixed(1)}°F` };
7 }
8
9 const celsius = ((value - 32) * 5) / 9;
10 return { result: `${value}°F is ${celsius.toFixed(1)}°C` };
11};

Use Run with a few sample values (e.g. value: 100, from_unit: "C") to confirm the output before saving.

4

Orchestration

Update your agent’s system prompt so it knows when to reach for the tool:

System prompt
When the user asks to convert a temperature, call convert_temperature with the
value and its unit ("C" or "F"), and read back the result naturally.
5

Testing

Start a conversation and try:

What’s 100 degrees Celsius in Fahrenheit?

The agent should call the tool and read back the converted value.

Authentication examples

Calling an API with a secret

1export default async (ctx) => {
2 const { order_id } = ctx.args;
3
4 const response = await fetch(`https://api.example.com/orders/${order_id}`, {
5 headers: {
6 Authorization: `Bearer ${ctx.secrets.EXAMPLE_API_KEY}`,
7 },
8 });
9
10 if (!response.ok) {
11 throw new Error(`Upstream error: ${response.status}`);
12 }
13
14 return await response.json();
15};

Map EXAMPLE_API_KEY to a workspace secret in the tool’s Context object section, then add api.example.com to Code tool allowed domains so the request is allowed to egress. The value you reference is a placeholder: the real secret is substituted into the header on egress, and is never visible to your code.

Calling an API with an OAuth auth connection

1export default async (ctx) => {
2 const { customer_id } = ctx.args;
3
4 const response = await fetch(`https://api.example.com/customers/${customer_id}`, {
5 headers: {
6 "X-With-Auth-Connection": ctx.authConnections.EXAMPLE_CRM,
7 },
8 });
9
10 if (!response.ok) {
11 throw new Error(`Upstream error: ${response.status}`);
12 }
13
14 return await response.json();
15};

Map EXAMPLE_CRM to a configured auth connection in the tool’s Context object section. The value you reference is a placeholder: the real credential is substituted into the header on egress, and is never visible to your code.

Best practices

Name tools intuitively, with detailed descriptions

If you find the assistant does not make calls to the correct tools, you may need to update your tool names and descriptions so the assistant more clearly understands when it should select each tool. Avoid using abbreviations or acronyms to shorten tool and argument names.

You can also include detailed descriptions for when a tool should be called. For complex tools, you should include descriptions for each of the arguments to help the assistant know what it needs to ask the user to collect that argument.

Name tool parameters intuitively, with detailed descriptions

Use clear and descriptive names for tool parameters. If applicable, specify the expected format for a parameter in the description (e.g., YYYY-mm-dd or dd/mm/yy for a date).

Consider providing additional information about how and when to call tools in your assistant’s system prompt

Providing clear instructions in your system prompt can significantly improve the assistant’s tool calling accuracy. For example, guide the assistant with instructions like the following:

Use `check_order_status` when the user inquires about the status of their order, such as 'Where is my order?' or 'Has my order shipped yet?'.

Provide context for complex scenarios. For example:

Before scheduling a meeting with `schedule_meeting`, check the user's calendar for availability using check_availability to avoid conflicts.

LLM selection

When using tools, we recommend picking high intelligence models like GPT 5.2, Gemini-2.5-Flash, or Claude Sonnet 4.5 and avoiding Gemini-2.0-Flash.

It’s important to note that the choice of LLM matters to the success of function calls. Some LLMs can struggle with extracting the relevant parameters from the conversation.