DEV Community

Hoàn Lương
Hoàn Lương

Posted on

Building Autolang: A Scripting Runtime for Lightweight AI-Generated Code

Building Autolang: A Scripting Runtime for Lightweight AI-Generated Code

I have some projects but I don't have much money, so I often use Gemini Flash for UI tasks and some features.

Gemini Flash is very fast and cheap, but sometimes it is surprisingly unreliable.

It can hallucinate members or functions that don't exist, or use as any just to make everything look OK.

This made me think about a problem.

Lightweight models are becoming extremely cheap, and I want to use them in my products. But if the models are going to generate code, maybe the solution isn't always to use a larger model.

What if the runtime itself was designed around the weaknesses of lightweight models?

That is how I started building Autolang.

Project: https://autolang.vercel.app
Documentation: https://autolang.vercel.app/docs

What is Autolang?

Autolang is a scripting runtime library rather than a general-purpose programming language.

I am building it as a small runtime sandbox for AI-generated code.

The basic idea is:

Developer-defined capabilities
            ↓
       AI-generated script
            ↓
       Autolang Compiler
            ↓
          VM / Runtime
Enter fullscreen mode Exit fullscreen mode

The developer decides what the AI can access.

For example, instead of exposing:

Database.query(...)
Enter fullscreen mode Exit fullscreen mode

I would prefer exposing something more constrained:

Products.getProducts()
Users.getUsers()
Orders.getRecentOrders()
Enter fullscreen mode Exit fullscreen mode

The AI can write the business logic, while the developer controls the capabilities available to it.

This also means the generated script doesn't need access to an entire database API or operating system.

Why build another language?

The main reason is not that I think another programming language is necessary for humans.

I am interested in compilers, so Autolang is also a project for me to learn about compiler and runtime design.

But I also want to explore whether a language can be designed around AI-generated code.

For example, static typing can provide the model with much better feedback when it generates something incorrectly.

Instead of:

something went wrong
Enter fullscreen mode Exit fullscreen mode

the runtime can provide a stack trace and a type error that gives the model enough information to fix its code.

This is especially interesting for cheaper models, which may make mistakes more frequently.

Some of the features

Autolang currently has or is designed around several features:

  • Static typing
  • Stack traces
  • Runtime error information
  • Opcode limits
  • Managed VM memory
  • Native function bindings
  • Developer-controlled capabilities
  • A small standard library
  • No need for generated scripts to install new packages

The syntax is statically typed and is inspired by languages such as Kotlin and TypeScript.

For example:

Products.getProducts()
    .filter { |product| product.remaining }
    .forEach { |product|
        ...
    }
Enter fullscreen mode Exit fullscreen mode

I want generated code to be relatively compact because the AI shouldn't need to generate package installation code or large amounts of boilerplate.

The language includes features such as ?., ??, !., as, is, fun, closures, and standard libraries.

Developer-defined bindings

One of the most important parts of Autolang is the binding system.

A developer can define a library that the Autolang program can use:

compiler.registerBuiltInLibrary(
  "company/database",
  `
    class Product(
      remaining: Bool
      price: Int
    )

    @js_object
    class Products {
      @native("get_products")
      fun getProducts(): Array<Product>
    }
  `,
  { autoImport: true },
  {
    get_products() {
      // Native implementation
    }
  }
);
Enter fullscreen mode Exit fullscreen mode

The Autolang VM keeps the type information.

So when the native function returns products, the VM knows that the result is:

Array<Product>
Enter fullscreen mode Exit fullscreen mode

This is different from simply exposing a generic JavaScript function and letting the generated code do whatever it wants.

If more complex objects are needed, they can also be represented as native JavaScript objects:

@js_object
class Product {
    @native("get_price")
    fun getPrice(): Int

    @native("is_remaining")
    fun isRemaining(): Bool
}
Enter fullscreen mode Exit fullscreen mode

The developer decides which operations are exposed.

An example

A TypeScript application can compile and execute an Autolang script:

