> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blobhub.io/llms.txt
> Use this file to discover all available pages before exploring further.

# blobhub workflow execute

> Create an execution of a workflow definition, and with --watch follow it to completion

`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`](/cli/workflow/commands/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

```bash theme={null}
blobhub workflow execute -f <manifest> --definition <alias> [--session <ref>] [--watch] [--open]
```

| Flag           | Default       | Description                                       |
| -------------- | ------------- | ------------------------------------------------- |
| `--file`, `-f` | required      | Path to the workflow manifest.                    |
| `--definition` | required      | Alias of the workflow definition to execute.      |
| `--session`    | a new session | Session alias or id; created if the alias is new. |
| `--watch`      | off           | Follow execution events until the run finishes.   |
| `--open`       | off           | Open the execution in the web debugger.           |

`--definition` behaves differently here than anywhere else in the group: it is **required** and takes **one**
alias, not a repeatable filter. One invocation is one execution.

## What it does

1. Resolves the blob and revision. This is a read — a `commit`-phase revision executes fine.
2. Lists the revision's definitions and matches the manifest, refusing an alias the manifest does not carry with
   `DEFINITION_NOT_ACCESSIBLE`.
3. Refuses a `playground` entry with `DEFINITION_NOT_EXECUTABLE`, **before** creating a session or an execution.
4. Resolves `--session` to an id, creating the session if the reference is a new alias.
5. Creates the execution and builds its debugger URL.
6. With `--watch`, polls the execution's events until a terminal status; with `--open`, launches a browser.

```text theme={null}
execution 5f2c0a91-... on session 8d41b7e3-...: creating
debugger: https://blobhub.io/acme-corp/checkout/debugger/8d41b7e3-.../5f2c0a91-...
```

Under `--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 resolves it **client-side**, and this is not an implementation detail — it
is forced by an asymmetry in the platform. `create_execution` accepts a session **id only**, while `get_session`
accepts an id *or* an alias. So `execute` calls `get_session` with whatever you passed and hands only the
resolved id onward. 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`:

| The reference | Not resolvable                                                                                                                                              |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| An alias      | Created as a new session. Aliases are unique per revision, so a real collision fails loudly at creation.                                                    |
| A UUID        | `SESSION_NOT_ACCESSIBLE`. Ids are server-assigned; nobody can mint one client-side, so this is a genuine failure rather than a request to create something. |

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 addressed by id, never by alias

The platform can look a definition up by alias, and `execute` deliberately does not use that path. The server's
alias lookup applies **no category filter**, while 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 an alias-addressed
execution would resolve to whichever the query happened to return first.

`execute` already holds the definition's id from the listing it did in step 2, so this ambiguity never reaches
the platform.

**The same shared alias is still worth knowing about locally.** `--definition` takes a bare alias with no
category qualifier, so on a manifest that declares one alias in both categories, `execute` takes the **first**
matching entry in manifest order and does not report the collision. If that entry is the playground one, the run
stops at `DEFINITION_NOT_EXECUTABLE` even though a workflow definition of that name exists. Use distinct aliases,
or declare the workflow entry first. [`ls`](/cli/workflow/commands/ls) shows both, with their categories.

## `--watch` polls, and that is exact

`--watch` follows the execution by polling its event listing every two seconds, remembering the last event's
`created_at` and asking for everything after it. It does not open a WebSocket.

That is not a compromise. The platform's `created_since` filter is **strictly exclusive**, so a poll that resumes
from the last event it saw redelivers nothing and skips nothing — the tail is exact, not merely close enough.
When the status goes terminal, the events are drained once more before returning, so the final lines of a fast
workflow are not lost between the last page and the status read.

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:

```text theme={null}
flow.entered: checkout_flow
processor.entered: pricing
processor.output: Processed 54 tokens successfully.
flow.exited
```

Two outcomes other than success:

* A terminal `failed` status raises `EXECUTION_FAILED` after 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_TIMEOUT` and 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.

Without `--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.

## Errors

| Code                                                                                               | When                                                                                                                                                                                                                                                     |
| -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MANIFEST_NOT_FOUND`, `MANIFEST_INVALID`, `MANIFEST_TYPE_MISMATCH`, `MANIFEST_VERSION_UNSUPPORTED` | The manifest is absent or unusable.                                                                                                                                                                                                                      |
| `DEFINITION_ALIAS_INVALID`, `DEFINITION_CATEGORY_UNKNOWN`, `DEFINITION_NOT_ACCESSIBLE`             | An alias fails the pattern; a category cannot be inferred or contradicts the document; the `--definition` alias is not in the manifest.                                                                                                                  |
| `DEFINITION_NOT_EXECUTABLE`                                                                        | The alias names a `playground` entry. The platform executes workflow definitions only. Nothing was created.                                                                                                                                              |
| `BLOB_NOT_ACCESSIBLE`, `BLOB_NOT_WORKFLOW`, `REVISION_NOT_ACCESSIBLE`, `REVISION_NOT_WRITABLE`     | The target cannot be resolved, or its status is not `ready`. This is a read, so the phase may be `draft`, `commit` or `managed` — anything else raises `REVISION_NOT_WRITABLE`, which the shared resolver raises on the read path too, despite the name. |
| `SESSION_NOT_ACCESSIBLE`                                                                           | `--session` was given a UUID that is absent or not reachable with this key. Pass an alias to find-or-create by name.                                                                                                                                     |
| `SESSION_NOT_OPEN`                                                                                 | The session exists but is not `open`. Refused before the execution is created.                                                                                                                                                                           |
| `EXECUTION_FAILED`                                                                                 | `--watch` followed the execution to a terminal `failed` status. The execution exists; the result payload was already printed.                                                                                                                            |
| `CREDENTIALS_NOT_FOUND`, `PROFILE_NOT_FOUND`, `INSECURE_CREDENTIALS_PERMISSIONS`                   | No usable credential, or a credentials file the CLI refuses to read.                                                                                                                                                                                     |
| `API_RATE_LIMITED`, `API_TRANSIENT_ERROR`, `API_NETWORK_ERROR`                                     | A call failed after its retries.                                                                                                                                                                                                                         |
| `EXECUTION_WATCH_TIMEOUT`, `DEFINITION_LIST_TRUNCATED`                                             | Advisories, on stderr. The exit code stays `0`.                                                                                                                                                                                                          |

`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.

Every code above, with its remediation, is in [Error codes](/cli/error-codes).

## See also

* [`blobhub workflow deploy`](/cli/workflow/commands/deploy) — what puts the definition on the revision in the
  first place.
* [`blobhub workflow ls`](/cli/workflow/commands/ls) — every definition on the revision, with its category.
* [`blobhub workflow check`](/cli/workflow/commands/check) — static validation, which is a different question
  from whether a run succeeds.
* [Session lifecycle](/blob-types/workflow/workflows/session-lifecycle) — what an execution belongs to, and what
  `open` means.
* [Execution events](/blob-types/workflow/workflows/execution-events) — the stream `--watch` prints.
