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
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
workflow_path | string | ✅ | — | Workflow file path (JSON format) or workflow UUID |
async_execution | boolean | — | false | Whether to execute asynchronously; true returns immediately after start, false waits for completion. Control: switch |
input_data | any | — | null | Input data passed to sub-workflow (optional). Put follow-up feedback inside this object, not at the top level. |
child_context | any | — | null | Previous child workflow LLM context returned by an earlier subflow call. Overrides input_data.context when both are set. |
agent_context | object (port) | — | null | Upstream 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_id | string | — | null | Ambient parent conversation id passed through to the child workflow |
child_session_id | string | — | null | Optional stable child-session id. Copied into child execution metadata and diagnostics. |
response_path | string | — | null | Optional dot-path in the combined result used to extract response before heuristic extraction. |
context_path | string | — | null | Optional dot-path in the combined result used to extract child_context before heuristic extraction. |
return_child_context | boolean | — | true | Whether to return the child workflow's updated context in agent_context. Control: switch |
return_node_outputs | boolean | — | true | Whether to include child node outputs in result.outputs. Control: switch |
child_context_max_bytes | integer | — | 100000 | Max serialized child context size (bytes) returned inline. Default 100_000. Oversized contexts are summarized. Control: number |
call_stack | array | — | null | Call stack for detecting recursive calls (internal use) |
timeout_seconds | integer | — | 300 | Timeout in seconds. Control: number |
max_parallelism | integer | — | 10 | Maximum number of parallel nodes. Control: number |
Outputs
| Field | Type | Description |
|---|---|---|
status | string | Sub-workflow execution status |
agent_context | object (port) | Sub-workflow output data as AgentContext. Connection port, not a form field. |
elapsed_ms | integer | Execution time in milliseconds |
error | string | Error message (if execution failed) |
summary | string | Execution result summary |
Batch Sub Workflow Tool — tools/batch_subflow
Run multiple sub-workflows concurrently with bounded parallelism and aggregated results
Inputs
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
items | array<object> | ✅ | — | Sub-workflow invocations to run concurrently (results returned in input order) |
max_concurrency | integer | — | 4 | Batch-level concurrency (concurrent in-flight sub-workflows). Distinct from per-subflow max_parallelism. Control: number |
timeout_seconds | integer | — | 300 | Per-item sub-workflow timeout in seconds. Control: number |
max_parallelism | integer | — | 10 | Maximum parallel nodes inside each sub-workflow (NOT batch concurrency). Control: number |
return_child_context | boolean | — | true | Whether each item should return the updated child context. Control: switch |
return_node_outputs | boolean | — | true | Whether to include child node outputs in result.outputs. Control: switch |
child_context_max_bytes | integer | — | 100000 | Per-item max serialized child_context bytes returned inline. Control: number |
call_stack | array | — | null | Inherited call stack used for recursion detection (internal use) |
Outputs
| Field | Type | Description |
|---|---|---|
status | string | 汇总状态:completed / partial_failed / failed |
results | array<object> | Results |
total | integer | Total |
succeeded | integer | Succeeded |
failed | integer | Failed |
elapsed_ms | integer | 批层墙钟总耗时(毫秒) |
summary | string | Summary |
Schedule Manager — tools/schedule
Directly list, create, update, pause, resume, cancel, and inspect scheduled tasks
Inputs
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
mode | enum | — | manual | Execution mode: Manual=user fills parameters, Llm=LLM auto-fills parameters. Control: select. Options: manual, llm |
action | string | — | "" | 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) |
id | string | — | null | Numeric scheduled task ID |
workflow_id | string | — | null | Workflow UUID |
status | string | — | null | Filter status for list_tasks: pending, running, completed, failed, cancelled, paused |
limit | integer | — | 50 | Max return count (default 50, max 500) |
offset | integer | — | 0 | Pagination offset (default 0) |
run_at | string | — | null | The 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). |
frequency | string | — | null | Frequency: once, every_minute, hourly, daily, weekly, monthly, custom |
custom_cron | string | — | null | Custom cron expression |
timezone | string | — | null | IANA timezone for interpreting run_at. Leave empty to use the server's system timezone (recommended). |
task_text | string | — | null | The 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_id | string | — | null | Node ID for raw_input routing |
params | any | — | null | Explicit 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. |
priority | integer | — | null | Execution priority (default 0) |
max_retries | integer | — | null | Maximum retries (default 3) |
label | string | — | null | Strongly 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_prompt | string | — | null | Schedule 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_unattended | string | — | null | What 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_busy | string | — | null | What to do when the workspace is already running a scheduled turn: skip (default), queue, or parallel. |
Outputs
| Field | Type | Description |
|---|---|---|
status | string | Operation status: ok / not_found / error / llm_config |
data | any | Query result or action result |
count | integer | Current page result count |
total | integer | Total count before pagination |
error | string | Error message |