Skip to main content

Example on GitHub

Full working example with type-checked TypeScript execution.
Give your agent a code-execution tool with explicit CPU and memory limits. The agent writes code, runs it in an isolate, and gets back structured results.

Run generated JavaScript

The agent writes JavaScript, uses export to return values, and the host gets them back.
JavaScript Execution
import { generateText, stepCountIs, tool } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import { NodeRuntime, createNodeDriver, createNodeRuntimeDriverFactory } from "secure-exec";
import { z } from "zod";

const runtime = new NodeRuntime({
  systemDriver: createNodeDriver({
    permissions: {
      fs: () => ({ allow: true }),
      network: () => ({ allow: true }),
    },
  }),
  runtimeDriverFactory: createNodeRuntimeDriverFactory(),
  memoryLimit: 64,
  cpuTimeLimitMs: 5000,
});

const { text } = await generateText({
  model: anthropic("claude-sonnet-4-6"),
  prompt: "Calculate the first 20 fibonacci numbers",
  stopWhen: stepCountIs(5),
  tools: {
    execute: tool({
      description: "Run JavaScript in a secure sandbox. Use export to return data.",
      inputSchema: z.object({ code: z.string() }),
      execute: async ({ code }) => runtime.run(code, "/entry.mjs"),
    }),
  },
});

console.log(text);

Type-check generated TypeScript before execution

If the agent writes TypeScript, type-check it first. Failed diagnostics go back to the agent for repair; passing code gets compiled and executed.
Type-Checked Execution
import { generateText, stepCountIs, tool } from "ai";
import { anthropic } from "@ai-sdk/anthropic";
import {
  NodeRuntime,
  createNodeDriver,
  createNodeRuntimeDriverFactory,
} from "secure-exec";
import { createTypeScriptTools } from "@secure-exec/typescript";
import { z } from "zod";

const systemDriver = createNodeDriver({
  permissions: {
    fs: () => ({ allow: true }),
    network: () => ({ allow: true }),
  },
});
const runtimeDriverFactory = createNodeRuntimeDriverFactory();

const runtime = new NodeRuntime({
  systemDriver,
  runtimeDriverFactory,
  memoryLimit: 64,
  cpuTimeLimitMs: 5000,
});
const ts = createTypeScriptTools({
  systemDriver,
  runtimeDriverFactory,
  memoryLimit: 256,
  cpuTimeLimitMs: 5000,
});

const { text } = await generateText({
  model: anthropic("claude-sonnet-4-6"),
  prompt:
    "Write TypeScript that calculates the first 20 fibonacci numbers. Use export to return the result.",
  stopWhen: stepCountIs(5),
  tools: {
    execute_typescript: tool({
      description:
        "Type-check TypeScript in a sandbox, compile it, then run the emitted JavaScript in a sandbox. Return diagnostics when validation fails.",
      inputSchema: z.object({ code: z.string() }),
      execute: async ({ code }) => {
        const typecheck = await ts.typecheckSource({
          sourceText: code,
          filePath: "/root/generated.ts",
          compilerOptions: {
            module: "esnext",
            target: "es2022",
          },
        });

        if (!typecheck.success) {
          return {
            ok: false,
            stage: "typecheck",
            diagnostics: typecheck.diagnostics,
          };
        }

        const compiled = await ts.compileSource({
          sourceText: code,
          filePath: "/root/generated.ts",
          compilerOptions: {
            module: "esnext",
            target: "es2022",
          },
        });

        if (!compiled.success || !compiled.outputText) {
          return {
            ok: false,
            stage: "compile",
            diagnostics: compiled.diagnostics,
          };
        }

        const execution = await runtime.run<Record<string, unknown>>(
          compiled.outputText,
          "/root/generated.mjs"
        );

        if (execution.code !== 0) {
          return {
            ok: false,
            stage: "run",
            errorMessage:
              execution.errorMessage ?? `Sandbox exited with code ${execution.code}`,
          };
        }

        return {
          ok: true,
          stage: "run",
          exports: execution.exports,
        };
      },
    }),
  },
});

console.log(text);
See TypeScript for the lower-level compile and type-check APIs.