Named Functions

TurboWarp extension · User guide

Write it once. Call it by name.

Named Functions turns a script into a function with a name, a description, and a JSON Schema for its arguments. Any sprite can call it and get a value back—wait for the result, or start several calls and collect them later. Mark a function as a tool and other extensions, such as AI tool calling, can use it too.

Why use it

Custom blocks stop at the sprite boundary

A custom block belongs to one sprite and cannot return a value. Broadcasts reach every sprite but carry no arguments and no result. Named Functions fills the gap: a callable unit that any script can reach, with checked inputs and a real return value.

Share logic across sprites

Keep scoring, inventory, or dialogue rules in one place. Every sprite and the Stage call the same function instead of copying scripts.

Get structured results

Pass JSON in and get JSON out. A function can return a number, text, a list, or an object, and arguments are checked before the script starts.

Offer tools to AI

Functions exported as tools are listed in the OpenAI function-calling shape, so an AI extension can see what your project can do and call it.

Quick start

Ready in four steps

Functions are found by reading define function hats, so there is nothing to register at startup. Place the hat, write the body, and call it.

  1. Load the extension

    Load Named Functions as a custom extension with Run extension without sandbox enabled. It needs the VM runtime to start function scripts.

  2. Place a define hat

    Drag define function into any sprite. Type the name, description, and args schema directly into the hat—these fields must be literal text.

  3. Write the body

    Read inputs with function argument and finish with return. A script that ends without return reports null.

  4. Call it anywhere

    Use call function with JSON arguments from any sprite. The block waits for the function and reports its return value.

What happens during one call

Invalid arguments fail before the script starts, and last function error names the field that did not match.

Extension URL

Use the version-pinned build: @kubohiroya/turbowarp-named-functions@0.1.2. Load extensions only from sources you trust.

Examples

Three ways to call a function

Wait for one result, start several calls and collect them together, or let another program decide which function to call.

↩ Call and wait

Compute a damage value

define function damage args schema {"power":number,"armor":number}
return (power) − (armor)
change hp by 0 − (call function damage with {"power":12,"armor":4})

call function takes at least one frame, because the function runs as its own script.

⇉ Start, then await

Run calls side by side

set p1 to start function add with {"a":1,"b":2}
set p2 to start function add with {"a":3,"b":4}
say await all [p1, p2]

start function reports a promise reference such as {"$promise":"p_1"}. await all reports [3,7]; a failed call becomes {"$error": message}.

◇ Export as tool

Let an AI read the score

define function get_score description Reports the player’s score. export as tool
return (score)

A tool needs a description—it is what the model reads. Treat tool arguments as untrusted input, even though they match the schema.

Schemas

Say what goes in—and what comes out

The args schema is a JSON Schema object, checked by a small interpreter—no code is generated—before the function runs. Fill in returns schema to check the return value as well, or leave it blank to skip return checks.

An args schema

{
  "type": "object",
  "properties": {
    "name":  {"type": "string", "minLength": 1},
    "score": {"type": "number", "minimum": 0},
    "tags":  {"type": "array", "items": {"type": "string"}}
  },
  "required": ["name", "score"],
  "additionalProperties": false
}

Supported keywords

type, properties, required, additionalProperties (true or false), items, enum, const, minimum, maximum, minLength, maxLength, minItems, and maxItems.

  • Other keywords are allowed but add no checks.
  • The args schema must have "type": "object".
  • A malformed schema leaves the function undefined, so function [NAME] defined? reports false.
  • A failed check names the JSON path, such as $.score must be >= 0.

Behavior

Timing, limits, and errors

Functions are scripts, not custom blocks. That makes them shareable and asynchronous, and it also sets a few rules worth knowing before you build on them.

SituationWhat happens
Each callTakes at least one frame. Use custom blocks for tight loops.
Several calls to one functionRun one at a time, in order. Different functions run concurrently.
A function calls itself, directly or indirectlyFails with Reentrant call: a -> b -> a instead of waiting forever. Use a custom block for recursion.
A function runs longer than 30 secondsThe call fails with a timeout.
More than 8 started calls at onceFurther start function calls wait for a free slot.
The project stopsRunning calls fail and promise references are cleared.
Two hats with the same name, or non-literal hat fieldsThe function is not defined; last function error explains why.

Application integration

Bundle the same functions into your own extension

The Composition API gives another extension the same registry and dispatcher without registering the standalone blocks. The consumer owns its own define function hat opcode and forwards three blocks to it.

Create and call

import {createNamedFunctions} from
  '@kubohiroya/turbowarp-named-functions/composition';

const functions = createNamedFunctions({
  runtime: Scratch.vm.runtime,
  functionHatOpcode: 'myextension_defineFunction'
});

const tools = functions.tools();
const score = await functions.call(
  'get_score', {}, {exportedOnly: true});

functions.release();

What the consumer forwards

  • matchHat(NAME, thread) from its define function hat.
  • argumentsFor(thread) from its argument reporter.
  • returnFrom(thread, value) from its return block.
  • tools() lists exported functions; call(…, {exportedOnly: true}) refuses anything not exported.
  • cancelAll(reason) fails pending calls; release() also detaches runtime listeners.

Block reference

Eleven blocks in three groups

Every block, argument, and default value is listed in the complete block reference below.

