AutolangDocs

Best Practices

Essential design patterns, memory guidelines, and API recommendations when embedding the Autolang virtual machine into host applications for AI execution.

When to use @js_object

Use @js_object when the object already exists in the host application.

Why @js_object Exists:

Under the hood, @js_object is fundamentally a native JsObject handle. However, rather than forcing scripts to call loose global functions or unstructured string calls, @js_object wraps the reference inside a clean, typed OOP class interface.

  • OOP Semantics: Scripts get dot-notation autocomplete, static type safety, and clean method syntax without calling loose functions.
  • Zero Field Copying: Autolang stores only the raw JS object handle. Native method calls (e.g. getName(), setName()) delegate directly to the underlying JS instance with this bound automatically.

Flexible Bi-directional Type Casting:

Autolang features an intelligent type casting engine between native JavaScript values and internal AObject VM representations. When native JS functions receive parameters or return values:

  • Primitives & Data: Numbers, strings, booleans, and arrays cast seamlessly back and forth.
  • Host References: Objects marked with @js_object bypass value copying — the VM casts and stores the raw JS handle directly.
  • Zero Boilerplate: Native functions simply return standard JavaScript objects; Autolang handles two-way marshaling and type checking automatically.

Good Candidates for @js_object:

  • Database entities and ORM models
  • Query builders and fluent filters
  • HTTP requests and response objects
  • File handles and stream controllers
  • External SDK client objects
@js_object class Product { fun getName(): String fun setName(value: String): Void fun getPrice(): Float }

When to use normal classes

Normal Autolang classes are ideal for small values created and owned entirely by the script.

class Point( val x: Float, val y: Float )

Good Candidates for Normal Classes:

  • Data Transfer Objects (DTOs)
  • Configuration objects
  • Mathematical and geometric types
  • Temporary script data

Avoid unnecessary copies

Prefer returning @js_object instead of converting large host objects into VM memory structures. Using getter/setter methods on @js_object avoids expensive field-by-field marshaling and eliminates repetitive type casting on subsequent operations.

Recommendedval user = db.findUser(1) println(user.getName()) // @js_object reference, zero copying
Avoidval user = db.findUser(1) println(user.name) // if user was copied field-by-field

Design small native APIs

Expose only the specific operations the AI actually needs. Avoid exposing large generic APIs that grant unnecessary system access.

@js_object class Product { fun getName(): String fun setName(value: String): Void fun getPrice(): Float }

Prefer fluent APIs

Objects representing builders or queries work naturally with method chaining (Fluent APIs). Fluent syntax is significantly easier for Large Language Models to generate accurately without syntax errors or variable misplacements.

Implementing Fluent APIs with @js_object:

1. Define each builder method in the @js_object class to return the class instance type (e.g. Query).
2. In the host JavaScript implementation, return this from each builder method.
3. Expose a single execution method (e.g. execute()) to trigger the host action.

// Host Registration compiler.registerBuiltInLibrary("db", ` @js_object class Query { @native("query_where") fun where(field: String, value: String): Query @native("query_order") fun orderBy(field: String, direction: String): Query @native("query_limit") fun limit(count: Int): Query @native("query_exec") fun execute(): Array<Product> } `, { autoImport: true }, { query_where(field, value) { return this.where(field, value); }, query_order(field, dir) { return this.orderBy(field, dir); }, query_limit(count) { return this.limit(count); }, query_exec() { return this.execute(); } }); // AI Script Usage val products = Database.createQuery() .where("status", "completed") .orderBy("amount", "desc") .limit(10) .execute()

Restrict AI capabilities

Keep libraries focused. Avoid monolithic system libraries — prefer modular single-responsibility libraries such as mail, database, storage, and report.

Memory management

Use setManagedMemory() on the host compiler to cap the maximum memory budget available for Autolang-managed heap allocations. Host-owned objects wrapped in @js_object remain outside VM memory accounting.

Learn more in the Security & Sandboxing Guide.

Common mistakes

Avoid: Copying every host object into Autolang

Return a @js_object whenever the host already owns the underlying object.

Avoid: Registering an entire SDK

Register only the specific capability functions AI scripts should invoke.

Avoid: Exposing unrestricted file or network access

Enable only the specific capability interfaces required for the task workflow.

Rule of Thumb

Use CaseChoose
Small immutable dataNormal Autolang class
Host-owned objects@js_object
Large database entities@js_object
Builders / ORM query objects@js_object
Script-only transient valuesNormal class