docs/user_guide/en/workflow_authoring.md
This guide covers YAML structure, node types, provider configuration, edge conditions, and design template export so you can build and debug DevAll DAGs efficiently. Content mirrors docs/user_guide/workflow_authoring.md with English copy for global contributors.
yaml_instance/ and yaml_template/.model, python, agent, human, subgraph, passthrough, literal).FIELD_SPECS (see field_specs.md) and the Schema API contract (config_schema_contract.md) if you rely on dynamic forms in the frontend/IDE.Every workflow file follows the DesignConfig root with only three keys: version, vars, and graph. The snippet below is adapted from yaml_instance/net_example.yaml and can run as-is:
version: 0.4.0
vars:
BASE_URL: https://api.example.com/v1
API_KEY: ${API_KEY}
graph:
id: paper_gen
description: Article generation and refinement
log_level: INFO
is_majority_voting: false
initial_instruction: |
Provide a word or short phrase and the workflow will draft and polish an article.
start:
- Article Writer
end:
- Article Writer
nodes:
- id: Article Writer
type: agent
config:
provider: openai
base_url: ${BASE_URL}
api_key: ${API_KEY}
name: gpt-4o
params:
temperature: 0.1
- id: Human Reviewer
type: human
config:
description: Review the article. Type ACCEPT to finish; otherwise provide revision notes.
edges:
- from: Article Writer
to: Human Reviewer
- from: Human Reviewer
to: Article Writer
condition:
type: keyword
config:
none:
- ACCEPT
case_sensitive: false
version: optional configuration version (defaults to 0.0.0). Increment it whenever schema changes in entity/configs/graph.py require template or migration updates.vars: root-level key-value map. You can reference ${VAR} anywhere in the file; fallback is the same-name environment variable. GraphDefinition.from_dict rejects nested vars, so keep this block at the top only.Environment Variables & .env File
The system supports referencing variables in YAML configurations using ${VAR} syntax. These variables can be used in any string field within the configuration. Common use cases include:
api_key: ${API_KEY}base_url: ${BASE_URL}name: ${MODEL_NAME}The system automatically loads the .env file from the project root (if present) when parsing configurations. Variable resolution follows this priority order:
| Priority | Source | Description |
|---|---|---|
| 1 (highest) | Values defined in vars | Key-value pairs declared directly in the YAML file |
| 2 | System/shell environment variables | Values set via export or system config |
| 3 (lowest) | Values from .env file | Only applied if the variable doesn't already exist |
[!TIP] The
.envfile does not override existing environment variables. This allows you to define defaults in.envwhile overriding them viaexportor deployment platform configurations.
[!WARNING] If a placeholder references a variable that is not defined in any of the three sources above, a
ConfigErrorwill be raised during configuration parsing with the exact path indicated.
graph: required block that maps to the GraphDefinition dataclass:
id (required), description, log_level (default DEBUG), is_majority_voting, initial_instruction, and optional organization.start/end entry lists (the system executes nodes listed in start at the beginning), plus nodes and edges. Provider/model/tooling settings now live inside each node.config; the legacy top-level providers table is deprecated. In the example the keyword condition on Human Reviewer -> Article Writer keeps looping unless the reviewer types ACCEPT.memory defines stores available to node.config.memories. The validator ensures every attachment points to a declared store.yaml_template/design.yaml mirrors the latest GraphDefinition shape. After editing configs run python -m tools.export_design_template or hit the Schema API to validate.Further reading: docs/user_guide/en/field_specs.md (field catalog), docs/user_guide/en/runtime_ops.md (runtime observability), and yaml_template/design.yaml (generated baseline template).
| Type | Description | Key fields | Detailed Docs |
|---|---|---|---|
agent | Runs an LLM-backed agent with optional tools, memories, and thinking phases. | provider, model, prompt_template, tooling, thinking, memories | agent.md |
python | Executes Python scripts/commands sharing the code_workspace/. | entry_script, inline_code, timeout, env | python.md |
human | Pauses in the Web UI awaiting human input. | prompt, timeout, attachments | human.md |
subgraph | Embeds a child DAG to reuse complex flows. | graph_path or inline graph | subgraph.md |
passthrough | Pass-through node that forwards only the last message by default and can be configured to forward all messages; used for context filtering and graph structure optimization. | only_last_message | passthrough.md |
literal | Emits a fixed text payload whenever triggered and discards inputs. | content, role (user/assistant) | literal.md |
loop_counter | Guard node that limits loop iterations before releasing downstream edges. | max_iterations, reset_on_emit, message | loop_counter.md |
loop_timer | Guard node that limits loop duration before releasing downstream edges. | max_duration, duration_unit, reset_on_emit, message, passthrough | loop_timer.md |
Fetch the full schema via POST /api/config/schema or inspect the dataclasses inside entity/configs/.
provider, the engine uses globals.default_provider (e.g., openai).model, api_key, and base_url accept ${VAR} placeholders for environment portability.globals in the workflow root ({ default_provider: ..., retry: {...} }) if supported by the dataclass.model:
provider: gemini
base_url: https://generativelanguage.googleapis.com
api_key: ${GEMINI_API_KEY}
name: gemini-2.0-flash-001
input_mode: messages
params:
response_modalities: ["text", "image"]
safety_settings:
- category: HARM_CATEGORY_SEXUAL
threshold: BLOCK_LOWER
The Gemini Provider supports multi-modal input (images/video/audio are automatically converted to Parts) and supports function_calling_config to control tool execution behavior.
- source: plan
target: execute
edges:
- source: router
target: analyze
condition: should_analyze # functions/edge/should_analyze.py
condition function raises, the scheduler marks the branch as failed and stops downstream execution.process to an edge when you want to transform or filter the payload after the condition is met (e.g., extract a verdict, keep only structured fields, or rewrite text).condition (type + config). Built-ins include:
regex_extract: Python regex with optional group, mode (replace_content, metadata, data_block), multiple, and on_no_match (pass, default, drop).function: calls helpers under functions/edge_processor/. The handler signature is def foo(payload: Message, **kwargs) -> Message | None. Note: The Processor interface is now standardized, and kwargs includes context: ExecutionContext, allowing access to the current execution context.- from: reviewer
to: qa
process:
type: regex_extract
config:
pattern: "Score\\s*:\\s*(?P<score>\\d+)"
group: score
mode: metadata
metadata_key: quality_score
case_sensitive: false
on_no_match: default
default_value: "0"
AgentConfig.tooling; see the Tooling module (Chinese for now).AgentConfig.thinking (e.g., chain-of-thought, reflection). Reference entity/configs/thinking.py for parameters.MemoryAttachmentConfig through AgentConfig.memories; details live in the Memory module.Nodes support a sibling field dynamic to enable parallel processing or Map-Reduce patterns.
type: map): Fan-out. Splits list inputs into multiple units for parallel execution, outputting List[Message] (flattened results).type: tree): Fan-out & Reduce. Splits inputs for parallel execution, then recursively reduces results in groups of group_size until a single result remains (e.g., "summary of summaries").nodes:
- id: Research Agents
type: agent
# Standard config (behaves as template for parallel units)
config:
provider: openai
model: gpt-4o
prompt_template: "Research this topic: {{content}}"
# Dynamic execution config
dynamic:
type: map
# Split strategy (first layer only)
split:
type: message # Options: message, regex, json_path
# pattern: "..." # Required for regex mode
# json_path: "$.items[*]" # Required for json_path mode
# Mode-specific config
config:
max_parallel: 5 # Concurrency limit
Ideal for chunked summarization of long texts:
dynamic:
type: tree
split:
type: regex
pattern: "(?s).{1,2000}(?:\\s|$)" # Split every ~2000 chars
config:
group_size: 3 # Reduce every 3 results into 1
max_parallel: 10
This mode automatically builds a multi-level execution tree until the result count is reduced to 1. Split config is the same as map mode.
After editing configs or FIELD_SPECS, regenerate templates:
python -m tools.export_design_template \
--output yaml_template/design.yaml \
--mirror frontend/public/design_0.4.0.yaml
FIELD_SPECS to emit YAML templates plus the frontend mirror file.POST /api/workflow/execute with session_name, graph_path or graph_content, task_prompt, optional attachments, and log_level (defaults to INFO, supports INFO or DEBUG).python run.py --path yaml_instance/demo.yaml --name test_run. Provide TASK_PROMPT via env var or respond to the CLI prompt.WareHouse/<session>/context.json to inspect node I/O. Note that all node outputs are now standardized as List[Message].python run.py --inspect-schema to view field specs quickly.ConfigError during parsing with a precise path surfaced in both UI and CLI logs.