Define

  • define function … declares a name, description, args schema, optional returns schema, and export mode.
  • function argument [PATH] reads one argument, such as items.0.name.
  • function arguments JSON reports every argument as JSON text.
  • return [VALUE] ends the function with a value.

Call

  • call function [NAME] with [ARGS] waits and reports the result.
  • start function [NAME] with [ARGS] reports a promise reference immediately.
  • await [PROMISE] waits for one started call.
  • await all [PROMISES] waits for a JSON array of started calls.

Inspect

  • [PROMISE] settled? checks a started call without waiting.
  • function [NAME] defined? checks that a valid hat exists.
  • last function error explains the most recent failure.

Troubleshooting

If a call fails

Check last function error first. Open each item for the most common cause and the shortest fix.

function [NAME] defined? reports false

NAME, DESCRIPTION, SCHEMA, and a non-empty RETURNS must be typed into the hat, not built from reporters. The name must be 1–64 letters, digits, _, or -, the schema must be valid JSON with "type": "object", and no other hat may use the same name.

The call fails before the function starts

ARGS must be JSON text that matches the args schema. {"a":"1"} passes a string, not a number. Build ARGS with JSON blocks or a join that produces valid JSON.

A function that calls itself reports “Reentrant call”

Recursion through named functions is rejected on purpose, because the inner call would wait for the outer one forever. Put recursive logic in a custom block and call that from the function.

The result is empty

The function script ended without reaching return, so the result is null. Check every branch. If RETURNS is set, a missing return is checked as null and may fail.

A loop that calls a function is slow

Each call takes at least one frame. Move the inner work into a custom block, or start the calls with start function and collect them with await all.

An AI extension cannot see my function

Set export as to tool and fill in DESCRIPTION. A tool without a description is not defined.

Named Functions: complete block reference

All 11 blocks are documented below, including compatibility blocks and blocks available through optional features. Select a block to read its behavior, arguments, default values, and menu choices. Each block has a permanent link.

define function [NAME] description [DESCRIPTION] args schema [SCHEMA] returns schema [RETURNS] export as [EXPORT]

Defines a named function. NAME, DESCRIPTION, and SCHEMA must be literal text. RETURNS is an optional JSON Schema for the return value; leave it blank to disable return validation.

Block type: HAT. Opcode: defineFunction. Permanent link

ArgumentTypeDefault valueMenu choices
NAMESTRINGadd
DESCRIPTIONSTRINGAdds two numbers.
SCHEMASTRING{"type":"object","properties":{"a":{"type":"number"},"b":{"type":"number"}},"required":["a","b"]}
RETURNSSTRING
EXPORTSTRINGnone
  • none
  • tool

In the fixed-input editor, EXPORT is chosen from none or tool. The editor changes only this stored value; it does not run the function or the hat, and it leaves NAME, DESCRIPTION, SCHEMA, and RETURNS unchanged. The GUI Dialogs and FixedInputs startup flags are OFF by default; enable both and reload to use the form. Unchanged raw values are not rewritten, and connected reporters are not evaluated.

function argument [PATH]

Inside a function, reports the argument at a dotted path such as a or items.0.name.

Block type: REPORTER. Opcode: functionArgument. Permanent link

ArgumentTypeDefault valueMenu choices
PATHSTRINGa

function arguments JSON

Inside a function, reports all arguments as JSON text.

Block type: REPORTER. Opcode: functionArgumentsJson. Permanent link

This block has no arguments.

return [VALUE]

Inside a function, returns a value and ends the script. JSON text is returned as JSON; other text is returned as a string.

Block type: COMMAND. Opcode: returnValue. Permanent link

ArgumentTypeDefault valueMenu choices
VALUESTRING0

call function [NAME] with [ARGS]

Calls a function and waits for its result. ARGS is JSON text and is checked against the args schema. Takes at least one frame.

Block type: REPORTER. Opcode: callFunction. Permanent link

ArgumentTypeDefault valueMenu choices
NAMESTRINGadd
ARGSSTRING{"a":1,"b":2}

start function [NAME] with [ARGS]

Starts a function without waiting and reports a promise reference as JSON text.

Block type: REPORTER. Opcode: startFunction. Permanent link

ArgumentTypeDefault valueMenu choices
NAMESTRINGadd
ARGSSTRING{"a":1,"b":2}

await [PROMISE]

Waits for a promise reference from start function and reports its result.

Block type: REPORTER. Opcode: awaitResult. Permanent link

ArgumentTypeDefault valueMenu choices
PROMISESTRING{"$promise":"p_1"}

await all [PROMISES]

Waits for a JSON array of promise references and reports a JSON array of results. Failed calls become {"$error": message}.

Block type: REPORTER. Opcode: awaitAll. Permanent link

ArgumentTypeDefault valueMenu choices
PROMISESSTRING[]

[PROMISE] settled?

Reports whether a started function has finished, without waiting.

Block type: BOOLEAN. Opcode: isSettled. Permanent link

ArgumentTypeDefault valueMenu choices
PROMISESTRING{"$promise":"p_1"}

function [NAME] defined?

Reports whether a valid define function hat with this name exists.

Block type: BOOLEAN. Opcode: isDefined. Permanent link

ArgumentTypeDefault valueMenu choices
NAMESTRINGadd

last function error

Reports the most recent function error, or an empty string.

Block type: REPORTER. Opcode: lastError. Permanent link

This block has no arguments.

Repository guide and examples