Slot reference
Every slot in Magic Cloud and Hyperlambda, 406 in total, with its arguments and return value. Start with the core keywords, such as [if] and [for-each], or pick a namespace. Every slot has a page of its own, with its complete JSON declaration. How this reference is built is explained further down.
Slots by namespace
- core keywords - 89 slots
- auth.* - 7 slots
- cache.* - 6 slots
- config.* - 4 slots
- console.* - 1 slot
- crypto.* - 24 slots
- data.* - 12 slots
- date.* - 6 slots
- endpoints.* - 1 slot
- execution.* - 4 slots
- git.* - 13 slots
- github.* - 3 slots
- guid.* - 1 slot
- http.* - 5 slots
- hyperlambda.* - 1 slot
- image.* - 6 slots
- io.* - 29 slots
- log.* - 9 slots
- mail.* - 2 slots
- math.* - 18 slots
- mime.* - 4 slots
- mssql.* - 12 slots
- mysql.* - 11 slots
- odbc.* - 7 slots
- openai.* - 2 slots
- pgsql.* - 11 slots
- puppeteer.* - 15 slots
- python.* - 1 slot
- request.* - 9 slots
- response.* - 3 slots
- server.* - 1 slot
- slot.* - 2 slots
- slots.* - 5 slots
- sockets.* - 7 slots
- sql.* - 4 slots
- sqlite.* - 14 slots
- strings.* - 26 slots
- system.* - 9 slots
- tasks.* - 9 slots
- time.* - 2 slots
- timezone.* - 1 slot
- validators.* - 10 slots
This reference was not written. It was asked for.
Every page in this section is generated, and what it is generated from is not the source code but the running system. Each slot in Magic Cloud carries its own name, description, arguments and return value as metadata, and Hyperlambda can read that metadata at runtime. Once a week a GitHub Actions workflow asks for it, receives 406 slots, and renders the pages you are reading. Nobody parses source files, scrapes anything or keeps a second copy that can go stale.
Why this is possible: homoiconicity
Hyperlambda is homoiconic. A program is a tree of nodes, and a tree of nodes is also the data structure the program works on. A slot is an ordinary node, and asking about slots is an ordinary function call: [vocabulary] lists their names, [slot.description] returns what one of them does, [slot.signature] returns its contract as a tree, and [lambda2hyper] writes any tree back as Hyperlambda text. Meta programming is not a library you import here, it is what the language does by default. This documentation is a Hyperlambda program whose input is the definition of Hyperlambda itself.
The code that produced this reference
This is the complete Hyperlambda file behind the endpoint the pipeline calls. This is dogfooding in its purest form: the language documents itself with its own code.
// Executable Hyperlambda file that lists every slot registered in the system and, for each slot, returns its name, its description and its signature. Returns a JSON array of objects, each with fields name (string), description (string) and signature (the slot's signature as nodes, so it converts to nested JSON). Open to everybody, since it only reads metadata that is public in the open source code and runs no code supplied by the caller. Callers are throttled to 10 requests per 60 seconds per IP address, and everybody together to 60 requests per 60 seconds.
.arguments
execution.throttle.create:docs-slots.ip
limit:int:10
window:int:60
per:ip
execution.throttle.create:docs-slots.global
limit:int:60
window:int:60
per:global
execution.throttle:docs-slots.ip
execution.throttle:docs-slots.global
vocabulary
.result
for-each:x:@vocabulary/*
slot.description:x:@.dp/#
slot.signature:x:@.dp/#
/*
* The signature is returned as nodes, which Magic converts to nested JSON. A constraint is
* named after its kind and can occur more than once, which JSON cannot hold as a key, so each
* constraint, at any depth, becomes an unnamed node carrying its kind as a child.
*/
for-each:x:@slot.signature/**/constraints/*
get-name:x:@.dp/#
unwrap:x:+/*/*
add:x:@.dp/#
.
kind:x:@get-name
set-name:x:@.dp/#
.:.
.entry
.
name:x:@.dp/#
description:x:@slot.description
signature
unwrap:x:@.entry/*/*
add:x:@.entry/*/*/signature
get-nodes:x:@slot.signature/*
add:x:@.result
get-nodes:x:@.entry/*
return-nodes:x:@.result/*
It begins with two throttles, one per IP address and one for everybody together, and has no authentication, since there is nothing to protect: it reads metadata that is public in the open source code and runs nothing a caller sends. Everything after that is slots, and nothing else. It lists the compiled slots, reads the description and the signature of each, and returns the signature as nodes. Magic turns nodes into JSON by itself, since a tree of nodes already is a tree of JSON objects, so there is no serialising step, no text format to agree on and nothing to parse. One detail shows how it works. A constraint is named after its kind and can occur more than once, which a JSON object cannot hold as a key, so the loop in the middle renames every constraint, at any depth, to an unnamed node with its kind as a child, using the ** selector to reach them all in one expression. Magic then writes them as a list. A Python script renders the result as markdown.
Get the whole reference yourself
The endpoint above is public. There is no account, no key and no secret. To protect the server it is throttled to 10 requests per 60 seconds per IP address, and to 60 per 60 seconds for everybody together, and beyond that it answers 429. The answer is about 460 KB, so keep a copy rather than asking again.
curl -s https://hyperlambda.dev/magic/modules/docs/slots
It returns a JSON array with one object per slot, with the fields name, description and signature. The signature is the contract of the slot as nested JSON: input is the value the slot takes, children are its arguments, constraints are the rules between them, scope says where it can be used, and output is what it returns. Arguments without a name, because they are positional, come as a list. With jq you can ask it questions.
List every slot name
curl -s https://hyperlambda.dev/magic/modules/docs/slots | jq -r '.[].name'
Get the description of one slot
curl -s https://hyperlambda.dev/magic/modules/docs/slots | jq -r '.[] | select(.name == "strings.concat") | .description'
Get the full signature of one slot
curl -s https://hyperlambda.dev/magic/modules/docs/slots | jq '.[] | select(.name == "data.read") | .signature'
List the arguments of a slot
curl -s https://hyperlambda.dev/magic/modules/docs/slots | jq -r '.[] | select(.name == "data.create") | .signature.children | keys[]'
List only the required arguments of a slot
curl -s https://hyperlambda.dev/magic/modules/docs/slots | jq -r '.[] | select(.name == "data.create") | .signature.children | to_entries[] | select(.value.required == true) | .key'
Find the slots whose description mentions something
curl -s https://hyperlambda.dev/magic/modules/docs/slots | jq -r '.[] | select((.description // "") | test("rows")) | .name'
The public sandbox below sees fewer slots than this endpoint. It runs your code, so it can only describe the 53 slots it is itself allowed to call. A slot can only be described by code that is allowed to call it, so a sandbox that described everything could also run everything. Use the endpoint for the whole language, and the sandbox to experiment.
The public sandbox
Anybody can send Hyperlambda to POST https://hyperlambda.dev/magic/modules/docs/playground, with no account and no key. It is rate limited to 30 requests per 60 seconds per IP address, stops after 20 seconds, and accepts up to 4000 characters. Every slot your code uses is checked against the whitelist before anything runs, so code that touches files, databases, the network or configuration is rejected rather than executed. Send {"describe": true} to get the exact vocabulary, limits and timeout without running anything. AI agents can find it in /.well-known/hyperlambda-agent, and it is yours to experiment with.
Save any example below as example.hl and send it like this.
jq -Rs '{hyperlambda: .}' example.hl | curl -s https://hyperlambda.dev/magic/modules/docs/playground \
-H "Content-Type: application/json" -d @-
List the slot names
[vocabulary] returns the slots you are allowed to see. With a prefix it filters, so vocabulary:strings. returns only the string slots.
vocabulary:strings.
return-nodes:x:@vocabulary/*
Get one description
slot.description:strings.concat
return-value:x:@slot.description
Returns Concatenates strings.
Get every description
The same loop the full reference uses, without the signature.
vocabulary
.result
for-each:x:@vocabulary/*
slot.description:x:@.dp/#
.entry
.
name:x:@.dp/#
description:x:@slot.description
unwrap:x:@.entry/*/*
add:x:@.result
get-nodes:x:@.entry/*
return-nodes:x:@.result/*
Get one signature as Hyperlambda
[slot.signature] returns a tree, and [lambda2hyper] writes any tree back as Hyperlambda text. [lambda2json] would give you JSON instead.
slot.signature:convert
lambda2hyper:x:@slot.signature/*
return-value:x:@lambda2hyper
Get only the arguments of a slot
slot.signature:convert
.result
for-each:x:@slot.signature/*/children/*
get-name:x:@.dp/#
.entry
.
name:x:@get-name
type:x:@.dp/#/*/type
required:x:@.dp/#/*/required
description:x:@.dp/#/*/description
unwrap:x:@.entry/*/*
add:x:@.result
get-nodes:x:@.entry/*
return-nodes:x:@.result/*
Returns [{"name": "type", "type": "string", "required": true, "description": "Target Hyperlambda type name"}].
Get only the required arguments
slot.signature:convert
.result
for-each:x:@slot.signature/*/children/*
if
eq:x:@.dp/#/*/required
.:bool:true
.lambda
get-name:x:@.dp/#
unwrap:x:+/*/*
add:x:@.result
.
.:x:@get-name
return-nodes:x:@.result/*
Returns ["type"].
This is the complete source of the sandbox endpoint, generated by the Sandbox API generator in Magic Cloud. The policy near the top is the whole whitelist.
Show the entire sandbox endpoint
/*
* Sandboxed Hyperlambda endpoint, generated by the Sandbox API generator.
*
* Executes caller-supplied Hyperlambda passed in [hyperlambda].
*
* Roles:
*
* - *****: Can introspect every compiled slot of the system - its name, description and full signature - and transform the result with pure tree, string and math functions. Cannot touch files, databases, the network, configuration or any other part of the server.
*
* The code is checked - every referenced function must exist on this server - then
* executed inside a whitelisted sandbox whose vocabulary and rate limit are chosen
* from the caller's roles. Always returns the code together with a [state] describing
* what happened, and a [reason] whenever the runtime refused the code or it failed.
*
* To discover the exact capability surface available to you, call with [describe] set
* to true instead of [hyperlambda]/[instruction] - it returns your visible vocabulary,
* and the rate limit and timeout that apply to you, without executing anything or
* counting against the rate limit.
*
* States: described (a [describe] call), executed, rejected (a function or a pinned
* argument was not allowed), unknown-slot (a referenced function does not exist),
* invalid-invocation (a declared argument is misspelled or a mandatory value is absent),
* error (the code threw), timeout (execution exceeded the configured limit),
* generator-failed (no code came back from the Hyperlambda Generator).
*/
.arguments
// Hyperlambda to execute as-is inside the sandbox, at most [max-hyperlambda] characters.
hyperlambda:string
// When true, returns your visible vocabulary instead of executing [instruction]/[hyperlambda].
describe:bool
/*
* Policy - injected by the generator. [rules] are matched top down: a rule matches
* when its [role] is '*' or the caller belongs to it. The vocabulary is the union of
* every matching rule's [slots]. The rate limit and the timeout are each taken from
* the first matching rule that declares one, resolved independently, so a rule can
* override one, both, or neither. Rules are ordered most-access-first, and the '*'
* base rule sits last as the fallback for both.
*/
.policy
override-root:bool:false
return-code:bool:false
generator-url:"https://ainiro.io/magic/modules/hyperlambda-generator/chat"
throttle-prefix:sandbox-docs-playground-post
max-hyperlambda:int:4000
rules
.
role:*
slots
vocabulary
slot.description
slot.signature
lambda2hyper
hyper2lambda
lambda2json
json2lambda
for-each
if
else
else-if
eq
neq
mt
mte
lt
lte
not
and
or
exists
not-exists
null
not-null
add
get-nodes
get-value
get-name
set-value
set-name
remove-nodes
unwrap
sort
convert
return
return-nodes
return-value
strings.concat
strings.contains
strings.starts-with
strings.ends-with
strings.to-lower
strings.to-upper
strings.join
strings.split
strings.replace
strings.length
strings.substring
strings.trim
math.add
math.subtract
math.multiply
math.divide
description:Can introspect every compiled slot of the system - its name, description and full signature - and transform the result with pure tree, string and math functions. Cannot touch files, databases, the network, configuration or any other part of the server.
limit:int:30
window:int:60
timeout:int:20000
// Result fields.
.code
.state
.reason
.result
.execute:bool:false
// Resolving the caller's identity once, for the role checks below.
auth.ticket.get
// Whether the caller is root. Root is never rate limited, whatever the policy says.
.is-root:bool:false
if
auth.ticket.in-role:root
.lambda
set-value:x:@.is-root
.:bool:true
/*
* Whether the caller bypasses the sandbox entirely, running the code with the
* server's full vocabulary and no whitelist. Only when the policy enables it AND
* the caller is root.
*/
.bypass:bool:false
if
and
get-value:x:@.policy/*/override-root
get-value:x:@.is-root
.lambda
set-value:x:@.bypass
.:bool:true
/*
* Rate limit and timeout for sandboxed (non-root) callers - root has neither. Both are
* resolved independently by walking the rules top down and taking the first matching rule
* that declares that dimension, so an earlier rule can override one, both, or neither,
* with the '*' base rule as the fallback. Resolved ahead of [describe] so that it can tell
* the caller what it is subject to, and applied only once there is code to run.
*/
.tname
.tlimit:int:0
.twindow:int:0
.ttimeout
if
not
get-value:x:@.is-root
.lambda
// Rate limit - first matching rule that declares a [limit].
for-each:x:@.policy/*/rules/*
if
and
null:x:@.tname
not-null:x:@.dp/#/*/limit
or
eq:x:@.dp/#/*/role
.:*
auth.ticket.in-role:x:@.dp/#/*/role
.lambda
set-value:x:@.tname
strings.concat
get-value:x:@.policy/*/throttle-prefix
.:-
get-value:x:@.dp/#/*/role
set-value:x:@.tlimit
get-value:x:@.dp/#/*/limit
set-value:x:@.twindow
get-value:x:@.dp/#/*/window
// Timeout - first matching rule that declares a [timeout].
for-each:x:@.policy/*/rules/*
if
and
null:x:@.ttimeout
not-null:x:@.dp/#/*/timeout
or
eq:x:@.dp/#/*/role
.:*
auth.ticket.in-role:x:@.dp/#/*/role
.lambda
set-value:x:@.ttimeout
get-value:x:@.dp/#/*/timeout
/*
* A caller asking to [describe] the sandbox gets back its own visible vocabulary, and
* the rate limit and timeout it is subject to, instead of executing anything. This runs
* before [instruction]/[hyperlambda] are required, and before the rate limit is applied,
* so discovering what is allowed here never costs the caller's execution budget.
*
* The vocabulary is a list with one object per slot, carrying its [name] and its pinned
* [value] (null when unpinned). It cannot be a map keyed by slot name, since the same
* slot can be whitelisted more than once with different pinned values.
*/
if
get-value:x:@.arguments/*/describe
.lambda
.response
state:described
vocabulary
/*
* A bypassing caller (root, when the policy lets root skip the sandbox) runs with
* the server's full vocabulary, so that is what it is told - never just the base.
*/
if
get-value:x:@.bypass
.lambda
vocabulary
for-each:x:@vocabulary/*
.row
.
name
value
set-value:x:@.row/0/*/name
get-value:x:@.dp/#
add:x:@.response/*/vocabulary
get-nodes:x:@.row/*
add:x:@.response
.
root-bypass:bool:true
else
// Everybody else gets the union of every matching rule's slots.
.vocabulary
for-each:x:@.policy/*/rules/*
if
or
eq:x:@.dp/#/*/role
.:*
auth.ticket.in-role:x:@.dp/#/*/role
.lambda
add:x:@.vocabulary
get-nodes:x:@.dp/#/*/slots/*
for-each:x:@.vocabulary/*
.row
.
name
value
set-value:x:@.row/0/*/name
get-name:x:@.dp/#
set-value:x:@.row/0/*/value
get-value:x:@.dp/#
add:x:@.response/*/vocabulary
get-nodes:x:@.row/*
/*
* What the caller is subject to: invocations per [window] seconds, per IP, and the
* timeout in milliseconds. Either is left out when it does not apply, as for root.
*/
if
not-null:x:@.tname
.lambda
add:x:@.response
.
limit
window
set-value:x:@.response/*/limit
get-value:x:@.tlimit
set-value:x:@.response/*/window
get-value:x:@.twindow
if
not-null:x:@.ttimeout
.lambda
add:x:@.response
.
timeout
set-value:x:@.response/*/timeout
get-value:x:@.ttimeout
return-nodes:x:@.response/*
/*
* Applying the rate limit resolved above to sandboxed (non-root) callers. The throttle
* is keyed by the caller's IP; declaring an unchanged throttle keeps its counters, so
* the declaration can live in the endpoint itself.
*/
if
not-null:x:@.tname
.lambda
execution.throttle.create:x:@.tname
limit:x:@.tlimit
window:x:@.twindow
per:ip
execution.throttle:x:@.tname
/*
* Resolving the code to run. A non-empty [instruction] is natural language and is
* sent to the Hyperlambda Generator; otherwise the raw [hyperlambda] is used.
*/
if
and
not-null:x:@.arguments/*/instruction
neq:x:@.arguments/*/instruction
.:
.lambda
validators.string:x:@.arguments/*/instruction
min:int:3
max:int:500
http.post:x:@.policy/*/generator-url
convert:bool:true
timeout:int:60
payload
prompt:x:@.arguments/*/instruction
if
or
lt:x:@http.post
.:int:200
mte:x:@http.post
.:int:300
null:x:@http.post/*/content/*/result
.lambda
return
state:generator-failed
code
reason:The Hyperlambda Generator did not return any code.
result
set-value:x:@.code
get-value:x:@http.post/*/content/*/result
else-if
and
not-null:x:@.arguments/*/hyperlambda
neq:x:@.arguments/*/hyperlambda
.:
.lambda
// Rejecting oversized code up front, before anything is parsed or executed.
validators.string:x:@.arguments/*/hyperlambda
max:x:@.policy/*/max-hyperlambda
set-value:x:@.code
get-value:x:@.arguments/*/hyperlambda
else
throw:Provide either an instruction or Hyperlambda to execute
status:int:400
public:bool:true
/*
* Static sanity check before running anything: every referenced function must exist
* on this server, otherwise a hallucinated name would be treated as inert data.
*/
hyperlambda.verify-slots:x:@.code
if
not
get-value:x:@hyperlambda.verify-slots
.lambda
if
exists:x:@hyperlambda.verify-slots/invalid-invocation
.lambda
set-value:x:@.state
.:invalid-invocation
set-value:x:@.reason
strings.join:x:@hyperlambda.verify-slots/invalid-invocation
.:"; "
else
set-value:x:@.state
.:unknown-slot
set-value:x:@.reason
strings.concat
.:"The code references functions that do not exist on this server: "
strings.join:x:@hyperlambda.verify-slots/*
.:", "
else
set-value:x:@.execute
.:bool:true
// Bypass callers (root, when the policy allows it) run with full trust, no sandbox.
if
and
eq:x:@.execute
.:bool:true
eq:x:@.bypass
.:bool:true
.lambda
// No timeout - root is fully trusted with the server.
try
hyper2lambda:x:@.code
invoke:x:@hyper2lambda
set-value:x:@.state
.:executed
if
not-null:x:@invoke
.lambda
set-value:x:@.result
get-value:x:@invoke
else
add:x:@.result
get-nodes:x:@invoke/*
.catch
if
strings.contains:x:@.arguments/*/message
.:cancel
.lambda
set-value:x:@.state
.:timeout
else
set-value:x:@.state
.:error
set-value:x:@.reason
get-value:x:@.arguments/*/message
// Sandboxed callers run inside a whitelist whose vocabulary is chosen from their roles.
else-if
eq:x:@.execute
.:bool:true
.lambda
try
// Timeout resolved above; null for root, which is fully trusted with the server.
if
not-null:x:@.ttimeout
.lambda
execution.timeout:x:@.ttimeout
// Assembling the vocabulary as the union of every matching rule's slots.
.vocabulary
for-each:x:@.policy/*/rules/*
if
or
eq:x:@.dp/#/*/role
.:*
auth.ticket.in-role:x:@.dp/#/*/role
.lambda
add:x:@.vocabulary
get-nodes:x:@.dp/#/*/slots/*
// Parsing the code and populating the whitelist's body and vocabulary.
hyper2lambda:x:@.code
add:x:./*/whitelist/*/.lambda
get-nodes:x:@hyper2lambda/*
add:x:./*/whitelist/*/vocabulary
get-nodes:x:@.vocabulary/*
whitelist
vocabulary
.lambda
set-value:x:@.state
.:executed
if
not-null:x:@whitelist
.lambda
set-value:x:@.result
get-value:x:@whitelist
else
add:x:@.result
get-nodes:x:@whitelist/*
.catch
if
strings.contains:x:@.arguments/*/message
.:not allowed
.lambda
set-value:x:@.state
.:rejected
else-if
strings.contains:x:@.arguments/*/message
.:cancel
.lambda
set-value:x:@.state
.:timeout
else
set-value:x:@.state
.:error
set-value:x:@.reason
get-value:x:@.arguments/*/message
/*
* Returning the verdict and result to the caller, in order: [state], then [code] only
* when the policy asks for it, then [reason] only when there is one to explain, then
* [result] last.
*/
.response
state
set-value:x:@.response/*/state
get-value:x:@.state
// [code] - only when the policy enables returning it.
if
get-value:x:@.policy/*/return-code
.lambda
add:x:@.response
.
code
set-value:x:@.response/*/code
get-value:x:@.code
// [reason] - only when there is one; a clean run has nothing to explain.
if
not-null:x:@.reason
.lambda
add:x:@.response
.
reason
set-value:x:@.response/*/reason
get-value:x:@.reason
// [result] - last, and always present.
add:x:@.response
.
result
if
exists:x:@.result/*
.lambda
add:x:@.response/*/result
get-nodes:x:@.result/*
else
set-value:x:@.response/*/result
get-value:x:@.result
return-nodes:x:@.response/*
The pipeline
This is the complete GitHub Actions workflow. It needs no credentials, since the endpoint is public.
Show the entire workflow
# Keeps the plugin pages and the generated slot reference in sync with Magic Cloud.
#
# Two jobs in one run:
#
# * sync-plugin-docs.py copies each plugin's README.md from the Magic repository,
# https://github.com/polterguy/magic, to plugins/<plugin>/index.md, adapted for Jekyll.
# The README is the source of truth.
# * build-slot-reference.py asks a read-only Hyperlambda endpoint on hyperlambda.dev for
# every compiled slot and renders reference/slots/ from the answer. The endpoint is
# public and throttled, so no credentials are needed. Nothing is built, and no source
# code is parsed.
#
# It runs weekly and on demand, since the Magic repository is a separate project that
# cannot trigger this one without a token. Run it from the Actions tab after a release.
# The commit touches nothing outside plugins/ and reference/, and llms-full.yml rebuilds
# llms-full.txt afterwards because markdown changed.
name: Sync plugin docs and slot reference
on:
schedule:
- cron: '0 5 * * 1'
workflow_dispatch:
permissions:
contents: write
concurrency:
group: slot-reference
cancel-in-progress: true
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v4
with:
repository: polterguy/magic
path: magic
- uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Copy plugin READMEs
run: python3 .github/scripts/sync-plugin-docs.py magic
# Fails, and writes nothing, when the endpoint answers with too few slots.
- name: Generate slot reference
run: python3 .github/scripts/build-slot-reference.py
# Only commit when something actually changed.
- name: Commit if changed
run: |
git add plugins reference
if git diff --cached --quiet; then
echo "Nothing changed."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git commit -m "Sync plugin docs and slot reference"
git push
Frequently asked questions
How is this slot reference generated?
Automatically, from the running system. A GitHub Actions workflow asks a Hyperlambda endpoint on hyperlambda.dev for every compiled slot. The endpoint runs a short Hyperlambda program that lists the slots with [vocabulary] and reads each slot's description and signature with [slot.description] and [slot.signature]. A Python script renders the answer as the pages in this section.
Why is it generated instead of written by hand?
A slot describes itself in the same place its code lives, so the reference cannot drift away from the implementation. If an entry is thin or wrong, the fix is to improve the slot's own metadata, and the next run publishes it.
What is homoiconicity?
A language is homoiconic when its programs are stored in a data structure the language itself can read and change. In Hyperlambda a program is a tree of nodes, and so is the metadata that describes every slot, so a program can ask the system about itself and process the answer with the same tools it uses for any other data.
What is meta programming, and where is it here?
Meta programming is code that reads, generates or transforms code. This reference is a Hyperlambda program whose input is the definition of Hyperlambda itself: it lists the language's own slots, reads their contracts, and the result becomes the documentation.
Can I run my own Hyperlambda against the public sandbox?
Yes. POST your code as JSON to https://hyperlambda.dev/magic/modules/docs/playground, with no account or key. It is rate limited to 30 requests per 60 seconds per IP address, runs for at most 20 seconds, and accepts at most 4000 characters of code.
Is it safe to let anybody run code on that server?
The sandbox only runs code whose every slot is on a whitelist of 53 slots: introspection, tree handling, strings and arithmetic. Code that touches files, databases, the network, configuration or anything else is rejected before it runs, and every call is rate limited and time limited.
Can I get the whole reference as data?
Yes. GET https://hyperlambda.dev/magic/modules/docs/slots returns every compiled slot as a JSON array of objects with the fields name, description and signature, where the signature is the slot's contract as nested JSON. It needs no account or key. The answer is about 460 KB, so keep a copy rather than asking again.
Is it safe to leave that endpoint open?
It only reads metadata that is already public in the open source code, and it runs nothing that the caller sends. It is throttled to 10 requests per 60 seconds per IP address and 60 per 60 seconds for everybody together, and answers 429 beyond that.
Why does the sandbox show fewer slots than this reference?
The sandbox runs your code, so it can only describe the 53 slots it is itself allowed to call. A slot can only be described by code that is allowed to call it, so a sandbox that described everything could also run everything. Use the slot endpoint for the whole language and the sandbox to experiment.
How do I get only the descriptions, or only the arguments, of some slots?
Use [vocabulary] with a prefix to pick slots by name, [slot.description] for one description, and [slot.signature] for the input, arguments and output of one slot. The examples on this page show each of them, and all of them run in the public sandbox.
Does every slot have its own page?
Yes. Each slot has a page of its own, at /reference/slots/ followed by its namespace and its name, for example /reference/slots/strings/strings.concat/. It is small enough to read or index on its own, with its value, arguments, constraints, return value and complete JSON declaration. The namespace pages are indexes that link to them.
Where do I find the JSON declaration of a single slot?
At the bottom of the slot's page, in an expandable section with a copy button, and as a file next to the page called slot.json. For strings.concat that is /reference/slots/strings/strings.concat/slot.json.
How do I fix a missing or wrong description?
Change the metadata on the slot in the source code of Magic Cloud, its description or its signature. The next run of the pipeline publishes it here.
How often is the reference updated?
Once a week, and on demand from the Actions tab of the documentation repository.
What is Hyperlambda?
Hyperlambda is a declarative programming language where the source code is a tree of nodes rather than free-form text. It runs on Magic Cloud, an open source, MIT licensed platform that builds and runs an entire backend.
Is Hyperlambda Turing complete?
Yes. Slots such as [if], [for-each] and [while] give it branching and loops, which is what makes it Turing complete.
Why do I get error code 1010 when I call the endpoint from a script?
The server sits behind Cloudflare, which rejects requests that carry no User-Agent header, or the default one of an http library such as Python's urllib. Send any descriptive User-Agent and the request goes through.