Skip to content
This page is a translation of the authoritative Chinese source and may lag behind.View the original

Scripting API reference ​

GateLLM ships a JavaScript script engine (QuickJS-based) for custom transforms on request and response JSON bodies. Scripts run in a sandbox with strict resource limits — safe and controllable.

This chapter is the API reference. For an intro see Write your first script transform; for config see Scripting config.

Basic structure ​

Each script defines a transform function that receives body and context, and must return body:

javascript
function transform(body, context) {
    // read and modify body
    // read context for metadata (read-only)
    return body;  // required!
}
ParameterMutableDescription
bodyyesJSON request body or response body
contextnoRequest/response metadata (model name, headers, etc.)

The Context object ​

context provides metadata of the current request/response, read-only:

Available in both request and response phases ​

FieldTypeDescription
context.clientModelstringThe model name the client sees
context.upstreamModelstringThe model ID sent to the upstream
context.upstreamNamestringThe upstream group name
context.sourceProtocolstringThe client protocol (e.g. "OpenAIChatCompletions")
context.targetProtocolstringThe upstream protocol (e.g. "Anthropic")
context.streambooleanWhether it's a streaming request
context.headersobjectRequest headers (sensitive headers filtered out)
context.queryobjectURL query parameters
context.requestIdstringUnique request ID
context.clientIpstringClient IP
context.accessKeyNamestringAccess key name
context.accessKeyGroupstringAccess key group

Available in the response phase only ​

FieldTypeDescription
context.responseStatusnumberUpstream HTTP status code
context.responseHeadersobjectUpstream response headers
context.elapsedMsnumberElapsed time (milliseconds)

Security: sensitive headers like authorization, cookie, x-api-key are removed before scripts can see them.

context.useModel route switching ​

javascript
context.useModel("model-name");

Full route switch: base_url, protocol, and credentials change together. body.model = "X" only changes the request body's field, not the route — use context.useModel to switch across endpoints/protocols.

The two request-script slots (before / after) ​

Request-side scripts are no longer one script plus a position switch, but two independent slots, each optionally empty and configurable together:

SlotFieldRun timingBody seenuseModel capability
After translationrequest_transform_afterafter protocol translationupstream protocol formatsame-protocol switch only
Before translationrequest_transform_beforebefore protocol translationclient original formatsupports cross-protocol switch
  • request_transform_after: runs after protocol translation, the body is already in upstream format. Suitable for simple field edits and upstream-dialect rewrites.
  • request_transform_before: runs before protocol translation, the body is the client's original format. Suitable for detecting client input (images, search, plan-mode markers) and switching routes.
  • Both slots can be configured together: before and after of the same route merge independently (model overrides upstream), and both scripts run — before runs first (can trigger a cross-protocol immediate useModel switch), after runs later. Note: once the before slot triggers an immediate useModel route switch, the original route's after slot no longer runs (the whole pipeline switches to the target route's); the after slot's declared useModel is a same-protocol deferred switch. response_transform has no slot concept and stays a single field.

Execution order ​

The before and after slots each run independently; when both are configured for the same route, before runs first in the pre-translation phase and after in the post-translation phase. Below are the positions of the two slots in the pipeline.

Request side — after slot (post-translation) ​

text
client request → protocol translation → auto normalization → request_payload rules → upstream script → model script → cache injection → send to upstream

Request side — before slot (pre-translation) ​

text
client request → upstream script → model script → (useModel swap) → protocol translation → auto normalization → request_payload rules → cache injection → send to upstream

Response side (non-streaming only) ​

text
upstream response → response script → reverse protocol translation → return to client

Response scripts for streaming requests are not supported yet.

Built-in functions ​

JSON Path operations ​

javascript
// read a nested value
const temp = json_path(body, "generation_config.temperature");

// set a value (auto-creates intermediate objects)
set_path(body, "generation_config.max_output_tokens", 4096);

// remove a field
remove_path(body, "deprecated_field");

// add only when the field doesn't exist
add_if_absent_path(body, "temperature", 1.0);

// append to an array
append_path(body, "messages", { role: "system", content: "Be concise." });

String functions ​

javascript
str_len("Hello, 世界!");           // 9 (character count, not bytes)
str_contains("hello world", "world"); // true
str_replace("foo-bar", "-", "_");    // "foo_bar"
str_starts_with("hello", "he");     // true
str_trim("  hello  ");              // "hello"

Regular expressions ​

javascript
regex_match("abc123", "[0-9]+");     // true
regex_replace("foo123bar", "[0-9]+", "N");  // "fooNbar"
regex_extract("a=1 b=2", "([a-z]+)=");  // ["a", "b"]

Encoding and hashing ​

javascript
base64_encode("hello");    // "aGVsbG8="
base64_decode("aGVsbG8="); // "hello"
sha256("hello");           // "2cf24dba5fb0..."
json_encode(body.messages); // serialize to string
json_parse(jsonStr);        // parse from string

Array functions ​

javascript
array_sort([3, 1, 2]);                // [1, 2, 3]
array_unique([1, 2, 2, 3]);           // [1, 2, 3]
array_filter_by(items, "active", true); // keep elements with active=true
array_find(users, "name", "alice");    // find the first element with name=alice
array_pluck(users, "name");           // extract all name fields
array_sum([1.5, 2.5, 3.0]);           // 7.0

Deep copy and merge ​

javascript
const backup = deep_clone(body);  // independent copy
const merged = deep_merge(defaults, overrides);  // recursive merge

UUID and time ​

javascript
uuid();    // "550e8400-e29b-41d4-a716-..."
now();     // 1748620800 (second-level timestamp)
now_ms();  // millisecond-level
format_time(now(), "%Y-%m-%d %H:%M:%S");  // "2025-05-31 00:00:00"

Runtime limits, error handling, and testing ​

The sandbox capability boundaries (what scripts can/can't do), the resource-limit table (operation count, heap cap, concurrent execution slots, lazy-projection semantics), script_error_mode error handling, common errors and troubleshooting, the test endpoint (POST /console/api/scripts/test), and performance advice are all in Script runtime limits and configuration — that is the single authoritative page for script config and limits; this page does not repeat them.

FAQ ​

Q: The script changed body.model, but the route didn't change.body.model only changes the request body's field, not the route. To switch routes use context.useModel("model-name").

Q: Does a response script work for streaming requests? Streaming-response scripts are not supported yet. Request scripts work for streaming requests, but response scripts only take effect for non-streaming.

Q: How do I choose between Before and After script positions?

  • Only changing fields of the upstream-format body → After (default)
  • Needing to detect the client's original format (e.g. different protocols have different image fields) and the judgment exceeds what switch-route can express → Before
  • Pure routing decisions like "detect image/web-search → switch model" (including cross-protocol) → prefer the native switch-route rule, see Route image-bearing requests to a vision model

Next: Write your first script transform for the intro structure; Fix protocol translation with scripts and Redact responses with a script for real examples; Script runtime limits and configuration for the sandbox, resource limits, error handling, and testing.