Intake
Intake is what you hand a run. Each workflow declares the fields it accepts, and Esy validates your payload against that declaration before a single provider call is made — so a typo costs you a 422 rather than a render.
Reading the schema
Fetch any workflow’s contract and you get its intakeSchema: a flat list of fields, each with a type, a required flag, and — where the field is constrained — its allowed values and default.
{
"fields": [
{
"name": "prompt",
"type": "string",
"required": true,
"description": "Subject of the coloring page"
},
{
"name": "aspectRatio",
"type": "enum",
"required": true,
"default": "3:4",
"options": ["3:4", "1:1", "4:3"]
},
{
"name": "quality",
"type": "enum",
"required": false,
"default": "medium",
"options": ["low", "medium", "high", "xhigh", "max"]
}
]
}Field types you will meet:
| Type | Meaning |
|---|---|
string | Free text. Usually the prompt or a title. |
enum | One of a fixed list in options. Anything else is rejected. |
boolean | A switch, almost always with a sensible default. |
integer | A count. |
number | A decimal, typically a threshold. |
array | A list of values. |
object | Structured input for a step that needs more than a scalar. |
artifactReference | The id of an existing artifact to feed into this run. |
default is filled in for you when you omit it, and the value that was used is recorded on the run. You never have to send a field just to get its default, and you can always see afterwards what the run actually ran with.When it does not validate
Every problem is named, so you should never have to guess which field was wrong. This is the single most common error against the API.
HTTP 422
{
"detail": {
"error": "intake_invalid",
"fields": [
"intake.prompt is required",
"intake.categories is required"
]
}
}Unknown keys are currently logged rather than rejected — do not rely on that as permission to send extra fields. See Errors for the full list.
Artifact inputs
Some workflows take another artifact as input — an infographic built from a research report, an edit applied to an existing image. Those fields have type artifactReference and usually constrain the artifactType they accept.
{
"name": "sourceReport",
"type": "artifactReference",
"required": true,
"artifactType": "research-report",
"description": "The report to turn into an infographic"
}You pass an artifact id, and Esy checks that it exists, that it is the right type, and that it is inside a workspace you can reach — before the run starts. A workflow can also declare that a step may produce the input if you do not supply one; see Compose with artifact inputs.
The rule behind the schemas
Once you have read a few intake schemas, you will notice something: they ask for results, not methods. That is deliberate, and it is the design rule that explains most of what you will otherwise find arbitrary.
Every run answers two questions, and they belong to different layers:
You ask for “a picture with a see-through background”. Whether the model renders transparency directly or Esy renders normally and keys the background out afterwards is a kitchen decision — it depends on which model is bound today and what that model can do.
Why it is built this way
A mechanism field fails twice over. First, it asks you a question already settled by the model binding, so wrong combinations simply break runs. Second, and worse, it makes saved intakes rot.
| A saved intake that says… | In a year |
|---|---|
| “I want a transparent background” | Still exactly what you wanted. The engine picks whatever is best by then. |
| “Run the background-removal step” | Actively worse: it forces an extra paid step that a newer model made unnecessary. |
A new promise — something the workflow could not deliver before — is a template change and a new version. A better mechanism for a promise already made is not: it is a capability flag on the model, conditional logic in the step, and a provenance entry. Your saved intakes keep working and quietly get better.
Seeing what was actually used
Because the engine makes these choices, it also records them. A finished run carries the resolved intake — defaults filled in — and the artifact records the mechanism chosen, for instance transparencyMechanism: "native" versus "post-process". If you need to know why two runs of the same workflow behaved differently, that is where to look.
| Field | Type | Required | Description |
|---|---|---|---|
run.intake | object | optional | What you sent, with defaults applied. |
run.workflowVersion | string | optional | Which definition interpreted that intake. |
run.specVersionHash | string | optional | Hash of definition + intake. Two identical hashes mean identical inputs. |
artifact.content | object | optional | The resolved prompt, the model used, and the mechanism chosen. |
- Read a workflow’s
intakeSchemabefore calling it; it names every field, its type, and its allowed values. - Intake asks for outcomes. If a field looks like it is asking you how to implement something, that is a bug, not a feature.
- Defaults are applied and recorded, so a finished run always shows what it really ran with.
