Workflows
A Workflow chains multiple Routines into an ordered pipeline on a single cron schedule. Where a Routine is one agent task, a Workflow is a sequence of Routines that run one after the other — with per-step failure handling and a shared run history.
Use a Workflow when you have a series of tasks that should happen in a fixed order and you want one schedule to drive all of them.
Routine vs. Workflow
| Routine | Workflow | |
|---|---|---|
| What runs | One agent prompt | Ordered sequence of Routines |
| Schedule | Its own trigger.cron | One shared cron for all steps |
| Failure handling | Stop on error | Per-step on_failure: stop | continue |
| Output | One Inbox notification | One notification per step that runs |
| File location | ~/.huginn/routines/{slug}.yaml | ~/.huginn/workflows/{id}.yaml |
Your first Workflow
Start by creating the Routines you want to chain. Use trigger.mode: manual so they don’t fire on their own — only the Workflow will trigger them.
# ~/.huginn/routines/standup-prep.yaml
id: "rtn-standup-001"
name: "Standup Prep"
enabled: true
trigger:
mode: manual
agent: Chris
prompt: |
Review the git log for commits since yesterday at 5pm.
List each commit with its author and a one-line summary.
Then list any open PRs and their current review status.
Format the output as a standup-friendly bullet list.
timeout_secs: 120
# ~/.huginn/routines/morning-review.yaml
id: "rtn-morning-review"
name: "Morning PR Review"
enabled: true
trigger:
mode: manual
agent: Mark
prompt: |
Review all open PRs in this repository.
For each one: what does it change, are tests included, any obvious issues?
Flag PRs that need attention.
timeout_secs: 300
Now create the Workflow:
# ~/.huginn/workflows/morning-cycle.yaml
id: "wf-morning-cycle"
name: "Morning Dev Cycle"
description: "Standup prep + PR review every weekday morning"
enabled: true
trigger:
mode: schedule
cron: "0 8 * * 1-5" # weekdays at 8am
steps:
- routine: standup-prep
on_failure: stop
- routine: morning-review
on_failure: continue
- routine: dep-scanner
on_failure: continue
When this fires at 8am on weekdays, it runs standup-prep first. If that step fails, execution stops (on_failure: stop). If it succeeds, morning-review runs. If morning-review fails, the pipeline continues to the next step anyway (on_failure: continue).
Slug resolution: The
routine:value is the filename stem of the Routine YAML — not theidfield inside it.routine: standup-prepresolves to~/.huginn/routines/standup-prep.yaml.
Variable substitution
Routines can declare variables that Workflows override per-step. This lets you write one Routine and reuse it with different parameters.
Declare variables in the Routine’s vars block:
# ~/.huginn/routines/pr-review.yaml
vars:
TARGET_BRANCH:
description: "Filter PRs targeting this branch"
default: "main"
required: false
REVIEWER_TEAM:
description: "GitHub team slug to check for assignments"
default: ""
required: true
prompt: |
Review open PRs targeting {{TARGET_BRANCH}}.
Check whether members of {{REVIEWER_TEAM}} have been assigned as reviewers.
Override per-step in the Workflow:
steps:
- routine: pr-review
on_failure: stop
vars:
TARGET_BRANCH: "release/v2"
REVIEWER_TEAM: "platform-eng"
Variable substitution is a simple string replace — not a template engine. There are no loops, conditionals, or filters. Required variables with no value cause the step to fail immediately.
Workflow YAML reference
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Stable unique identifier. Used in file paths and API routes. |
name | string | Yes | Display name in the web UI. |
description | string | No | Optional description. |
enabled | bool | Yes | false loads the Workflow but does not schedule it. |
trigger.mode | enum | Yes | schedule or manual. |
trigger.cron | string | When mode: schedule | Standard 5-field cron expression. |
steps | array | Yes | Ordered step list. Steps run sequentially. |
steps[].routine | string | Yes | Slug of the Routine to run (filename stem). |
steps[].on_failure | enum | No | stop (default) or continue. |
steps[].vars | map | No | Variable overrides for this step. |
Failure handling
on_failure | Behavior |
|---|---|
stop (default) | Halt. Subsequent steps don’t run. Overall status: failed. |
continue | Log the failure, run the next step. Overall status: partial if any step failed. |
Use stop for steps that later steps depend on. Use continue for optional, non-critical steps.
Run status values
| Status | Meaning |
|---|---|
completed | All steps ran and succeeded. |
failed | A stop step failed. Pipeline halted. |
partial | One or more continue steps failed. Pipeline ran to completion. |
Managing Workflows in the web UI
Open huginn tray → http://localhost:8421 and navigate to /workflows.
From there you can:
- Enable / disable without editing YAML
- Run Now — trigger immediately, ignoring the cron schedule (useful for testing)
- Manage steps — add, reorder, or remove steps inline
- View run history — per-step status breakdown for every past run
Changes take effect immediately. No restart required.
Trigger via API
# Fire a Workflow immediately
curl -X POST http://localhost:8421/api/v1/workflows/wf-morning-cycle/run
# Check run history
curl http://localhost:8421/api/v1/workflows/wf-morning-cycle/runs
Run history storage
Each Workflow maintains an append-only history at:
~/.huginn/workflows/{id}.runs.jsonl
Each entry includes workflow_id, started_at, completed_at, status, and per-step details. Entries are never pruned automatically.
Design constraints (v1)
- No inter-step data passing. Each step’s prompt is static. Steps communicate only through side effects (files written, memory stored, notifications posted). This keeps each Routine independently testable.
- No nested Workflows. A step must be a Routine, not another Workflow.
- No conditional branching. The only control flow is
on_failure: stop | continue. Express conditional logic inside a single Routine’s prompt.
Tips
- Test each Routine individually first. Use Run Now or the REST API to confirm output before wiring into a Workflow.
- Use
on_failure: continuefor optional steps. A slow dependency scan shouldn’t block your PR review. - Use
trigger.mode: manualfor Workflow-only Routines. They won’t pollute the Inbox with solo runs. - Keep Routines read-only for unattended safety. Write and exec tools require approval by default.
See also
- Routines — single-agent cron tasks, the building blocks of Workflows
- Named Agents — creating custom agents for specific Routine tasks
- Permissions — permission tiers in headless mode