Generate an OpRun#
After a developer has deployed an op to your gyoza cluster, it becomes an OpDefinition on the server. You can now instantiate an OpRun from it to actually execute the op with your inputs.
All interactions happen through the gyoza server REST API. This guide uses
curl for the examples, but any HTTP client works the same way.
See also
Full API reference with all endpoints and schemas: REST API.
Prerequisites#
A running gyoza server (see Deploy the Gyoza Server) with at least one OpDefinition registered (see Deploy a Gyoza Op).
The server URL and API key.
We will use http://localhost:5555 as the server URL, my-secret-token as the API key and classify-op as the OpDefinition name throughout this guide.
Check the input and output specs#
Before creating a run you need to know what inputs the op expects and what outputs it produces. You can fetch the OpDefinition by name using:
GET /definitions/{name}
For our classify-op example:
curl http://localhost:5555/definitions/classify-op \
-H "X-API-Key: my-secret-token"
The response includes (among other fields) the input_specs and
output_specs sections:
{
"id": "classify-op",
"version": "1.0.0",
"input_specs": {
"image_path": {"type": "string", "required": true},
"top_k": {"type": "int", "required": false, "default": 3}
},
"output_specs": {
"label": {"type": "string"},
"confidence": {"type": "float"}
}
}
This tells you that image_path is required (a string) and top_k
is optional (defaults to 3). Your run request must satisfy these
constraints. The output_specs section lists the fields the op
produces, which is also where you find the field names you can pre-fill
with upload URLs (see Delivering file outputs).
Create the run#
To create an OpRun, send a POST to the definition’s runs endpoint:
POST /definitions/{name}/runs
For our classify-op example, providing the inputs that match the spec
above:
curl -X POST http://localhost:5555/definitions/classify-op/runs \
-H "Content-Type: application/json" \
-H "X-API-Key: my-secret-token" \
-d '{
"inputs": {
"image_path": "/remote/path/photo.jpg",
"top_k": 3
},
"priority": 5
}'
inputsThe input payload for the op. Required fields must be present and types must match the
input_specs, otherwise the server returns a400error.priorityOptional. Scheduling priority for the execution of the op. OpRuns with higher priority are executed first by the scheduler.
outputsOptional. Partial outputs template, pre-fill an output field with an upload URL to have the file it produces delivered there. See Delivering file outputs below.
If you need to run a specific version of the OpDefinition, you can append a
version query parameter to the request, if you don’t specify a version, the server will use the latest version of the definition by default.
curl -X POST "http://localhost:5555/definitions/classify-op/runs?version=1.0.0" \
-H "Content-Type: application/json" \
-H "X-API-Key: my-secret-token" \
-d '{"inputs": {"image_path": "/remote/path/photo.jpg"}}'
The response is the full OpRun object, including its id, save it,
you will need it to monitor, cancel, or retry the run:
{
"id": "a1b2c3d4-...",
"state": "PENDING",
"priority": 5,
"progress": 0,
"current_attempt": 1,
"image": "myregistry/classify-op:1.0.0",
"inputs": {"image_path": "/remote/path/photo.jpg", "top_k": 3},
"outputs": {},
"op_definition": "classify-op",
"createdAt": "2026-03-02T20:00:00Z",
"updatedAt": "2026-03-02T20:00:00Z"
}
The run starts in PENDING state and will be picked up by a worker
automatically.
Delivering file outputs#
Ops that produce large files declare them as output fields holding a local
path (see Build a Gyoza Op). Since gyoza only transports JSON and knows
nothing about your storage, you tell each run where to deliver those files
by pre-filling the output field with an upload URL (e.g. a presigned S3/GCS
PUT URL, signed with your credentials). The field names come from the
definition’s output_specs:
curl -X POST http://localhost:5555/definitions/segment-op/runs \
-H "Content-Type: application/json" \
-H "X-API-Key: my-secret-token" \
-d '{
"inputs": {"image_url": "https://bucket.example/photo.jpg?X-Sig=..."},
"outputs": {"mask": "https://bucket.example/results/mask.tif?X-Sig=..."}
}'
After the op runs, gyoza uploads the produced file to that URL and the final output holds the file’s canonical URL (the query string with the signature is stripped):
{
"state": "COMPLETED",
"outputs": {"mask": "https://bucket.example/results/mask.tif"}
}
Fields without a pre-filled URL are returned exactly as the op produced them. The template survives retries, and neither the server nor the worker ever holds storage credentials, the URL is opaque data to them.
Files larger than 5 GiB#
One PUT stops at 5 GiB. For a bigger output, add the part URLs of a multipart upload you created:
{"mask": {
"url": "https://bucket.example/results/mask.tif?X-Sig=...",
"parts": ["https://bucket.example/results/mask.tif?partNumber=1&uploadId=...&X-Sig=...", "..."],
"part_size": 1073741824
}}
Up to 5 GiB the file goes to url; above it, slice n goes to
parts[n-1]. Complete the upload after the run, or abort it if unused.
Idempotent definition submissions#
For durable orchestration, pass both idempotency_key and logical_payload
to POST /definitions/{name}/runs?version=.... The key must contain 1–200
letters, digits, underscores, dots, colons or hyphens. Namespace it by client,
execution and node; keys are global to this Gyoza deployment.
logical_payload requires inputs and outputs JSON objects describing
immutable resource identities, parameters and destinations. Put signed URLs in
the normal inputs/outputs transport fields, and stable file/version or
storage-object references in the logical payload. The caller is responsible for
including every logical input and destination; Gyoza cannot infer resource
identity from a signed URL.
The server hashes this payload together with the requested definition/version,
priority and event-delivery configuration. A repeated key returns the original
run (including after completion), while different logical content returns 409.
The response includes op_definition_version, pinned on initial creation.
An omitted version is resolved only for the initial successful submission.
Concurrent submissions publish exactly one runnable record.
Use GET /runs/by-idempotency-key/{key} to recover the operation after a
network timeout; 404 means the key has not been recorded. Repeating the same
POST is also safe. Renewed signed URLs do not alter an already-created run.
These fields are optional as a pair, so existing clients remain compatible.
Run deletion also deletes its submission identity; do not delete runs while
clients may still reconcile or repeat their submissions.
Canceling an unknown submission#
POST /runs/by-idempotency-key/{key}/cancel accepts an empty body and returns
{idempotency_key, canceled: true, run_id, state}. If submission has not yet
arrived, run_id and state are null: the server stores only a cancellation
reservation, not a fabricated operation. A delayed creation with that key is
rejected with HTTP 409, detail: "submission_canceled". Lookup of such a
reservation returns the same 409. Reservations do not appear in run lists,
statistics or the processing queue.
If the operation already exists, the endpoint cancels it and returns its ID and
state. Already terminal operations retain their original state. Repeated calls
are safe, including after an uncertain network response. Stale worker writes
cannot resurrect an operation canceled through this endpoint. The capability
cancellation_by_submission_key advertises this guarantee. Keep cancellation
reservations for as long as a client might deliver the original submission.
Next steps#
Monitor and Manage an OpRun: Track progress, retrieve outputs, cancel, or retry runs.
Consume Events by Topic: Track many runs at once by tailing their events from a shared topic feed.