seq (Sequence)
The root atom for all agent programs. Executes steps in order.
- Stops on
return(whenctx.outputis set) - Stops on error (monadic error flow)
- Cost: 0.1
// AsyncJS compiles to seq at the top level
const x = 1
const y = 2
return { sum: x + y }
if (Conditional)
Conditional branching based on expression evaluation.
if (count > 0) {
console.log("Has items")
} else {
console.log("Empty")
}
while (Loop)
Repeats body while condition is truthy. Consumes fuel each iteration.
let i = 0
while (i < 10) {
console.log(i)
i = i + 1
}
Note: No break/continue. Use condition variables instead.
return
Ends execution and returns values from state. The schema defines which state variables to include in the output.
const result = compute()
return { result } // Returns { result: <computed value> }
try/catch
Error handling with monadic error flow. When an error occurs, subsequent steps are skipped until caught.
try {
const data = fetch(url)
processData(data)
} catch (err) {
console.warn("Failed: " + err)
return { error: err }
}
The catch block receives:
err(or custom name): error messageerrorOp: the atom that failed
for...of / map
Transforms each item in an array. The result variable in each iteration
becomes the new item value.
const doubled = items.map(x => x * 2)
// Or with for...of:
const results = []
for (const item of items) {
results.push(process(item))
}
filter
Keeps items that match a condition.
const adults = users.filter(u => u.age >= 18)
reduce
Accumulates a single value from an array.
const sum = numbers.reduce((acc, n) => acc + n, 0)
find
Returns first item matching condition, or null.
const admin = users.find(u => u.role === "admin")
fetch
HTTP requests. Requires fetch capability or uses global fetch with SSRF protection.
const data = fetch("https://api.example.com/data")
const posted = fetch("https://api.example.com/items", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: { name: "New Item" }
})
Response types: "json" (default for JSON content-type), "text", "dataUrl" (for images)
Security:
- Requires
ctx.context.allowedFetchDomainsallowlist OR restricts to localhost - Automatically adds
X-Agent-Depthheader to prevent recursive agent loops - Custom fetch capability can override all restrictions
storeGet / storeSet
Persistent key-value storage. Requires store capability.
// Save data
storeSet("user:123", { name: "Alice", prefs: {} })
// Retrieve later
const user = storeGet("user:123")
Warning: Default in-memory store is not suitable for production.
storeQueryWhere (predicate pushdown)
Send the predicate to the data instead of dragging rows to the code.
predicate is a canonical verified predicate — build it at author/transpile time
with canonicalizePredicate() from tjs-lang/lang, then pass the resulting object.
Because it is verified pure and canonical, it is safe to ship, cheap to compare, and
carries a stable key the store can cache on (two spellings of the same predicate hit
the same cache entry).
// canonical form produced outside the VM; the VM forwards it as data
const rows = storeQueryWhere({ collection: 'users', predicate: adultPredicate })
Requires a store that implements queryPredicate. If it doesn't, this fails with a
message pointing at the ordinary storeQuery + filter path rather than silently
returning everything — a filter that silently doesn't filter is an authorization bug.
llmPredict
Call language model. Requires llm capability with predict method.
const response = llmPredict("Summarize this: " + text)
// With options
const structured = llmPredict(prompt, {
model: "gpt-4",
temperature: 0.7,
responseFormat: { type: "json_object" }
})
transpileCode (Code to AST)
Transpiles AsyncJS code to an AST without executing it. Useful for generating agents to send to other services via fetch.
// Generate an agent and send it to a worker
let code = llmPredict({ prompt: 'Write an AsyncJS data processor' })
let ast = transpileCode({ code })
let result = httpFetch({
url: 'https://worker.example.com/run',
method: 'POST',
body: JSON.stringify({ ast, args: { data: myData } })
})
Security: Only available when the code.transpile capability is provided.
runCode (Dynamic Code Execution)
Transpiles and executes AsyncJS code at runtime. The generated code runs in the same context, sharing fuel budget, capabilities, and trace.
This enables agents to write and execute code to solve problems.
// Agent writes code to solve a problem
let code = llmPredict({ prompt: 'Write AsyncJS to calculate fibonacci(10)' })
let result = runCode({ code, args: {} })
return { answer: result }
The code must be a valid AsyncJS function. The function's return value becomes the result of runCode.
Security: Only available when the code.transpile capability is provided.
The transpiled code runs with the same permissions as the parent.
Recursion depth is limited to prevent stack overflow.
memoize
In-memory caching within a single execution. Same key returns cached result.
// Expensive computation cached by key
const result = memoize("expensive-" + id, () => {
return heavyComputation(data)
})
cache
Persistent caching across executions using store capability.
// Cache API result for 1 hour (3600000 ms)
const weather = cache("weather-" + city, 3600000, () => {
return fetch("https://api.weather.com/" + city)
})
console.log / console.warn / console.error
Logging utilities that integrate with trace and error flow.
console.log("Debug info: " + value) // Adds to trace
console.warn("Potential issue") // Adds to trace + warnings summary
console.error("Fatal: " + msg) // Triggers monadic error flow
log: trace only (no side effects)warn: trace + appears inresult.warningserror: stops execution, setsresult.error