Workflow Chaining
Experimental Feature
Workflow chaining is currently experimental and under active development. The documentation, examples, workflow API, metadata schema, and artifact layout are subject to significant changes in future releases. If you encounter any issues, have questions, or have ideas for improvement, please consider starting a discussion on GitHub.
Workflow chaining lets you split a dataset build into named stages. Each stage runs a normal DataDesigner.create() call, writes its own artifact directory, and hands a selected parquet output to the next stage as a LocalFileSeedSource.
Use it when one generation step naturally depends on the cleaned or reshaped output of another step, especially when a processor-only stage is clearer than mixing all transformations into one config.
Basic shape
Stage outputs
A stage can expose different views of its data:
Processors added with config_builder.add_processor(...) run inside the stage and usually create side artifacts. They do not automatically change what the next stage receives. Use output_processors=[...] when a processor should define the stage boundary output.
Processor-only stages
Stages can be processor-only when they receive seed data from an upstream stage:
This is useful for final cleanup, schema transforms, and format-specific export preparation.
Postprocessing hooks
Use output_processors for structured transforms that can be expressed as processor configs. Use on_success when a stage boundary needs arbitrary Python code, such as filtering rows before the next stage runs.
The callback receives the completed stage artifact directory and must return a parquet file or directory that can seed downstream stages.
on_success_version is part of the stage resume identity. Change it when the callback’s output semantics change. If a callback returns zero rows, the workflow raises by default; set allow_empty=True to mark that stage as completed empty and skip downstream stages.
Changing row counts between stages
Each stage has a fixed requested row count while it runs. To resize a workflow, change the selected output at a stage boundary and let the next stage seed from that output.
Filtering is the shrink case: a callback can write fewer rows than the stage generated, and the next stage defaults to that filtered row count when num_records is omitted.
Growing is the explode case. If a downstream stage asks for more rows than the upstream selected output contains, the seed reader cycles through the seed rows in order.
The conversations stage receives 100 persona rows as its seed and requests 1,000 output rows. Data Designer reuses persona rows in order, so each persona seeds about 10 conversation rows. Add downstream sampler or LLM columns when each repeated seed row should produce distinct outputs.
For custom upsampling, make the expanded dataset the selected output of the upstream stage:
In this version, conversations defaults to the 1,000-row callback output and can use variant_id to diversify prompts.
Resume
Workflow names are durable artifact identities. Reusing the same name with resume=ResumeMode.IF_POSSIBLE reuses compatible completed stages, resumes a matching partial stage through DataDesigner.create(..., resume=ResumeMode.ALWAYS), and reruns the first changed or missing stage plus its descendants.
Use ResumeMode.ALWAYS for strict resume before the first recovered checkpoint. A changed stage or missing selected output raises instead of starting fresh. If a matching partial stage resumes successfully, descendants are recreated from that stage’s current output.
Review gates
Use targets to materialize an intermediate stage without running the rest of the workflow. export_stage() writes the selected stage output for review. After review, pass the approved parquet as a stage output override and resume the downstream target.
If the reviewed data replaces a stage’s selected output in place, run with resume=ResumeMode.IF_POSSIBLE and rerun_from="expanded" to rebuild that stage and its descendants from the current boundary output.
Current limits
- Stages are linear. DAGs, parallel branches, and joins are planned separately.
push_to_hub()does not support selected processor or callback outputs yet. Useexport()for the selected workflow output.on_successcallbacks are trusted user code. If a callback returns a path, Data Designer reads that path as the next stage input.- The artifact layout is intended for inspection, but it is not yet a stable public contract.