Workflows
A workflow is the versioned definition a run executes. It declares what it accepts, what it does, which models it uses, what has to pass, and what it produces. You do not write prompts against Esy — you pick a workflow and fill in its intake.
/v1/workflows; the field you pass when starting a run is templateId. Same thing, two names, and the field name is not going to change.The contract
Every workflow is a contract with two ends. intakeSchema declares what goes in; artifactSchema declares what comes out. Between them sit the steps, the bindings, and the gates.
{
"id": "generate-coloring-page",
"name": "Generate Coloring Page",
"artifactClass": "visual",
"outputType": "visual",
"status": "active",
"supersededById": null,
"version": "2026.09.10",
"intakeSchema": { "fields": [ … ] },
"runtimeSteps": [ … ],
"gates": [ … ],
"providers": { "imageGenerator": "…", "classifier": "…", "textGate": "…" },
"budgetPolicy": { "perRunCapUsd": 0.35 },
"artifactSchema": {
"artifactClass": "visual",
"artifactType": "coloring-page",
"files": ["image/png"],
"metadata": { "aspectRatio": "enum [3:4, 1:1, 4:3]", "classification": "object" }
}
}| Field | Type | Required | Description |
|---|---|---|---|
id | string | required | Stable slug, and the value you pass as templateId. Never reused for a different workflow. |
artifactClass | enum | required | visual, research, video, or knowledge. |
version | string | required | A date-like label such as 2026.09.10. Runs pin this. See Versioning. |
status | enum | optional | active or deprecated. A deprecated workflow refuses new runs and names its successor. |
intakeSchema | object | required | The fields this workflow accepts. See Intake. |
runtimeSteps | array | required | The ordered program. See Runs and steps. |
gates | array | optional | What must pass, and which step each gate unlocks. See Gates and review. |
providers | object | optional | Role → model-registry id. The bindings a run may override. |
budgetPolicy | object | optional | Advisory, chiefly perRunCapUsd. Real enforcement comes from budgets. |
artifactSchema | object | required | The declared output: class, type, file types, and promised metadata. |
Finding one to run
The catalog is public and needs no key, which makes it the right thing to point a build script at.
curl -s https://api.esy.com/v1/catalog/workflowsThe list gives you the summary of each workflow — what it is for, roughly how long it takes, whether it includes QA, what you provide and what you get. To see the actual input contract, ask for one by id:
curl -s https://api.esy.com/v1/catalog/workflows/generate-coloring-page"redacted". You get everything you need to call the workflow correctly, and nothing you would need to clone it.Naming
Ids are verb-noun in kebab case, and the verb is load-bearing: it tells you what kind of work happens, which is usually what you actually want to know when choosing between two workflows.
| Verb | Means | Example |
|---|---|---|
| generate | Invents something new from a description. | generate-illustration |
| plan | Researches and produces a structured plan, not the thing itself. | plan-clipart-pack |
| build | Computes a result from inputs, deterministically where it can. | build-… |
| compose | Writes from supplied sources rather than inventing. | compose-… |
| edit | Changes an existing artifact you supply. | edit-image |
| remove | Takes something away from an input. | remove-image-background |
| transcribe | Converts between media, preserving content. | transcribe-… |
assemble is reserved for an internal stage and never appears in an id. create and make are deliberately unused — they say nothing that generate or build does not say more precisely.
Visibility
Not every workflow is runnable, and the ladder is strict. A workflow must be at least internal before a run against it will execute.
| Visibility | In the catalog? | Runnable? |
|---|---|---|
| draft | No | No — creating a run does not execute it |
| internal | No | Yes |
| public | Yes | Yes |
Validating a published workflow
For a workflow in the catalog, validation happens on the server the moment you call it: POST /v1/runs checks your intake against the intakeSchema and returns a 422 naming every bad field before a provider is called. A rejected run costs nothing, so the cheapest pre-check is to read the schema, build the intake from it, and let the server have the final word. See Errors.
Validating a workflow you are writing
POST /v1/workflows/dry-run is an authoring tool. It does not take a templateId — you send a draft definition (its steps, bindings, and intake schema) plus a sample intake, and it resolves the plan and prices it without calling a provider.
curl -X POST https://api.esy.com/v1/workflows/dry-run \
-H "Authorization: Bearer $ESY_API_KEY" \
-H "content-type: application/json" \
-d '{
"intakeSchema": { "fields": [ … ] },
"runtimeSteps": [ … ],
"providers": { "imageGenerator": "openai/gpt-image-2-2026-04-21" },
"intake": { "prompt": "a lighthouse at dusk" }
}'{
"ok": true,
"stepCount": 3,
"steps": [ … ],
"errors": [],
"warnings": [],
"estimate": {
"estimatedCost": { "min": 0.004, "typical": 0.008, "max": 0.012, "currency": "USD" },
"highCost": false
}
}{ "templateId": …, "intake": … } is accepted and silently ignored — you get back ok: true with zero steps and the warning “template has no runtime steps”. That is not a pass. Check stepCount and warnings, not just ok.POST /v1/workflows/estimate works the same way — it prices a draft runtimeSteps + providers pair, not a published workflow. Because the public catalog redacts prompts and bindings, you cannot dry-run or estimate someone else’s workflow; you can only call it.
schemaVersion: "workflow-schema-v1" on a workflow. It is a label, not a registry: there is no v2, and no separate validator keyed to it. The validation that actually runs is the dry-run above. Treat the field as provenance, not as a contract you can look up.- A workflow declares both ends of its contract:
intakeSchemain,artifactSchemaout. - The catalog is public and unauthenticated — read the contract before you call, rather than guessing field names.
- The verb in the id tells you what kind of work it does.
generateinvents;composewrites from sources. - A bad intake is rejected with a
422before anything is spent. Dry-run and estimate are for workflows you are authoring, and take a definition rather than atemplateId.
