Skip to content
Pilotoo
v0.1

Workflows

A workflow is a graph you define. Each node is a step, such as an HTTP call, a model call, a tool call, a condition or an approval. Edges wire one node’s output to the next node’s input. The graph fixes the order, the branching and the data. When a model is involved, it decides only inside its own node.

Use a workflow when you want the same steps in the same order every time. Use an agent when you want a model to choose which tools to call.

This workflow receives a support message, asks a model whether it is urgent, and pages the on-call person only if it is. It uses a webhook trigger, an llm node, an if node and a tool node.

triage.json
{
"name": "Triage support message",
"nodes": [
{ "id": "start", "type": "trigger.webhook", "config": {} },
{
"id": "classify",
"type": "llm",
"config": {
"profileId": "default",
"system": "You triage support messages.",
"prompt": "Is this message urgent? Message: {{ $input.text }}",
"schema": {
"type": "object",
"properties": { "urgent": { "type": "boolean" }, "summary": { "type": "string" } },
"required": ["urgent", "summary"]
}
}
},
{
"id": "check",
"type": "if",
"config": { "conditions": [{ "left": "{{ $node.classify.urgent }}", "operator": "truthy" }] }
},
{ "id": "page", "type": "tool", "config": { "tool": "notify_oncall", "input": { "message": "{{ $node.classify.summary }}" } } },
{ "id": "paged", "type": "output", "config": { "name": "result", "value": "Paged on-call" } },
{ "id": "skipped", "type": "output", "config": { "name": "result", "value": "Not urgent" } }
],
"edges": [
{ "from": { "node": "start", "port": "out" }, "to": { "node": "classify", "port": "in" } },
{ "from": { "node": "classify", "port": "out" }, "to": { "node": "check", "port": "in" } },
{ "from": { "node": "check", "port": "true" }, "to": { "node": "page", "port": "in" } },
{ "from": { "node": "page", "port": "out" }, "to": { "node": "paged", "port": "in" } },
{ "from": { "node": "check", "port": "false" }, "to": { "node": "skipped", "port": "in" } }
]
}

profileId names a model profile on your server, and notify_oncall is a tool you registered (see Tools). The workflow reads the run input with {{ $input.text }} and a node’s output with {{ $node.classify.urgent }}.

Create the workflow and start a run:

Terminal window
curl -X POST $API/workflows -H 'content-type: application/json' -d @triage.json
# 201 { "id": "wf_...", ... }
curl -X POST $API/workflows/$ID/runs -H 'content-type: application/json' \
-d '{"input":{"text":"Checkout is down for every customer"}}'
# 201 { "id": "run_...", "status": "running", ... }
curl $API/workflows/$ID/runs/$RUN_ID
# { "status": "finished", "output": { "result": "Paged on-call" }, ... }

The server mints the workflow id, so the definition you post has none. Add your usual authorization header to each call.

apps/api/src/app.module.ts
PilotooModule.forRoot({
workflowSandbox: sandbox, // only if you use `code` nodes
workflowTools: true, // lets agents list and run workflows
});
.env
WORKFLOW_ROLES=member,owner

All options are in Server integration.