Skip to content

Commands and tool schemas

Commands are ordinary typed functions.

This configuration fragment assumes the source accepts RESET and RENAME_PRESET.

Command configuration (fragment)
commands: ({ source: actor }) => ({
reset: () => actor.send({ type: 'RESET' }),
renamePreset: (label: string) => actor.send({ type: 'RENAME_PRESET', label }),
});

Direct calls retain their arguments, receiver, arity, return value, thrown value, and original promise.

Retained command references reject after owning-core disposal.

State and command names must be disjoint, including dynamic keys.

Function-valued states remain states; they are not commands merely because they are callable.

After real command binding, core.get("commands") returns names with { input: null }.

It never returns executable functions.

Before binding an existing commands callback it returns null; without a callback it returns {}.

These are unknown and known-empty catalogues, respectively.

core.get("schema") is immutable JSON-safe catalogue data, not a live snapshot or a formal JSON Schema document.

It does not infer payload validation from TypeScript types or sample values.

See Headless runtime.

Keep descriptions and validation at the application/tool boundary.

Define these schemas when exposing commands as tools.

These examples validate numbers, strings, enumerations, and nested objects and arrays:

import { buildManifest, resolveCall } from 'ignite-element/tools';
const toolSchema = {
commands: {
setLimit: {
description: 'Set maximum count.',
input: { type: 'number', minimum: 3, maximum: 12 },
},
renamePreset: {
description: 'Rename the saved preset label.',
input: { type: 'string', minLength: 1, maxLength: 32 },
},
configureAlerts: {
description: 'Update alert routing rules.',
input: {
type: 'object',
properties: {
enabled: { type: 'boolean', default: true },
priority: { type: 'string', enum: ['low', 'high'], default: 'low' },
channels: { type: 'array', items: { type: 'string' }, minItems: 1 },
},
required: ['enabled', 'priority', 'channels'],
additionalProperties: false,
},
},
},
};
const manifest = buildManifest(toolSchema);
const valid = resolveCall(manifest, 'setLimit', 6);
const invalid = resolveCall(manifest, 'setLimit', 99);

These definitions belong to the application; they are not automatically derived or attached to the core catalogue.

Do not fabricate an empty-object input schema for an unknown function signature.

Supply an actual contract before offering a command to a model.

igniteTools(core, dialect, { schema: toolSchema, canExecute }) accepts the same explicit definitions and an independently supplied availability predicate.

Missing required input schemas cause tool construction to fail before any source command executes.

Scalar provider wrapping and input validation remain in the tools boundary.

Project source-native capability into states, such as canSubmit or a commandAvailability map.

A tool schema may explicitly set gated: true and provide canExecute(name) in tool options.

The predicate reads the current application projection; it is not a method on the core.

Availability is a hint, not authorization.

Keep guards, validation and asynchronous work in the source/application.

Rebuild a provider’s offered tool list when the application needs a fresh availability view; invocation still rechecks its supplied predicate.

execute({ command, input }) passes exactly one positional payload, including undefined when omitted.

Arrays are not spread.

Commands requiring multiple positional arguments remain directly callable but are not advertised as safe serialized calls by the strict types.

Execution awaits the callback and queued observation window, not all downstream work.