Skip to content

Gene Development Guide

This guide walks you through the full lifecycle of creating a Rotifer gene — from initial idea to cloud publication.

A gene is the atomic unit of capability in the Rotifer Protocol. Unlike traditional “skills” or “tools” that are static function wrappers, genes are living entities that:

  • Have a Phenotype — typed metadata describing their interface, domain, and fitness contract
  • Compete in Arenas — same-domain genes fight for survival based on fitness scores
  • Can be composed — genes combine via formal algebra (Seq, Par, Cond, Try)
  • Are sandboxed — WASM isolation ensures memory-safe, resource-limited execution
Terminal window
npx @rotifer/playground init my-project
cd my-project

This creates a project with 5 pre-installed Genesis genes that serve as baselines in the Arena.

Create a new gene directory with the required files:

Terminal window
mkdir -p genes/my-translator

Every gene must export an express() function — the single entry point for gene invocation.

genes/my-translator/index.ts
export async function express(input: {
text: string;
targetLang: string;
}): Promise<{ translated: string; confidence: number }> {
const translated = await translateText(input.text, input.targetLang);
return {
translated,
confidence: 0.95,
};
}
async function translateText(text: string, lang: string): Promise<string> {
// Your translation logic here
// Could call an API, use a local model, etc.
return `[${lang}] ${text}`;
}

Key rules for express():

  • Must be an export (named export, not default)
  • Must accept a single input object
  • Must return a non-null result object
  • Should handle errors gracefully (throw typed errors)

The Phenotype describes your gene’s interface contract.

{
"domain": "text.translate",
"inputSchema": {
"type": "object",
"properties": {
"text": { "type": "string", "description": "Text to translate" },
"targetLang": { "type": "string", "description": "Target language code" }
},
"required": ["text", "targetLang"]
},
"outputSchema": {
"type": "object",
"properties": {
"translated": { "type": "string" },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 }
},
"required": ["translated", "confidence"]
},
"version": "0.1.0",
"fidelity": "Wrapped",
"transparency": "Open"
}

Phenotype fields explained:

FieldDescription
domainFunctional domain — genes with the same domain compete in Arena
inputSchemaJSON Schema for input validation
outputSchemaJSON Schema for output validation
versionSemantic version
fidelityWrapped (API call), Hybrid (mix), or Native (pure WASM)
transparencyOpen (source auditable) or Opaque

Or use rotifer wrap to generate these automatically:

Terminal window
rotifer wrap my-translator --domain text.translate
Terminal window
rotifer test my-translator

The test suite automatically:

  1. Validates your Phenotype against the Gene Standard
  2. Calls express() with generated test inputs
  3. Checks that output matches outputSchema
  4. Verifies error handling
  5. Computes preliminary fitness scores

Add --verbose for detailed I/O:

Terminal window
rotifer test my-translator --verbose

Transform your TypeScript gene into a sandboxed WASM module:

Terminal window
rotifer compile my-translator

This runs the compilation pipeline:

  1. esbuild — Bundle and minify TypeScript
  2. WASI shim — Add WASI compatibility layer
  3. Javy — Compile JavaScript to WASM via QuickJS
  4. IR Injector — Add Rotifer custom sections

The output gene.ir.wasm is a self-contained WASM module with embedded metadata.

After compilation, your gene’s fidelity upgrades from Wrapped to Native.

Terminal window
rotifer arena submit my-translator

The Arena:

  1. Runs L2 sandbox tests (automatic)
  2. Computes fitness score F(g) and safety score V(g)
  3. Ranks your gene against others in the same domain
  4. Records the entry in the local Arena database

Check rankings:

Terminal window
rotifer arena list -d text.translate

Share your gene with other developers:

Terminal window
rotifer login # Authenticate with GitHub
rotifer publish my-translator # Upload to cloud registry

Others can now find and use your gene:

Terminal window
# Another developer
rotifer search "translator"
rotifer install <your-gene-id>
Terminal window
rotifer arena submit my-translator --cloud
rotifer arena list --cloud -d text.translate

Use dot-separated hierarchical names:

search.web # Web search
search.code # Code search
file.read # File reading
file.write # File writing
code.format # Code formatting
code.generate # Code generation
text.translate # Translation
text.summarize # Summarization
data.transform # Data transformation
  • Use JSON Schema draft 2020-12
  • Always specify required fields
  • Add description to every property
  • Use minimum/maximum for numeric constraints
  • Prefer specific types over any

Throw typed errors from express():

export async function express(input: { query: string }) {
if (!input.query?.trim()) {
throw new Error("INVALID_INPUT: query must be a non-empty string");
}
try {
const result = await performSearch(input.query);
return { results: result };
} catch (err) {
throw new Error(`EXECUTION_FAILURE: ${err.message}`);
}
}
  • Minimize cold start time — avoid heavy imports at module level
  • Cache expensive resources (API clients, compiled patterns)
  • Return early on validation failures
  • Use streaming for large outputs when possible