Workflows
A workflow engine you embed, extend and hand to an agent.
Draw the steps once and they run the same way every time. A model decides only inside its own node. Build flows in the visual editor, as JSON, or let an agent build them from the chat.
Node types and configs follow the kit's schemas; names are illustrative.
Every step is a node kind.
- Triggers
By hand or from the workflow_run tool, from a webhook with a token, or on a cron.
trigger.manual · trigger.webhook · trigger.schedule - Calls
Any HTTP API, a model with a schema, an agent, a registered tool, or a linked account.
http · llm · agent · tool · connection.* - Logic
Branch, loop over a list, store values and name the result.
if · switch · forEach · set · output - Code
JavaScript in a QuickJS sandbox in a worker thread, with time and memory limits.
code - People
Pause the run until someone approves, then resume where it stopped.
approve - Your own
A schema, its ports and one function; the builder and validation pick it up.
defineNodeKind
Three places to run it.
src/run.ts
import { coreNodeKinds, createWorkflowRuntime } from '@pilotoo/workflow';
const runtime = createWorkflowRuntime({
kinds: coreNodeKinds,
checkpointer,
ports: { fetch },
onEvent: (event) => console.log(event.type),
});
const outcome = await runtime.start({
workflow,
runId: 'run-1',
threadId: 'thread-1',
input: { userId: 7 },
});Your own nodes, next to the built-in ones.
Register a kind on the server and it appears in the builder palette, validated like the rest.
Writing a node kindexport const slugify = defineNodeKind({
type: 'slugify',
category: 'transform',
label: 'Slugify',
config: z.object({ text: z.string() }),
ports: { inputs: ['in'], outputs: ['out'] },
execute: (_context, config) => ({
output: config.text.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
}),
});Wire it to the other blocks.
Turn on a block to see what a workflow gets from it.