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

# Overview

> Learn how to build and run workflows.

A workflow is a reliable sequence of steps written in TypeScript. Use one when you already know the order of work: call an action, prompt an agent, branch on the result, wait for approval, then continue.

Keystroke records each action, agent, or LLM step as it finishes. If a later step fails or the run is retried, the workflow resumes from the first unfinished step instead of starting over.

## Example requests

Ask your coding agent for an automation with known steps. It can turn that request into a workflow whose steps are tracked, retried, and inspected.

> "When a new signup comes in, research the account, score the lead, add it to Salesforce, and post a brief to Slack."

> "Every Friday, collect closed deals from HubSpot, generate a sales summary, and email it to the leadership team."

> "When a support escalation is approved, create a Linear issue, notify the account owner, and wait for a human resolution before closing the loop."

## How workflows are defined

In Keystroke, workflows live in your project code under `src/workflows/`. Each file default-exports a `defineWorkflow()` definition with typed input and output, and the runtime discovers it when you run or deploy the project.

```ts src/workflows/signup-pipeline.ts theme={null}
import { defineWorkflow } from "@keystrokehq/keystroke/workflow";
import { z } from "zod";
import { researchSignup } from "../actions/research-signup";
import { postBrief } from "../actions/post-brief";

export default defineWorkflow({
  slug: "signup-pipeline",
  description: "Research a signup lead and post a brief to Slack.",
  input: z.object({ name: z.string(), email: z.string().email() }),
  output: z.object({ brief: z.string() }),
  async run(input) {
    const { brief } = await researchSignup.run(input);
    await postBrief.run({ text: brief });
    return { brief };
  },
});
```

The `run` function is normal `async`/`await` code. Each `.run()` (or agent `.prompt()`) call is recorded as a durable step, so the workflow can replay completed steps instead of repeating them.

## What workflows can do

| Capability                 | How it works                                                                                  |
| -------------------------- | --------------------------------------------------------------------------------------------- |
| **Typed input and output** | Zod schemas validate the payload going in and the result coming out                           |
| **Action steps**           | Call any [action](/learn/actions/overview) with `.run()`, your own or one from an integration |
| **Agent steps**            | Prompt an [agent](/learn/agents/overview) with `.prompt()` when a step needs judgment         |
| **LLM steps**              | Use `promptLlm()` for a one-shot model call without defining a full agent                     |
| **Durability**             | Completed steps are recorded and replayed, so retries resume instead of restarting            |
| **Durable waits**          | `ctx.sleep()` and `ctx.hook()` suspend a run for a delay or until it is resumed externally    |
| **Sandbox**                | An optional `/workspace` shared with agent steps for file and code work                       |

Workflows are one of the main primitives in a project, alongside [agents](/learn/agents/overview), [actions](/learn/actions/overview), and [triggers](/learn/triggers/overview). Reach for a workflow when the work is a known sequence that should run reliably; reach for an [agent](/learn/agents/overview) when the work needs open-ended reasoning. The two compose: a workflow can prompt an agent as a step, and an agent can run a workflow as a [tool](/learn/agents/build-agents#workflows-as-tools).

## How to run workflows

Most workflows run from a [trigger](/learn/triggers/overview), such as a webhook, schedule, poll, or app event attached to the workflow. While building, run them directly from the CLI:

```bash theme={null}
keystroke workflows run signup-pipeline --input '{"name":"Ada","email":"ada@example.com"}'
```

See [run workflows](/learn/workflows/run-workflows) for triggers, the HTTP API, and using a workflow as an agent tool.

## Running deployed workflows

Deploy your project, then run the workflow against the deployed project:

```bash theme={null}
keystroke deploy --project <slug>   # or --filter workflows/signup-pipeline
keystroke workflows run signup-pipeline --input '{"name":"Ada","email":"ada@example.com"}'
```

You can also run a local server with `keystroke dev` and the same commands target it instead. The CLI chooses local or cloud based on the active target; see [targets: local vs cloud](/cli#targets-local-vs-cloud).

## Next steps

<CardGroup cols={2}>
  <Card title="Build workflows" href="/learn/workflows/build-workflows">
    Define workflows with typed input, steps, durability, and waits.
  </Card>

  <Card title="Run workflows" href="/learn/workflows/run-workflows">
    Start runs from the CLI, triggers, the API, and agent tools.
  </Card>

  <Card title="Test workflows" href="/learn/workflows/test-workflows">
    Run workflows in tests and assert their output.
  </Card>

  <Card title="Workflow runs" href="/learn/logs/workflow-runs">
    Inspect input, output, steps, errors, and traces.
  </Card>
</CardGroup>