await compiler.compileAndRun(
  "main.atl",
  `
    var expenseCount = 0
    var normalCount = 0
    var cheapCount = 0

    Products.getProducts()
      .filter { |product| product.remaining }
      .forEach { |product|
        when (product.price) {
          >3 -> expenseCount += 1
          ==3 -> normalCount += 1
          else -> cheapCount += 1
        }
      }

    println(...)
  `
);

console.log(compiler.getOutput());
Enter fullscreen mode Exit fullscreen mode

The important part is that the AI doesn't need to know how the database works.

It only needs to know that Products.getProducts() exists and what type it returns.

The developer keeps control over the actual native implementation.

Why not tool calling?

This is probably the first question people ask.

I don't see Autolang as a replacement for tool calling.

Tool calling is useful when the model needs to interact with external systems.

I am interested in situations where the model needs to perform a lot of computation or data processing after obtaining the data.

For example, imagine an internal SME application with:

Users.getUsers()
Enter fullscreen mode Exit fullscreen mode

and the AI needs to classify hundreds or thousands of users:

VIP
NORMAL
INACTIVE
Enter fullscreen mode Exit fullscreen mode

With a tool-calling approach, repeatedly sending requests between the model and the application can introduce additional latency and cost.

Instead, the application could expose the data to an Autolang script and let the script perform the processing inside the runtime.

So the model generates the logic once, rather than requiring a round trip for every individual operation.

Why not JavaScript, Python, or isolated-vm?

JavaScript and Python are general-purpose programming environments.

isolated-vm provides isolation for JavaScript.

Autolang is trying to solve a somewhat different problem.

I want the language itself to be small, statically typed, constrained, and predictable for generated code.

The runtime knows about:

  • Types
  • Opcodes
  • VM memory
  • Native bindings
  • Runtime errors
  • Stack traces

The goal is not simply to execute untrusted JavaScript.

The goal is to create an environment where an AI can generate a small script using a set of capabilities explicitly provided by the developer.

Is it a replacement for Docker or KVM?

No.

I don't intend Autolang to replace Docker, KVM, microVMs, or operating-system-level isolation.

Autolang is much more focused:

AI-generated code
        ↓
Developer-defined capabilities
        ↓
Autolang runtime
        ↓
Controlled execution
Enter fullscreen mode Exit fullscreen mode

It is intended to be a sandbox for AI-generated scripts that operate through bound functions.

For applications that require strong OS-level isolation, I would still expect technologies such as containers or VMs to be appropriate.

Memory and runtime size

One of my goals is to keep the runtime small.

The current Autolang instance uses about 0.5 MB with the full standard library enabled.

A 1,800-line test peaked at around 3.8 MB on Windows 11.

These are early measurements rather than formal benchmarks, but they are encouraging for the kind of lightweight runtime I am trying to build.

A possible use case

The main use case I currently have in mind is internal SME software.

For example, an application might expose:

Users.getUsers()
Products.getProducts()
Orders.getRecentOrders()
Enter fullscreen mode Exit fullscreen mode

Then an AI could generate small programs to answer business-specific questions:

Which customers are likely to be VIPs?

Which products are running low?

Which customers haven't ordered recently?

Which orders look unusual?
Enter fullscreen mode Exit fullscreen mode

The developer doesn't need to implement every possible analysis as a separate feature.

Instead, the developer provides safe capabilities and lets the AI generate the logic.

That could potentially reduce development time for internal tools where requirements change frequently.

What I am still unsure about

Autolang is still an experiment.

I don't know yet whether this is actually better than simply using JavaScript, Python, or existing sandboxing solutions.

I also don't know how much the AI-friendly type system and error reporting will actually improve the reliability of lightweight models in practice.

That is one of the reasons I am building it.

I want to find out whether a small runtime designed around AI-generated code can provide a useful middle ground between:

"Let the AI run arbitrary code"
Enter fullscreen mode Exit fullscreen mode

and

"Make every operation a separate tool call"
Enter fullscreen mode Exit fullscreen mode

For now, Autolang is both a compiler/runtime project I enjoy working on and an experiment in making cheap AI-generated code easier to execute safely and predictably.

If you are interested in the implementation, the project and documentation are here:

Project: https://github.com/hoansdz/Autolang

Documentation: https://autolang.vercel.app/docs

Top comments (0)