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

# Workflow Reference

> The workflow object that names what to run, separately from where it runs.

A `workflow` reference names what to run — an organization, blob, revision and definition anywhere the caller
can read — separately from where it runs. Where it runs is the command's `target`; every API that names a
workflow takes the same two objects:

| Command | `target` — where it runs | `workflow` — what it runs |
| :- | :- | :- |
| [Create Execution](/blob-types/workflow/operations/create-execution) | `{session}`, in the route's revision | a reference |
| A schedule's [invocation target](/blob-types/scheduler/overview#invocation-targets) | `{org, blob, revision, session}` | a reference |

## The three shapes

```json theme={null}
{"org": "<id|alias>", "blob": "<id|alias>", "revision": "<id|default>", "definition": "<id|alias>"}
```

| Shape | Names | Meaning |
| :- | :- | :- |
| `{definition}` | one field | a definition in the target's own revision — the route's for `create_execution`, `target.revision` for a schedule |
| `{blob, revision, definition}` | `blob` is an id | the organization is the blob's own |
| `{org, blob, revision, definition}` | `blob` may be an id or alias within `org` | fully qualified |

* `org` is required exactly when `blob` is an alias; given with a blob id, it must name that blob's organization.
* `revision` is required whenever `blob` is given — no default-to-`default`.
* Any other combination (a `revision` without a `blob`, a `blob` without a `revision`, an `org` without a `blob`,
  a blob alias without an `org`) is refused with 400 `invalid_workflow_reference`.
* Every value is a non-blank string of at most 64 characters; a blank, over-length or non-string value is refused
  with 400 `invalid_workflow_reference`.
* A `definition` value shaped like a canonical UUID is an id; anything else is an alias.
* Used verbatim in both `create_execution`'s `workflow` field and a schedule's `invocation_target.workflow`.

## Resolution and access

A caller can run a definition exactly when `download_definition` on the definition's own revision would
succeed: READ on the source blob, the blob is `workflow`-typed and readable, the revision passes `data/query`'s
gate, and the definition is in the `workflow` category. Every failure before the category check answers the
identical 403 — you can run what you could download, and no reference can become an oracle for another
organization's contents.

An alias is looked up in the `workflow` category only, so a `playground` definition sharing it is never picked. A
definition **id** naming a `playground` definition the caller can reach is refused with 400
`invalid_definition_category`. An org-scoped API key reaches no other organization, so it can name definitions only
in its own.

## Whose rules apply

Everything a run depends on comes from where it **runs** — the session, its blob, and the caller's tenant for
credentials — never from the source definition's author:

| Rule | Comes from |
| :- | :- |
| Credentials resolved by alias | the caller's tenant |
| The `logic.code` import allowlist, `workflow.code_imports` | the session's blob |
| Every other limit on the session and its executions — `workflow.executions_per_session`, the run's ceilings, `workflow.session_objects_per_session` | the session's blob |
| `workflow.running_executions_per_org` | the organization of the session's blob |
| Every write and event | the session |

A shared workflow only runs where the runner holds the same credential aliases and allows the same imports. See
[How a value is chosen](/general/limits#how-a-value-is-chosen).

## The path form

One string, `/`-separated, in the same three shapes: `definition`, `blob/revision/definition` (where `blob` must be
an id), `org/blob/revision/definition`. No alias grammar admits `/`, so the split is unambiguous. Two segments,
or more than four, are refused before anything is sent.

It exists only where one string has to hold a reference: the `--definition` argument of
[`blobhub workflow execute`](/cli/workflow/commands/execute) and the port of the playground's
[chat widget](/blob-types/workflow/playgrounds/widgets). Every request body, stored record and manifest carries
the object instead, and the API never accepts the path.

## Where it's used

* [Create Execution](/blob-types/workflow/operations/create-execution)
* [Scheduler overview → Invocation Targets](/blob-types/scheduler/overview#invocation-targets)
* [Scheduler manifest](/cli/scheduler/manifest)
* [CLI Concepts](/cli/concepts)

## Migrating from the removed shapes

<Warning>
  The platform refuses each shape below. Send its replacement.
</Warning>

| Removed | Replaced by |
| :- | :- |
| `create_execution`'s `session_id` | `target.session` — a session id or alias |
| `create_execution`'s `definition_id` or `alias` | `workflow`: `{"definition": "<id or alias>"}` |
| `invocation_target.blob_id` | `invocation_target.target.blob`, with `target.org` when the blob is named by alias |
| `invocation_target.revision` and `invocation_target.session` | `invocation_target.target.revision` and `invocation_target.target.session` |
| `invocation_target.workflow_alias` | `invocation_target.workflow`: `{"definition": "<alias>"}` |
| `invocation_target.description` | the schedule's own `description`, at the top level of `create_schedule` and `update_schedule` |

<CodeGroup>
  ```json Before (removed) theme={null}
  {
    "command": "create_execution",
    "session_id": "8d41b7e3-5c2a-4f90-a1b6-3e7d9c0f2a15",
    "alias": "data-process",
    "input_data": []
  }
  ```

  ```json After theme={null}
  {
    "command": "create_execution",
    "target": {"session": "8d41b7e3-5c2a-4f90-a1b6-3e7d9c0f2a15"},
    "workflow": {"definition": "data-process"},
    "input_data": []
  }
  ```
</CodeGroup>

<CodeGroup>
  ```json Before (removed) theme={null}
  {
    "command": "create_schedule",
    "invocation_target_type": "workflow",
    "invocation_target": {
      "blob_id": "5b0e7c2a-3f61-4d9b-8a47-2c9e1f6d0b38",
      "revision": "default",
      "session": "scheduled_runs",
      "workflow_alias": "daily-report",
      "input_data": [],
      "description": "Daily report for the morning digest."
    }
  }
  ```

  ```json After theme={null}
  {
    "command": "create_schedule",
    "description": "Daily report for the morning digest.",
    "invocation_target_type": "workflow",
    "invocation_target": {
      "target": {
        "blob": "5b0e7c2a-3f61-4d9b-8a47-2c9e1f6d0b38",
        "revision": "default",
        "session": "scheduled_runs"
      },
      "workflow": {"definition": "daily-report"},
      "input_data": []
    }
  }
  ```
</CodeGroup>

The schedule's other fields are unchanged. Schedules, and the run history they recorded, stored in a removed shape
are rewritten to the new shape. See
[Create Execution](/blob-types/workflow/operations/create-execution) and
[Invocation Targets](/blob-types/scheduler/overview#invocation-targets). The CLI's own scheduler manifest carries
a parallel migration — see [The retired layout](/cli/scheduler/manifest#the-retired-layout) for what changes
there.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.