Workflows
SkillProductivity"Orchestrate durable multi-step work with defineWorkflow and operate workflow instances. Use when a current task needs retries, sleeps, waiting for an external event, or the user asks to inspect, signal, or retry a workflow instance."
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Workflows skill
What this skill tells your AI
The instructions your AI receives, as published by rejot-dev/fragno in apps/backoffice/content/static/skills/workflows/SKILL.md and read by ahel’s review.
Use defineWorkflow for work that must survive retries, time, or an external continuation.
Authoring a workflow
-
Preflight. Apply the system guidance's closed-world preflight before calling
defineWorkflow. The workflow authoring declarations are already present in the system reference; read the provider declarations selected by that gate.Complete when the closed-world preflight passes. When it cannot pass, complete this branch by reporting the blocking requirement.
-
Author. Define the workflow directly at the top level. Inline definitions automatically start; retain the returned
instanceId. Save a workflow file only when the user asks for persistent automation behavior; use the Building Automations skill for that branch.defineWorkflow({ name: "approval-workflow" }, async (event, step) => { const request = await step.do("prepare-request", async () => { return { requestId: crypto.randomUUID() }; }); const approval = await step.waitForEvent("approval", { type: "approval", timeout: "15 minutes", }); return { request, approval: approval.payload }; });Put side effects, provider calls, and expensive work inside
step.do. Keep pure deterministic calculations outside steps. Use stable, descriptive step names because history and retries address those names. Usestep.sleeporstep.sleepUntilfor time andstep.waitForEventfor external continuation.Complete when every non-deterministic operation has a durable step and every continuation has an exact event type.
-
Observe. Copy the returned
instanceId; code-mode calls do not share in-memory variables. Read the run withworkflow.getInstance({ instanceId }). Inspect output for a completed run, confirm the authored event type for a waiting run, and readworkflow.getHistory({ instanceId })when diagnosing an errored run. If instance details are temporarily unavailable, callworkflow.listInstances({})once as a status fallback and report the backend failure beside the observed summary.Complete when the instance is
completewith observed output, intentionallywaitingwith its exact continuation, orerroredwith the failed step and error identified.
Prompting an agent
When a workflow needs model work, use step.agent.prompt(name, input). One workflow instance owns
one continuing agent session, so later prompts include the earlier prompt, tool-call, and
tool-result history. Give every prompt a stable name.
Workflow agents inherit no tools from the authoring Pi session. Define each capability locally with
defineTool and pass the complete tool set to that prompt. Prefer a tool result when the workflow
needs structured data:
const classify = defineTool({
name: "classify",
description: "Return the harmfulness classification.",
parameters: {
type: "object",
additionalProperties: false,
required: ["classification", "confidence", "reason"],
properties: {
classification: { enum: ["harmful", "not harmful", "uncertain"] },
confidence: { enum: ["low", "medium", "high"] },
reason: { type: "string", maxLength: 1000 },
},
},
execute: async (_toolCallId, result) => result,
});
const response = await step.agent.prompt("classify-text", {
text: `Classify this text:\n\n${text}`,
tools: [classify],
});
const classificationResults = response.toolResults.filter(
({ toolName }) => toolName === "classify",
);
if (classificationResults.length !== 1) {
throw new Error("Expected exactly one classify tool result.");
}
const classification = classificationResults[0].result;
Tool execution is part of the prompt step and can repeat when an attempt fails before commit. Keep
tools pure and replay-safe. Put external effects in separate step.do calls with stable idempotency
keys. Before branching, confirm that the expected tool ran. When execute returns the validated
tool arguments, use the result properties directly instead of repeating the JSON Schema validation.
Operating an existing workflow
Read "/static/codemode/providers/workflow.d.ts" for exact inputs:
workflow.createInstance({ path, instanceId, payload })starts a saved.workflow.jsfile. Supply a stableinstanceIdand copy it for later calls. InlinedefineWorkflowruns do not need this call.workflow.listInstances({ status, pageSize, cursor })lists codemode workflow instances.workflow.getInstance({ instanceId })reads status, output, error, and source path.workflow.getHistory({ instanceId })exposes steps, events, and emissions for diagnosis.workflow.sendEvent({ instanceId, type, payload })resumes a waiting instance.workflow.retryFailedStep({ instanceId, delayMs })retries the latest failed top-level step.
For a waiting instance, send the exact event type expected by step.waitForEvent. Failed-step
retry requires the latest top-level step to be the only failed top-level step. Retrying a do step
reruns all of its nested steps, including completed steps, so their effects and mutations must be
repeatable. Retrying a failed event wait starts a fresh timeout window and considers pending events
before the new deadline.
Signals
- GitHub stars
- 61
- Forks
- 6
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
workflows-rejot-dev- Source
- github.com/rejot-dev/fragno