execute runs a deployed workflow definition. It resolves a session, creates one execution against it, prints
the debugger URL, and — with --watch — tails the execution’s events until it reaches a terminal status.
It is the command that closes the loop after deploy: the same manifest that
says what to deploy also says what to run, so a CI job can deploy a revision and exercise it without knowing an
id.
Synopsis
--definition behaves differently here than anywhere else in the group: it is required and takes one
reference, not a repeatable filter. One invocation is one execution.
What it does
- Resolves the blob and revision. This is a read — a
commit-phase revision executes fine. - For a bare alias (no
/), lists the revision’s definitions and matches the manifest, refusing an alias the manifest does not carry withDEFINITION_NOT_ACCESSIBLE. - For a bare alias, refuses one the manifest declares only as a
playgroundentry withDEFINITION_NOT_EXECUTABLE, and aworkflowentry not deployed on the revision withDEFINITION_NOT_ACCESSIBLE— both before creating a session or an execution. - A qualified reference (containing
/) skips steps 2–3 entirely — it is parsed client-side into aworkflowobject, andcreate_executionresolves and access-checks it server-side in step 6. A qualified reference the platform refuses is therefore refused only after step 5, so a session that step created stays behind. - Resolves
--sessionto an id, creating the session if the reference is a new alias. - Creates the execution, sending
target: {"session": "<id>"}andworkflowas--definitionwas typed —{"definition": "<alias>"}for a bare alias, the parsed object for a qualified reference — and builds its debugger URL. - With
--watch, polls the execution’s events until a terminal status; with--open, launches a browser.
--json the payload carries execution_id, session_id, session_created, definition, status and
url, alongside the envelope’s schema_version. The payload is emitted even when the run fails — the result
is printed before EXECUTION_FAILED is raised, so a --json consumer still gets the execution id it needs to go
look at what happened.
--open launches a browser only when --json is off. The URL is in the payload either way, so a wrapper can
open it itself; a subprocess that opens a browser behind a machine consumer’s back is not a side effect the CLI
takes on its own.
How --session is resolved
Every workflow execution belongs to a session. Omit --session and one is created for this run.
When you do pass a reference, the CLI still resolves it client-side, even though target.session takes
an id or an alias, resolved in the route’s revision, just as get_session does. execute resolves it anyway
for two reasons: a reference that is a new alias needs its session created before an execution can run against
it, and a session that is not open needs to be refused before anything is created rather than surfacing later as
an opaque conflict out of create_execution. So execute calls get_session with whatever you passed, and
sends only the resolved id onward, as target: {"session": "<id>"}. The alias itself is never sent.
What happens when the reference does not resolve depends on its shape, because the platform reports absent and
not yours as the same 403:
A session that resolves but is not open — closed, closing, or deleting — is refused with
SESSION_NOT_OPEN
before the execution is attempted. The CLI will not reopen it for you. Reporting it here, where you can still
act, is the point: the alternative is an opaque conflict out of create_execution after the fact.
The definition is sent as typed
execute sends --definition to create_execution exactly as you typed it: a bare alias as
{"definition": "<alias>"}, a qualified reference as the object its path form parses into. Alias uniqueness is
scoped per (category, alias), so one alias may legally name both a workflow and a playground definition on the
same revision — and the platform looks an alias up in the workflow category only, so the playground one is never
picked instead.
A shared alias resolves the same way in the manifest. --definition takes a bare alias with no category
qualifier, so on a manifest that declares one alias in both categories, execute checks the workflow entry,
whichever of the two the manifest declares first. Only an alias declared solely as a playground entry stops at
DEFINITION_NOT_EXECUTABLE. ls shows each entry with its category.
A qualified reference skips the manifest, so none of this local matching applies to it: the platform resolves
it, with the same category filter on an alias. A qualified reference naming a playground definition by id is
refused by the platform as invalid_definition_category, which execute reports as DEFINITION_NOT_EXECUTABLE.
--watch polls
--watch follows the execution by polling its event listing every two seconds. It does not open a WebSocket. Each
poll reads one page — up to ten events, the platform’s default — created after the last event it printed, since the
platform’s created_since filter is strictly exclusive. When the status goes terminal it reads one more page, so
the final lines of a fast workflow usually print.
The printed tail is not the complete record. Event timestamps are not unique, and the events index is updated a
moment after each write, so an event that shares the last printed event’s created_at, or is indexed after a later
event was read, can be skipped. A run that ends with more unread events than the final page holds loses the rest.
The execution’s full event log — the debugger, or
List Execution Events — is the authority.
Events print one per line as they arrive, as the event’s type and message joined by a colon. An event with no
message prints its type alone:
- A terminal
failedstatus raisesEXECUTION_FAILEDafter the result is printed. The events above the error are the platform’s own account of what went wrong. - Fifteen minutes without a terminal status raises the advisory
EXECUTION_WATCH_TIMEOUTand stops tailing. The execution is still running on the platform and is unaffected — only the tail gave up. The status in the payload is the last one actually observed, not an empty value.
--watch the command returns as soon as the execution is created, and the reported status is whatever
the platform assigned at creation — typically creating. That is the right shape for fire-and-forget; it is not
a claim that the run succeeded.
When the outcome is unknown
Creating the session and creating the execution are writes, and the CLI repeats a write only when the failure proves it never ran: an HTTP 429, which is API Gateway’s throttling, or a connection that was never made. A 5xx, a body that is not JSON, a read timeout or a dropped connection can arrive after the platform has done the work, so those surface at once instead of being retried:- Creating the execution raises
EXECUTION_OUTCOME_UNKNOWN: a run may have started. The message names the session and links its page in the web debugger, which lists the session’s executions. Look there before running the command again — running it blind can start a second run. - Creating the session keeps its transport code,
API_TRANSIENT_ERRORorAPI_NETWORK_ERROR, and says the session may exist but nothing has run in it, so running the command again is safe. With the same--sessionalias, the rerun finds that session and uses it.
API_RATE_LIMITED or API_NETWORK_ERROR once its retries run out: nothing
ran, so running the command again is safe.
Errors
EXECUTION_FAILED is the one code here that means the platform did its job: the definition ran and the run
failed. Everything above it means the run never started. EXECUTION_OUTCOME_UNKNOWN means it may have.
Every code above, with its remediation, is in Error codes.
See also
blobhub workflow deploy— what puts the definition on the revision in the first place.blobhub workflow ls— every definition on the revision, with its category.blobhub workflow check— static validation, which is a different question from whether a run succeeds.- Session lifecycle — what an execution belongs to, and what
openmeans. - Execution events — the stream
--watchprints. - The workflow reference — the
workflowobject and its path form, in full.

