workflows
**Workflows** Author and execute short JavaScript/TypeScript scripts that orchestrate many concurrent leaf agents in a sandbox. Use this skill when a problem breaks into multiple similar subtasks that can run in parallel, such as processing batches of items, analyzing multiple documents, or handling lists of requests. Launch a workflow with `run_workflow`, providing either an inline script or a saved workflow name, and receive a `runId` immediately while the asynchronous execution completes in the background.
git clone --depth 1 https://github.com/vellum-ai/vellum-assistant /tmp/workflows && cp -r /tmp/workflows/assistant/src/config/bundled-skills/workflows ~/.claude/skills/workflowsSKILL.md
A workflow is a short JS/TS script you author that runs in a sandbox and fans work
out across many short-lived **leaf agents**, orchestrated deterministically. Launch
one with `run_workflow` (inline `script` OR saved `name`, exactly one). It returns a
`runId` immediately; the run is asynchronous and you are notified in this
conversation when it completes — **do NOT poll**.
Reach for one when a task decomposes into many similar small sub-tasks that can run
concurrently. For a single task or a quick lookup, do it inline.
## The script model
These are the load-bearing invariants. Get them wrong and the run misbehaves silently.
### Scripts are SYNCHRONOUS — never `await`
Host functions block and return their result directly. Write straight-line code.
```js
const r = agent("Summarize this thread."); // r is the result, right here
```
Do **not** write `await agent(...)`, and do **not** make the script `async`. An
`async` script deadlocks on its second host call — the sandbox can suspend the main
evaluation stack but not a promise continuation.
### Every script begins with a literal `meta`
The first statement must be a pure-literal export — no computed values, template
strings, or concatenation:
```js
export const meta = {
name: "triage-inbox",
description: "Triage and label inbox messages",
};
```
`meta` is extracted **statically**, without executing the script, so it must be a
plain object literal with string `name` and `description`. The `name` is how a saved
workflow is referenced by `workflow(name)` and the scheduler.
### You must `return` the result
The script body runs as a function. Its result is whatever it `return`s at the top
level — a bare trailing expression (e.g. `result;`) is **discarded** and the run
finishes with no result. Always `return` the value you want surfaced.
```js
const result = agent(`Write the final summary: ${JSON.stringify(parts)}`);
return result;
```
### Determinism (this is what makes runs resumable)
Every leaf call is journaled by sequence number and input hash, so a resumed run can
replay the unchanged prefix instead of re-spawning agents. That only holds if the
script is deterministic, so `Date.now()`, `Math.random()`, and argless `new Date()`
**throw**. Pass any timestamps or random seeds in through `args`.
## Host API
All functions are synchronous from the script's perspective.
| Function | Returns | Notes |
| ---------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `agent(prompt, opts?)` | the leaf's result | Runs ONE leaf. **Throws** on leaf failure (fails the whole run). |
| `leaf(prompt, opts?)` | a leaf descriptor | Runs nothing on its own; used inside `parallel`/`map`/`pipeline`. |
| `parallel(specs)` | `results[]` | Runs an array of `leaf(...)` descriptors concurrently, results in input order. A failed leaf becomes `null` (never throws). |
| `map(items, build)` | `results[]` | `build(item, i)` returns a `leaf(...)` descriptor per item; runs them like `parallel`. |
| `pipeline(items, ...stages)` | `results[]` | Each `stage(prev, i)` returns a `leaf(...)` descriptor (run an agent) OR a plain value (pass through unchanged — filter/transform locally, no agent spent). Per-stage barrier: stage N+1 starts only after all of stage N finishes. |
| `phase(title)` | — | Marks a named phase for progress reporting. |
| `log(msg)` | — | Emits a progress log line. |
| `usage()` | `{ agentsSpawned, inputTokens, outputTokens }` | Live snapshot so a script can self-moderate. |
| `workflow(name, args?)` | the child's result | Runs a SAVED workflow inline, depth 1 only (a child may not call `workflow()`). |
| `args` | the run input | The `args` object passed to `run_workflow`. |
Use `agent` for a single sequential leaf (throws on failure). Use `parallel`/`map`/
`pipeline` for fan-out (a failed leaf is `null`, so a batch survives a few bad items).
## Leaf options (`opts` for `agent` / `leaf`)
| Option | Type | Effect |
| --------- | -------------------------- | --------------------------------------------------------------------------------------- |
| `schema` | JSON Schema object literal | Forces structured output via a tool. A schema leaf runs with **no tools** (pure judge/extractor). Use a plain JSON Schema literal, not Zod. |
| `label` | string | Short display/diagnostic label for the leaf. |
| `profile` | string | Overrides the model profile. Must exist in `llm.profiles` or the leaf throws. See [Listing profiles](#listing-available-profiles). |
| `persona` | boolean | `true` makes the leaf speak AS the assistant (identity + memory) — use for output meant to be in the assistant's voice. Default is anonymous — use for impartial judgin>
>
>
>
Check Vellum Assistant architecture and package boundaries. Use when editing imports, moving code, adding endpoints, touching assistant/gateway/client/skill boundaries, or reviewing architecture-sensitive changes.
Review Vellum Assistant code changes for correctness, repo-specific quality rules, security risks, and missing validation. Use when reviewing diffs, preparing a PR, finishing implementation work, or when the user asks for a code review, quality pass, or pre-merge check in this repository.
Guide Vellum Assistant feature flag changes and rollout hygiene. Use when adding, editing, reviewing, or documenting assistant feature flags, rollout-gated behavior, or platform flag follow-up work.
Validate Vellum Assistant database and workspace migrations. Use when adding, editing, reviewing, or testing migrations, release-note migrations, persisted schemas, workspace file formats, or data backfills.