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 528 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 model credentials that are already available in the current account first, and do not rush to do long Provider split
- Don't set up 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.
Validate and preview every change
Changed something → "Verify" first to check the structure and references → "Preview" to view the static execution plan → Finally, use test data to actually execute. Rehearsal does not invoke steps or verify third-party credentials or side effects for you.
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 Agent Steps — For most "summarization/extraction/rewriting" tasks, just configure agent and input.
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:
workflow:
- step: fetch_data
code:
language: python
script: |
# 输出较大的 JSON
print(fetch_data())
extract:
- json_path: $.data.stats.total_users
variable: user_count
- json_path: $.data.items
variable: items
- step: summarize
agent: writer
depends_on:
- fetch_data
input: "用户数:{{user_count}}"Optional branches must be merged explicitly
If the upstream may be skipped due to condition, do not assume that it must have output. You can have different branches write explicit runtime variables separately, and then merge them using aggregate or subsequent code steps.
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
- Inference/Code Review → Select the high-capacity or inference model provided by the current Provider
- Short Summary/Category → Choose a low-latency, low-cost model
- Long document → First confirm the model context window and how the tool handles the file
- Before going live, compare quality, latency, and cost using your own real samples; do not choose based on the model name alone
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
- Validate and preview first — First eliminate the problems of structure, dependency and missing variables, and then use a small sample to implement it in real life.
- Classification using cheap models — Classifier 9 out of 10 does not require Opus/GPT-5.
- There is an upper limit on concurrency — Batch processing uses iterate_over's parallel / max_parallel to control concurrency and avoid triggering Provider TPM/RPM limits.
- Cache RAG index — Re-embedding the same corpus every time is expensive, so persist the results to an artifact.
- Monitor actual bills — The costs in the execution details are only estimates; also set budget or usage alarms in the model Provider console.
8. Security And Compliance
- Never write keys into YAML - use Credential Center.
- Declare credentials required by a code step explicitly as credential:<provider> in variable_types. Never place plaintext values in variables or scripts.
- 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
- Validate and preview a new workflow first, then perform a real execution with a test account, test data, or read-only permissions.
- 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 any important change, "export YAML" for a local backup — even with version history as a safety net, a local copy is more reassuring.
- 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
- Critical processes include explicit notification steps in failure paths; available channels depend on current workflow tools, modules, and configured credentials.
- Check the data dashboard regularly - which workflow is the most expensive/slowest/fails most often? Optimization starts with it.
- Administrators with audit log access regularly review permission changes and credential usage records.
12. Workflow Completion Checklist
- The verification is error-free and the preview plan is in line with expectations.
- A successful execution using test data
- 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"
- The critical failure path has available notification or manual processing methods
- 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