Skip to main content

Your First Workflow

JJHub workflows are TSX files stored in your repository under .jjhub/workflows/. They use Smithers JSX components wrapped by the @jjhub-ai/workflow package.

Project Setup

The .jjhub/ directory at your repository root is a Bun workspace member with its own package.json and tsconfig.json. This gives you full LSP support (autocomplete, type checking, go-to-definition) when editing workflows.

.jjhub/package.json

.jjhub/tsconfig.json

Root package.json

Add .jjhub and packages/* to your Bun workspaces so the @jjhub-ai/workflow dependency resolves:
Then run bun install to link the workspace. The @jjhub-ai/workflow package lives at packages/workflow/ and re-exports Smithers JSX components (Workflow, Task, Parallel, Sequence, Branch, Ralph) plus the on trigger builders.

Create a Workflow File

Coming Soon: We are actively working on a first-class feature to allow you to run these exact same workflows entirely on your local machine for rapid testing and debugging! Check our Roadmap for more details.

Trigger a Run

Workflows run automatically on configured events (push, landing request opened, schedule, etc.). To manually trigger a workflow:

Manual Dispatch with Inputs

Workflows can declare inputs that users provide when triggering a run manually. This is useful for deploy workflows, release workflows, or any workflow that needs runtime parameters.

Defining Inputs

Use the on.manualDispatch trigger to declare the inputs your workflow accepts:

Input Types

Each input supports the following properties:

Triggering via CLI

Pass inputs using the --input (or -i) flag, one per key-value pair:
If a required input is missing, the CLI returns an error:
If an invalid value is provided for a choice input:

Triggering via API

Send a POST request to the workflow dispatches endpoint with inputs in the request body:
API endpoint: Request body: The response returns the created workflow run object.

Accessing Inputs in Workflow Code

Inside any task, access inputs via ctx.input:
For workflows triggered by other events (push, landing request, schedule), ctx.input is an empty object.

View Runs

Scheduled Triggers

Workflows can run on a schedule using CRON expressions. This is useful for nightly builds, periodic reports, dependency checks, and any recurring automation.

Defining a Schedule

Use on.schedule() in your triggers array with a standard CRON expression:

CRON Syntax

Schedules use standard five-field CRON syntax:

Common Patterns

Timezone

All schedules run in UTC. Adjust your CRON expressions accordingly. For example, if you want a nightly build at midnight US Eastern (UTC-5), use 0 5 * * *.

Multiple Schedules

A workflow can have multiple schedule triggers, and can combine schedules with other trigger types:

How Scheduled Workflows Run

Scheduled workflows are managed by the JJHub scheduler on the server side, not triggered by push events or user actions. When a schedule fires:
  1. The scheduler matches the CRON expression against the current UTC time
  2. A workflow run is created targeting the default bookmark (typically main)
  3. The run is queued and assigned to a runner pod from the warm pool
  4. Execution proceeds identically to any other workflow run (same logs, SSE streaming, commit statuses)
You can view scheduled runs the same way as any other run:

AI Agent Steps

Workflows can invoke AI agents as tasks using the agent prop:
To use AI agents in workflows, configure your API key as a repository secret:

Schema-Driven Workflows

For AI agent workflows that pass structured data between tasks, use createSmithers to define output schemas with Zod. This gives you type-safe ctx.output() for reading previous task results and automatic SQLite-backed persistence.

How It Works

The simple export default (ctx) => <Workflow> pattern (shown earlier) works for compute tasks that just run shell commands. Use createSmithers when tasks need to pass structured data to each other.

Next Steps