Workflows
A Workflow is a sequence of Skills with optional human-in-the-loop approve gates. It's how you compose single-step capabilities into an end-to-end process.
What it does
Every workflow is a small DAG of steps — and workflows are deterministic: the same structure every run. Open-ended agent work belongs in Missions, never in a workflow step. Four step types:
skill— invoke a Skill (typed LLM call) with interpolated input, capture outputsync— incrementally refresh named sources so downstream steps read live dataapprove— pause, route to the Review Queue, resume on decisionaction— call a side-effecting adapter (gmail.send_email, hubspot.update_deal, …)
State persists in workflow_run rows; each step's result lands in a JSONB column and is addressable as {{steps.<name>.output.<field>}} by downstream steps.
If the process dies mid-run, the run sits paused at its last persisted step. Resume from MCP, the dashboard, or a direct oRPC call.
Triggers
A workflow declares only trigger: {type: manual} (with an optional inputSchema for the Run form). Everything time- or event-driven lives in an Automation:
# workspace/<org>/automations/reply-followup.yaml
when: { event: prospect.reply } # or { schedule: "0 12 * * 1-5" }
do: { workflow: discovery_followup }
Workflow-embedded schedule/event triggers from earlier releases still work but warn as deprecated on workspace:apply.
Folder shape
workspace/<org>/workflows/<slug>/
├── workflow.yaml # steps + trigger + input schema (required)
├── evals.yaml # end-to-end fixtures (recommended)
└── README.md # optional — rationale, edge cases
workflow.yaml
slug: discovery_followup
name: Discovery Follow-up
description: Post-discovery-call automation. Summarize, draft, gate, send.
trigger: {type: manual}
inputSchema:
type: object
required: [transcript, prospect_name]
properties:
transcript: {type: string}
prospect_name: {type: string}
steps:
- name: summary
type: skill
skill: discovery_summary
input:
transcript: '{{input.transcript}}'
- name: email
type: skill
skill: draft_followup_email
input:
discovery_summary: '{{steps.summary.output}}'
prospect_name: '{{input.prospect_name}}'
- name: review
type: approve
prompt: Review the drafted follow-up email before sending.
reviews: email
- name: send
type: action
action: gmail.send_email
evals.yaml
End-to-end fixtures — feed an input, assert on final output + intermediate step outputs. Catches regressions where one step's output shape shifts and breaks a downstream step. See Evals.
Runtime
Start a workflow → steps execute sequentially → on approve step, run pauses. Approver reviews at /dashboard/review, clicks approve/reject, optionally rates 👍/👎 with a note. Approve resumes the run from the step after; reject marks it failed. Durable by design — in-flight state lives in Postgres, not memory.
Every run is query-able by status, rating, context SHA — see the logs view.
Connection to other resources
- Skills — every
skillstep invokes one - Agents — an Agent often kicks off a Workflow rather than running a one-shot skill
- Review Queue — the UI surface for every
approvestep across every running workflow
Next
- Quickstart — run your first workflow end-to-end
- Authoring context — the edit + apply cycle
- Evals — fixtures catch breakage before prod
- Feedback + logs — rating runs, measuring outcomes