Skip to main content
Workflows are deterministic orchestration, so unlike agents you can usually write real assertions on their output. Run the workflow with executeWorkflow() and check the result. Where a workflow includes an agent or LLM step, isolate that non-determinism so the rest of the workflow stays easy to assert. Test workflows at the boundary you care about: Run tests from the project root:
Vitest ships with @meetluno/cli. No project vitest.config.ts is required.

Run a workflow in a test

executeWorkflow() runs one durable pass and resolves to a result you can assert on. The result is a discriminated union: completed with output, failed with error, canceled, or suspended when the run hit a durable wait.
For a workflow whose steps are pure or call deterministic actions, asserting the full output like this is the most useful test. Action steps run for real in-process; pass resolveCredentials in the options if they need credentials.

Test durable waits

A workflow with a .sleep() / .sleepUntil() or a hookStep() suspends instead of completing in one pass. executeWorkflow() returns { status: "suspended", items }, where each item’s kind is "sleep" or "hook". Assert that the run suspended where you expect:

Stub agent and LLM steps

In-process, agentStep() and llmStep() call executors you pass to executeWorkflow(): runAgent for agent steps and runLlm for LLM steps. Without them those steps fail, which keeps unit tests from calling a model by accident. Pass stubs to test what the workflow does around an expensive step without running it:
runAgent receives the agent and { message, sessionId?, outputSchema? } and returns { text, sessionId } (plus output when the step declares output). runLlm receives { prompt, model, outputSchema?, … } and returns the text, or the structured object when there is an outputSchema. A sub-workflow step runs inline under local executeWorkflow and uses the same options. Local tests do not create separate child runs or waiting_children suspensions — those only appear on the deployed queued runtime. Assert queued-child behavior against a deployed project (or accept that local inline execution differs).

Definition tests

Definition tests are fast and never run the workflow. Use them to catch accidental slug changes or schema edits that would break callers and triggers.
Because input and output are Zod schemas, you can parse sample payloads against them directly.

Input validation tests

A workflow rejects input that does not match its input schema before any step runs. Assert that bad input is refused.

Testing workflows with agent or LLM steps

A workflow with an agentStep() or llmStep() is no longer fully deterministic, so assert on the parts that are stable rather than exact model text.
  • Test deterministic actions separately. Move logic-heavy steps into actions and unit-test those directly, so the workflow test only has to check orchestration.
  • Assert on shape, not wording. For a step that returns model text, assert the output is a non-empty string or matches a structured outputSchema, not an exact sentence.
  • Guard real model runs. To run an agent step against a real model, pass runAgent that prompts the agent (agent.prompt(input)). Tests that call a real model should skip when no provider key is available, so local and CI runs do not fail without credentials.
Run integration tests from the project root:
Integration tests load .env when present and skip when required keys are unset. Vitest and its config ship with @meetluno/cli — no project vitest.config.ts.

Inspect failing runs

When a test fails, or a real run misbehaves, inspect the run before changing code. From the CLI:
workflows runs get accepts a bare <run-id> or the compound <workflowSlug> <run-id>. The steps include shows each recorded step (including input and output when available) and where the run failed. Pass children to embed nested child-run detail at the same include depth. For deployed workflows, use History in the web app and filter to workflow runs; the detail panel shows input, output, steps, errors, and trace data. See workflow runs.

Next steps

Build workflows

Compose actions, agents, and durable steps.

Run workflows

Start runs from the CLI, triggers, the API, and agent tools.

Workflow runs

Debug failed runs in the web app.

Deploy a project

Run tests before deploying changed workflows.