// DOCS

Workflows

A workflow is a goal with a deadline and a team. It bundles a charter, KPIs, a roster of brains users, an owned board, and a set of paused template automations (progress scorer, task nudger, milestone reviewer, etc.) into one container with shared lifecycle. Flip the workflow's status to active and every attached automation un-pauses together; flip it back to paused or archived and they all stop.

Workflow vs board vs automation

These three primitives compose, and reaching for the right one matters:

You have… Use a…
A list or table you want to track by hand Board
One scheduled program doing one thing Automation
A goal with a deadline, KPIs, and >1 person involved Workflow

A workflow owns a board and several automations. Deleting the workflow (by default) deletes the attached automations but keeps the board — pass delete_board: true if you want the board to go too.

Anatomy of a workflow

workflow
 ├── title              short label
 ├── charter            paragraph of intent — the "why"
 ├── kpis[]             { name, target, unit?, deadline? }
 ├── deadlines[]        { label, date }
 ├── roster[]           { user_id, role: owner | contributor | observer }
 ├── status             draft | active | paused | archived
 ├── board_id           the owned board (auto-provisioned)
 └── automation_ids[]   attached template automations (auto-provisioned, active)

Roster changes cascade onto the owned board's member list: owner → owner, contributor → editor, observer → viewer. Every user on the roster can open the board immediately.

Status is the lifecycle lever. New workflows are created active by default — every attached automation starts firing on its cron immediately. Flip to paused to halt every automation together; archived does the same plus hides the workflow from the default list. draft is still a valid status if you want a workflow you've explicitly opted out of running yet.

Creating a workflow — the right way

Ask Claude:

"Set up a workflow for shipping our v2 launch by Q3 with the launch team."

Claude runs create_workflow_flow which walks you through:

  1. Purpose & success — what is this workflow trying to achieve?
  2. KPIs — 1–4 measurable signals with targets and optional deadlines. ("Engagement" without a number is rejected — push back.)
  3. Deadlines — labeled dates (e.g. "code freeze 2026-07-15").
  4. Roster — which brains users, in what role.
  5. Template automations — pick from the catalog below.
  6. Confirm structure — proposed shape is read back.
  7. Createcreate_workflow provisions in a single transaction: workflow row + owned board + roster + all chosen automations (active).
  8. Review — open /workflows/<id> to eyeball the attached automations. Flip status to paused if you need to halt them.

Everything is created in active state with every automation already running. The cron sweep starts firing them on schedule immediately — flip status to paused if you need to halt the cron.

The template automation catalog

When the playbook asks "which template automations do you want," it's picking from this set. Each is an active automation that knows about the workflow's KPIs, deadlines, and roster:

Template What it does Default cron
progress_scorer Reads the board, scores % done vs KPI, pings the owner if slipping. Daily 9am
task_nudger Finds rows assigned to roster members due in the next window, DMs each member their list via Telegram. Daily 8am
milestone_reviewer LLM-reads activity since last milestone, sends the owner a recap (blockers + completions). Fri 6pm
agentic_summary LLM-generates a progress summary, appends to the board's summaries dataset, dashboard renders the latest. Every 2 days, 9am
monday_migration_sync Lists all Monday boards (active + archived) via source_query, upserts one task row per board on the workflow board, auto-classifies by name. Hourly
deadline_radar Scans the workflow's deadlines, alerts on anything inside the warning window (default 7d) or overdue. Daily 9am
blocked_items_alert Lists every row currently status=blocked and pings the owner. Weekdays 10am
kpi_pulse LLM-grades each KPI against current board state and sends a red/yellow/green pulse per KPI. Weekly Mon 9am
weekly_roster_digest LLM-summarises the week and Telegram-broadcasts it to every contributor + owner. Observers excluded. Fri 5pm
standup_collector Pings each roster contributor asking for a 3-line standup. Weekdays 9am

You don't have to take them all. Pick the two or three that match how you actually run the project. You can add more later via update_workflow.

Customizing a workflow

update_workflow is the lifecycle and frame editor. Important rules:

  • Passing roster, kpis, or deadlines replaces the array — include every entry you want to keep, not just the diff.
  • status="active" un-pauses every attached automation. paused / archived pause them.
  • The owned dashboard auto-regenerates whenever title, charter, KPIs, or deadlines change. Force a regeneration with regenerate_dashboard: true.
await brains.update_workflow({
  workflow_id,
  status: "active",                       // un-pauses all automations
  kpis: [
    { name: "signed customers", target: 5, deadline: "2026-08-01" },
    { name: "NPS", target: 50, unit: "score" },
    { name: "ARR", target: 250000, unit: "usd" }, // include existing + new
  ],
});

Roster shape:

await brains.update_workflow({
  workflow_id,
  roster: [
    { user_id: "<uuid-alon>", role: "owner" },
    { user_id: "<uuid-noah>", role: "contributor" },
    { user_id: "<uuid-keren>", role: "observer" },
  ],
});
// Cascades onto the owned board automatically.

Customizing the attached automations

Each template automation is a real automation — same Deno sandbox, same tool grants, same caps. Edit it with update_automation and your edits stick. The workflow doesn't overwrite template automations on status changes; it only pauses/un-pauses them.

If a template doesn't fit, you can:

  • Delete it (delete_automation) — the workflow still works without it.
  • Replace it by creating a custom automation from scratch (create_automation_flow) and attaching it to the workflow via update_workflow attachment={ automation_ids: […] }.
  • Tweak its grants or cron with update_automation — typical edits: change the morning hour, expand the dedupe key, hand the automation an extra http_fetch host.

Smoke-test every newly-created automation right after creating the workflow. Use run_automation_once on each attached template to confirm it does what you expect. Workflows now create attached automations as active by default, so a broken template starts firing on real cron the moment the workflow is created — catch it before the next cron tick.

Lifecycle

active       ← default on create; all attached automations firing on cron
  ↓ update_workflow status=paused
paused       ← automations paused, workflow still visible
  ↓ update_workflow status=active
active       ← un-pauses every attached automation
  ↓ update_workflow status=archived
archived     ← hidden from default lists, automations paused

(draft is still a valid status — explicit opt-in for "don't run yet")

delete_workflow cascades to the attached automations by default but keeps the owned board unless you pass delete_board: true. This is deliberate — the board often holds historical data the user wants to preserve even after the project wraps.

Roster roles

Role Brain access Board write Workflow edit
owner yes yes yes
contributor yes yes (editor) no
observer yes read-only no

Owners can flip status, edit KPIs/deadlines/roster/title, and delete the workflow. Contributors can write to the board (the work surface). Observers can read everything but can't write — useful for executives, clients, or auditors who need visibility without permission to muck with the data.

Tool surface

Tool Purpose
create_workflow_flow Guided multi-step authoring. Use this.
create_workflow Raw create — only for reproducing existing workflows.
list_workflows List workflows in a brain.
get_workflow Read workflow + roster + attached automations.
update_workflow Edit charter, KPIs, deadlines, roster, status.
delete_workflow Delete (cascades automations; board kept unless delete_board: true).