Portal Community

Sandbox Engines

EngineIsolationPerformanceES SupportWhen to Use
JintFull — pure .NET, no native codeGood for simple logicES2020Default; maximum security isolation
V8 (ClearScript)V8 isolate — separate heap per callMuch faster for complex codeFull modern JSPerformance-sensitive functions; complex computations

What Is Available in the Sandbox

// Available JavaScript globals:
console.log(...)       // Outputs to application logger (does NOT reach the browser)
JSON.parse(...)        // JSON serialisation
JSON.stringify(...)    // JSON deserialisation
Date                   // Date objects and arithmetic
Math                   // Math functions
Array, Object, String  // Standard JS built-ins
setTimeout / clearTimeout  // Available but async execution is bounded by timeout limit

// Injected by AIFunctionRuntime (available as globals):
__tenantId             // string — the calling tenant's ID
__agentId              // string — the calling agent's ID
__userId               // string — the calling user's ID
__env                  // object — read-only config values (non-secret, pre-defined)

What Is Blocked

// These are NOT available — any attempt throws ReferenceError:
fetch(...)             // No network access
XMLHttpRequest         // No network access
require(...)           // No module loading
import(...)            // No dynamic imports
process                // No Node.js process access
fs                     // No filesystem
__dirname / __filename // No path information
eval(...)              // Blocked (code injection risk)
Function(...)          // Blocked (dynamic function creation)
WebSocket              // No network access

AIFunctionRuntime C# Implementation

public class AIFunctionRuntime
{
    private readonly AIFunctionRuntimeConfig _config;

    public async Task<JsonElement> ExecuteAsync(
        AIFunction function,
        JsonElement input,
        AIFunctionContext context,
        CancellationToken ct)
    {
        using var engine = CreateSandboxedEngine(context);

        // Load the function code
        engine.Execute(function.Code);

        // Convert input to JS object and call execute()
        var jsInput  = engine.FromJsonElement(input);
        var jsResult = engine.Invoke("execute", jsInput);

        // Serialise result back to JSON
        return JsonSerializer.Deserialize<JsonElement>(
            engine.ToJson(jsResult));
    }

    private JintEngine CreateSandboxedEngine(AIFunctionContext ctx)
    {
        var engine = new Engine(options =>
        {
            options.TimeoutInterval(TimeSpan.FromSeconds(_config.TimeoutSeconds));
            options.MaxStatements(_config.MaxStatements);
            options.LimitMemory(_config.MaxHeapMb * 1024 * 1024);
        });

        // Inject context globals (read-only)
        engine.SetValue("__tenantId", ctx.TenantId.ToString());
        engine.SetValue("__agentId",  ctx.AgentId.ToString());
        engine.SetValue("__userId",   ctx.UserId);

        return engine;
    }
}

Execution Limits

LimitDefaultConfig Key
Execution timeout5 secondsAIFunctions:TimeoutSeconds
Max heap memory64 MBAIFunctions:MaxHeapMb
Max JS statements1,000,000AIFunctions:MaxStatements
Max result JSON size100 KBAIFunctions:MaxResultKb