> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://onepin.ai/docs/workflow/overview/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://onepin.ai/_mcp/server. # Workflow > How an Onepin workflow definition works — the graph of Source, Operator, Validator, and Sink nodes, how a line of script becomes finished audio, and how to edit a definition in code. Every workflow is a **definition**: a graph of typed nodes connected by edges. A line of script enters at one end, passes through the nodes you wire up, and leaves as finished audio. When you clone a template you get a ready-made graph; to change what it says, who speaks, or what comes out, you edit node `config` objects. ``` definition ├── graph │ ├── nodes[] — id (UUID), type, name, position, config │ └── edges[] — id, source, sourcePort, target, targetPort └── execution — run-time settings ``` ## The four node families Every node belongs to one of four families. Open a node for what it does, its config, and how to inspect it live. | Family | What it does | Nodes | | ------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Source** | Brings script in | [Script](/docs/workflow/script) | | **Operator** | Transforms lines | [Translator](/docs/workflow/translator) · [Normalizer](/docs/workflow/normalizer) · [Generator](/docs/workflow/generator) · [Phoneme Injector](/docs/workflow/phoneme-injector) · [Pronunciation Corrector](/docs/workflow/pronunciation-corrector) | | **Validator** | Scores lines and routes them `pass` or `fail` | [How validators work](/docs/workflow/validators) · [Accuracy](/docs/workflow/accuracy-validator) · [Naturalness](/docs/workflow/naturalness-validator) · [Noise](/docs/workflow/noise-validator) · [Pronunciation](/docs/workflow/pronunciation-validator) | | **Sink** | Sends the result out | [Export](/docs/workflow/export) | A validator is not a kind of operator. An operator rewrites a line and hands it on; a validator leaves the line alone and decides where it goes next — which is why it alone has two output ports. The API agrees: `GET /api/v2/nodes/{node_type}` returns `category`, and it reads `source`, `operator`, `validation`, or `output`. > **Note** > > In a definition's JSON, each node's `type` carries its internal id, and those are what you write when you author a definition by hand: > > * **Source** — `source_script` (Script) > * **Operator** — `operator_translator` · `operator_normalizer` · `operator_generator` (Generator) · `operator_phoneme_injector` · `operator_pronunciation_corrector` > * **Validator** — `validator_error_rate` (Accuracy) · `validator_naturalness` · `validator_noise` (Noise) · `validator_pronunciation` (Pronunciation) > * **Sink** — `sink_preview` (Export) > > The prefix is the family, with one exception to watch for: Accuracy is `validator_error_rate`, not `validator_accuracy`. > > Run `onepin nodes list` for the live list with each node's display name and ports — that, not this page, is the source of truth for what a node is called in the app. ## How lines flow Every edge carries **lines**. A line is one piece of script plus its language, and it picks up more as it moves through the graph: ``` Script → (translated) → (normalized) → Generator → validators → Export text text text + audio + scores downloaded ``` A port only accepts a line that already carries what it needs. Export, for example, requires audio — and only the Generator adds audio — so a Generator always sits upstream of Export. Onepin checks these connections when you save; an edge that can't carry what the next node needs is rejected with a clear message. See [General rules](/docs/workflow/general-rules) for the full set. ## Editing a definition Definitions are replaced whole, not merged — so the reliable pattern is **read → modify → write back**: ```python definition = client.workflows.get(workflow_id=workflow_id).data.model_dump()["definition"] for node in definition["graph"]["nodes"]: if node["type"] == "source_script": node["config"] = {"input_type": "text", "source_language": "en-us", "text": "..."} client.workflows.patch_workflow(workflow_id, definition=definition) ``` The [Run a workflow](/docs/guides/run-a-workflow) guide walks this end to end. Authoring a definition from scratch (`client.workflows.create_workflow` / `onepin workflows create --definition @file.json`) follows the same schema — start from `onepin workflows definition-schema`. ## Estimating cost before running ```bash onepin workflows preview-run # estimate a run without executing it ``` Also available per template (`GET /api/v1/templates/{id}/estimate`) and via the SDK (`client.workflows.preview_run`, `client.workflows.estimate_workflow`). ## Related * [General rules](/docs/workflow/general-rules) — what makes a graph valid * [Run a workflow](/docs/guides/run-a-workflow) — edit a definition entirely in code * [Voices & Models](/docs/get-started/voices-models) — the model catalog * [API Reference](/docs/api-reference) — the REST surface, endpoint by endpoint > Onepin is a voice workflow platform that orchestrates, validates, and ships production-ready audio across 33 TTS models.