Best Practices
When to use which step, how to write idempotent, modularity, performance and cost tuning - the collective experience of engineering workflows.
This article is a summary of "pits that have been stepped on". If you have written more than 10 workflows, you will be able to empathize with them; if you have not written them, save them first and come back to them when you encounter them.
1. How to Write a Workflow That Can Be Put Into Production
Start From A Template
Even if your use case looks unique, among the 240+ templates there's usually one you can "keep half, change half." Starting from a template saves a lot of the time it takes to build the skeleton from scratch.
Instantiate from Template is where most users start.
Do the "Stupid Version" First, Then the "Smart Version"
First version of the new workflow:
- Hard-coded default values for variables
- Don’t add condition, just run them all.
- Use the unified LLM Key of the platform, no need to worry about BYOK
- Do not hang cron, run manually
After running through, we will "refine" one by one: variableization, branching, BYOK, cron, and approval. This way, problems can be easily located at every step.
Dry-Run Every Time You Make a Change
Changed something → dry-run to see the DAG structure and variable flow → run again. Dry-run costs zero, don’t jump.
2. Selection Of Step Type
The priority is from top to bottom. If you encounter difficulty in choosing, pick the one that is ranked higher:
code— If you can use deterministic logic, don't use LLM. Fast, cheap, testable.classifier— Use it when LLM is required but the output is a category; do not use single to let the Agent play freely.single— Most "summarize/extract/rewrite" tasks.sub_workflow— 同一段逻辑在多个 workflow 里复用,或单 workflow > 15 个 step。group_chat— Use it when a task needs several perspectives to hash things out; use single when one Agent can handle it alone.agent_based— Tasks have strong branching characteristics, and each branch requires LLM to determine where to send it.state_machine— There are clear state transitions, such as multiple rounds of interaction/work order life cycle.manual_approval— It must be added before any steps that affect online / spend money / external parties.
Leaving everything to the orchestrator for dynamic dispatch may seem flexible, but in fact it means "letting LLM do the system design" - it is unreproducible, difficult to debug, and the token cost is high. The number of agent_based workers should be clear and less than 5.
3. Variables And Data Flow
Large Fields Are Extracted First and Then Passed
When the upstream step returns 100KB JSON, do not directly send it to the downstream task. Use extract to select the fields you really need:
- id: fetch_data
type: code
code: |
// 返回一个很大的 JSON
return await heavyFetch();
extract:
user_count: $.data.stats.total_users
top_3: $.data.items[:3].nameUse | Default(...) to Find Out
When referring to a variable that may be empty (the output of a step skipped by condition), add default:
- id: summarize
type: single
agent: writer
condition: "length({{steps.classify.categories}} | default([])) > 0"
task: "{{steps.classify.output | default('无内容可摘要')}}"condition Branch Vs on_failure
Don't mix:
- condition controls "can't take this step under normal circumstances" - skip = SKIPPED (not considered a failure)
- on_failure is "compensatory action after error" - send notification / downgrade to alternate data source
Use on_failure as a try-catch, but not as a normal branch. Normal business logic uses condition.
4. Agent And Model
`tool_set`: Smaller Is Better
The tools provided by the default preset are not used in most steps. Cut to 2-3 pieces - the success rate increases and the token consumption decreases.
Models Are Selected According to Tasks
- Reasoning / Code Review → Claude Opus 4 / GPT-5 / DeepSeek-Reasoning
- Short summary / Category → Haiku / GPT-4.1-mini / DeepSeek-V3.5
- Chinese writing → Claude Sonnet / Kimi K2
- Long context (32K+) → Kimi K2 / Claude 200K
Temperature Select By Task
- 0.0 – 0.3 – Reasoning/Classification/Extraction (to be stable)
- 0.4 – 0.7 – summary/rewrite (balanced)
- 0.7 – 0.9 – Creative writing/brainstorming (be creative)
5. Idempotent And Automatic Continuation
All steps of the pure data pipeline add idempotent: true - the service can continue to run after restarting. Do not add steps that contain side effects (send messages/place orders).
See details Auto-Resume.
6. Splitting And Modularization
- A workflow has more than 15 steps - it should be split.
- The same 3-5 step logic needs to be used in another workflow - it should be made into a module (sub_workflow).
- After the module is released, deleting the input/changing the type will break the compatibility, and the MAJOR version must be upgraded.
7. Cost Control
- dry-run first — As noted, a wasted real run costs the most, so this one saves the most.
- Classification using cheap models — Classifier 9 out of 10 does not require Opus/GPT-5.
- There is an upper limit on concurrency — For batch processing, use sub_workflow + max_parallel to control concurrency, and don’t let the TPM explode.
- Cache RAG index — It is expensive to re-embed the same corpus every time and persist the results to the product.
- Bind budget alarm — 在通知设置里加"单 execution cost > $1"或"当日累计 > $50"告警。
8. Security And Compliance
- Never write keys into YAML - use Credential Center.
- The code step's credentials: list should be explicit - don't give the step credentials it doesn't need.
- Add manual_approval before payment / external communication / writing customer database.
- Consider opening workflows involving user data ApproverList of approvers for the compliance team to enter.
- Rotate the API Key used for the Webhook (and the signing secret in compatibility mode) regularly.
9. Testing And Launch Process
- The new workflow is first dry-run on the test workflow page.
- Run the code step script separately in local node/python to see the output.
- Run Agent behavior using breakpoint debugger + small sample 10 times to check stability.
- Use "Trigger once immediately" to verify the time zone/parameter preset before scheduling goes online.
10. Collaboration And Versions
- Before making any important changes, "export YAML" and make a local backup - even if you don't know the version history, a local copy is more reliable.
- Multi-person editing: one person takes the lock, saves the changes, releases the lock, and then the next person takes it. Please split the parallel change into sub-workflows.
- Sync with the team before major version changes - others may be relying on your module.
11. Monitoring And Alarming
- The execution.failed of key workflow is tied to Slack/Feishu notification - if it fails, you will know immediately.
- Check the data dashboard regularly - which workflow is the most expensive/slowest/fails most often? Optimization starts with it.
- Check the audit log once a month - are there any exceptions to the permissions/who has used the credentials.
12. Workflow Completion Checklist
- dry-run passed
- A successful run
- The idempotent / retry strategy for each step is confirmed
- There are manual_approval or condition explicit controls before external side effects.
- All credentials are parsed from Credential Center, there is no plaintext key in YAML
- cron / webhook tied and confirmed "next trigger time"
- Set up failure notifications (at least push execution.failed to Slack)
- Export a copy of YAML to git for off-site backup
Recommended Further Reading
- YAML Syntax Reference — Fuzzy fields cannot be checked accurately
- Breakpoint Debugging — A tool for locating problems in complex processes
- Troubleshooting — Specific symptom comparison