Subflow & Schedule Nodes

Applies to: ChengOS v0.2.0+ | Last verified: 2026-09-25 | Source: crates/cheng-nodes/src/nodes/builtin/tools

tools/subflow calls another workflow once and waits for its result — it is how a large graph is kept readable and how one piece of logic gets reused. tools/batch_subflow is the same call fanned out over a collection, which is the right tool when the item count is data-driven rather than drawn. tools/schedule manages timed tasks: create, pause, resume, cancel, and read back the result of a run that already happened.

Sub Workflow Tool — tools/subflow

Call other workflows as sub-workflows (supports file path or workflow ID)

Inputs

FieldTypeRequiredDefaultDescription
workflow_pathstring✅—Workflow file path (JSON format) or workflow UUID
async_executionboolean—falseWhether to execute asynchronously; true returns immediately after start, false waits for completion. Control: switch
input_dataany—nullInput data passed to sub-workflow (optional). Put follow-up feedback inside this object, not at the top level.
child_contextany—nullPrevious child workflow LLM context returned by an earlier subflow call. Overrides input_data.context when both are set.
agent_contextobject (port)—nullUpstream AgentContext (typically connected from a routing node). Serialized to child workflow's context input. Priority: child_context > agent_context > input_data.context. Connection port, not a form field.
conversation_idstring—nullAmbient parent conversation id passed through to the child workflow
child_session_idstring—nullOptional stable child-session id. Copied into child execution metadata and diagnostics.
response_pathstring—nullOptional dot-path in the combined result used to extract response before heuristic extraction.
context_pathstring—nullOptional dot-path in the combined result used to extract child_context before heuristic extraction.
return_child_contextboolean—trueWhether to return the child workflow's updated context in agent_context. Control: switch
return_node_outputsboolean—trueWhether to include child node outputs in result.outputs. Control: switch
child_context_max_bytesinteger—100000Max serialized child context size (bytes) returned inline. Default 100_000. Oversized contexts are summarized. Control: number
call_stackarray—nullCall stack for detecting recursive calls (internal use)
timeout_secondsinteger—300Timeout in seconds. Control: number
max_parallelisminteger—10Maximum number of parallel nodes. Control: number

Outputs

FieldTypeDescription
statusstringSub-workflow execution status
agent_contextobject (port)Sub-workflow output data as AgentContext. Connection port, not a form field.
elapsed_msintegerExecution time in milliseconds
errorstringError message (if execution failed)
summarystringExecution result summary

Batch Sub Workflow Tool — tools/batch_subflow

Run multiple sub-workflows concurrently with bounded parallelism and aggregated results

Inputs

FieldTypeRequiredDefaultDescription
itemsarray<object>✅—Sub-workflow invocations to run concurrently (results returned in input order)
max_concurrencyinteger—4Batch-level concurrency (concurrent in-flight sub-workflows). Distinct from per-subflow max_parallelism. Control: number
timeout_secondsinteger—300Per-item sub-workflow timeout in seconds. Control: number
max_parallelisminteger—10Maximum parallel nodes inside each sub-workflow (NOT batch concurrency). Control: number
return_child_contextboolean—trueWhether each item should return the updated child context. Control: switch
return_node_outputsboolean—trueWhether to include child node outputs in result.outputs. Control: switch
child_context_max_bytesinteger—100000Per-item max serialized child_context bytes returned inline. Control: number
call_stackarray—nullInherited call stack used for recursion detection (internal use)

Outputs

FieldTypeDescription
statusstring汇总状态:completed / partial_failed / failed
resultsarray<object>Results
totalintegerTotal
succeededintegerSucceeded
failedintegerFailed
elapsed_msinteger批层墙钟总耗时(毫秒)
summarystringSummary

Schedule Manager — tools/schedule

Directly list, create, update, pause, resume, cancel, and inspect scheduled tasks

Inputs

FieldTypeRequiredDefaultDescription
modeenum—manualExecution mode: Manual=user fills parameters, Llm=LLM auto-fills parameters. Control: select. Options: manual, llm
actionstring—""Action type: list_tasks / get_task / get_execution_result / create_task / update_task / pause_task / resume_task / cancel_task / delete_task. Tip: when using create_task, always set a descriptive label so the task list is readable at a glance instead of showing only IDs. Control: select. Options: list_tasks (List Tasks), get_task (Get Task), get_execution_result (Get Execution Result), create_task (Create Task), update_task (Update Task), pause_task (Pause Task), resume_task (Resume Task), cancel_task (Cancel Task), delete_task (Delete Task)
idstring—nullNumeric scheduled task ID
workflow_idstring—nullWorkflow UUID
statusstring—nullFilter status for list_tasks: pending, running, completed, failed, cancelled, paused
limitinteger—50Max return count (default 50, max 500)
offsetinteger—0Pagination offset (default 0)
run_atstring—nullThe schedule expression. Accepts THREE formats: (1) a relative delay to run once after a wait — '2m', '30m', '1h', '1d'; (2) a cron expression for a recurring schedule — '0 9 * * *' (daily 09:00), '0 9 * * 1' (Mondays 09:00), '0 9 * * 0,6' (weekends 09:00); (3) a LOCAL wall-clock datetime to run once at a specific time — '2026-06-30T09:00' or '2026-06-30T09:00:00' (no timezone/offset; the node applies the server timezone itself). For a one-off datetime this MUST be in the future — do not guess the current date; any validation error states the current server time, so read it and correct run_at. Leave timezone empty to use the server's system timezone (recommended).
frequencystring—nullFrequency: once, every_minute, hourly, daily, weekly, monthly, custom
custom_cronstring—nullCustom cron expression
timezonestring—nullIANA timezone for interpreting run_at. Leave empty to use the server's system timezone (recommended).
task_textstring—nullThe workflow INPUT for the scheduled run, as plain text. For a chat/input-fronted workflow this becomes its raw_input. Put the actual content to run here (or use params). Do NOT put it in label.
target_node_idstring—nullNode ID for raw_input routing
paramsany—nullExplicit workflow input parameters object, e.g. {"raw_input": "hello"}. This is exactly what the workflow's entry node receives. Use this OR task_text to provide the input — not label.
priorityinteger—nullExecution priority (default 0)
max_retriesinteger—nullMaximum retries (default 3)
labelstring—nullStrongly recommended: a short descriptive NAME for the task, shown in lists and logs so you can identify tasks at a glance without querying each one by ID. Always set a label when creating tasks. Good labels: '每日新闻摘要', '数据备份-周一', '天气查询测试'. Bad labels: '任务1', 'test', '123'. Keep it under 20 characters and describe the task's core purpose. This is NOT the workflow input — never put the task content here; use task_text or params.
agent_promptstring—nullSchedule an AGENT TURN in the workspace this run is already using, instead of a bare workflow run. Use it to give your future self work: 'check whether the build passed and summarize the failures'. The machine and directory are taken from the current execution and cannot be chosen here — a scheduled turn always lands in the workspace it was created from. Requires the current run to be client-local (a cheng session on the user's own machine).
agent_unattendedstring—nullWhat the scheduled turn does when it needs an approval: fail_fast (default, abort with a reason) or wait (park until a person answers or it times out).
agent_on_busystring—nullWhat to do when the workspace is already running a scheduled turn: skip (default), queue, or parallel.

Outputs

FieldTypeDescription
statusstringOperation status: ok / not_found / error / llm_config
dataanyQuery result or action result
countintegerCurrent page result count
totalintegerTotal count before pagination
errorstringError message

Next steps