Releases: clawnify/clawflow
v1.2.3
v1.2.2
Patch release.
Fixes
flow_run/flow_read/flow_publishfailed with"require is not defined"whenever called with afile:argument. The plugin'sresolveFlowFile/versionsDir/listVersions/readVersionhelpers used inlinerequire("path")/require("fs"), but the package ships as"type": "module"andtsc --module NodeNextemits those calls verbatim — so they blew up under the ESM plugin loader. Inline flows (nofile:) sidestepped the broken path. Replaced with top-levelnode:fs/node:pathimports.
v1.2.1 — README refresh
Patch release: refreshed logo image in README. No source or behavior changes vs v1.2.0.
v1.2.0 — Plugin tool registration restored + configurable approvals
Restores flow_run / flow_create / etc. as native OpenClaw tools on hosts running ≥ 2026.4.26 and replaces the legacy boolean approval gate with a configurable one.
Fixes
- Manifest now declares
contracts.tools— OpenClaw 2026.5.2 enforces this as the manifest ownership contract for plugin tool registration. Without it, everyregisterTool()call was silently rejected andtoolNamesreported empty. - Plugin default exported from
dist/index.js— the loader resolves throughpackage.json.main.src/index.tsnow re-exports the plugin default from./plugin/index.js, sodist/index.jsexposes both the OpenClaw entry and the public library symbols. registerHooknow passes aname— required by OpenClaw 2026.4.26. Missing-name failures previously killed the entire plugin load withError: hook registration missing name.
New: configurable approval gate
Replaces the hardcoded requireApproval: true + plain prompt with a config-driven gate. Add to plugins.entries.clawflow.config:
{
"approval": {
"enabled": true, // default true
"skipSessionPatterns": [], // substrings matched against ctx.sessionKey
"timeoutMs": 300000, // default 5 min
"timeoutBehavior": "deny" // default "deny"
}
}Returns the rich requireApproval: { title, description, severity, timeoutMs, timeoutBehavior } object the dashboard renders natively. Hosts that need unattended automation (e.g. inbound-webhook sessions) can list session-key substrings under skipSessionPatterns to bypass the gate.
Compatibility
compat.pluginApi/minGatewayVersionbumped to>=2026.5.2build.openclawVersionbumped to2026.5.12
Migration
If you were on @clawnify/clawflow@1.1.0:
- No code changes required.
- If you want to skip the approval prompt for specific session contexts, add
approval.skipSessionPatternsto yourplugins.entries.clawflow.configblock inopenclaw.json.
What's Changed
v1.1.0 — custom step extension API
What's new
Public extension API for registering custom step types alongside built-ins (ai, code, http, …) — no fork required, no shoehorning logic into do: "code" blocks.
import { registerStepType } from "@clawnify/clawflow";
registerStepType({
name: "clawnify_app",
allowedKeys: ["app_id", "method", "path", "body"],
validate: (input) => { /* return { ok, errors } */ },
async run(input, ctx) {
const res = await fetch(url, { signal: ctx.abortSignal });
return { status: res.status, ok: res.ok, body: await res.json() };
},
});Flow JSON is unchanged — { "do": "clawnify_app", "name": "...", "app_id": "..." } resolves through the same dispatcher as built-ins.
API surface
registerStepType(def)— module-level registration on the default registryStepRegistryclass —register/get/has/names/clearPluginConfig.customSteps— pass a private registry for test isolation or multi-runner scenariosCustomStepContexthanded torun():state— frozen deep copy of flow stateenv— resolved env (flow.env merged with process.env)logger— node-prefixeddebug/info/warn/errorabortSignal— per-flowAbortSignal(wired for future flow-level cancellation)nodeName— the node'snamefieldresolveTemplate(str)— manually resolve{{ }}against live state
Behavior
- Pre-resolves
{{ template }}strings in input fields, mirroringdo: http - Validator errors surface with the same
{ node, field, message }shape as native validation — indistinguishable from built-in errors allowedKeysdrives the existing unknown-field detection so typos in flow JSON still fail validation- Collisions with built-ins and duplicate registrations throw synchronously at register time
- Unknown step at runtime fails fast with
Unknown step type: "X". Registered custom steps: ...
Design notes
- No new schema-library dependency. Validator is
(input) => { ok, errors }— bring Zod / Ajv if you want. - No
retryhelper onctx— node-levelretry:already covers this. AbortSignalis exposed now even though flow-cancel isn't wired yet, so the API doesn't break when it's added.
Compatibility
Purely additive — no breaking changes from 1.0.x. Existing flows and plugins continue to work unchanged.
v1.0.0 — trigger → inputs (breaking)
Breaking changes
ClawFlow 1.0.0 removes the trigger concept from the flow format. Flows are now trigger-agnostic — the Clawnify platform resolves webhooks, cron, and manual triggers externally and passes a generic inputs payload.
What changed
FlowDefinition.triggerremoved → replaced by optionalinputs: Record<string, InputSpec>declaration block{{ trigger.X }}→{{ inputs.X }}in all templatesFlowState.trigger→FlowState.inputs- HTTP server:
startWebhookServer/WebhookServerOpts→startFlowServer/FlowServerOpts; endpoint/:flowName/webhook→/:flowName/run FlowTriggertype removed →InputSpectype added- Plugin tool
flow_create:triggerparam →inputsparam
Input validation
Declare inputs with required: true and they are validated at flow start (fail-fast before any node runs). Undeclared keys pass through silently. No declaration = anything-goes mode.
{
"flow": "my-flow",
"inputs": {
"body": { "type": "string", "required": true },
"id": { "type": "string", "required": true }
},
"nodes": [...]
}Migrating from 0.x
npx @clawnify/clawflow migrate <flows-dir> --dry # preview
npx @clawnify/clawflow migrate <flows-dir> # apply
The script rewrites flow files in-place: drops trigger: blocks, rewrites all {{ trigger.X }} templates, bare paths, and condition expressions.
v0.9.7
Skip webhook server on EADDRINUSE instead of crashing.
When clawflow's plugin register() is called in an environment where the gateway daemon already owns the webhook port (e.g. openclaw <anything> on a live VPS), the webhook listener now logs and returns instead of throwing. Avoids needing CLAWFLOW_NO_SERVE=1 for human CLI invocations.
PR #31