motion.yaml
motions check parses motion.yaml strictly: an unknown key, a misplaced field or a reference to something that doesn’t exist is an error, reported with its path, such as steps[2] (people).cap.per_company_usd: Too small.
Top level
Section titled “Top level”| Key | Type | Default | |
|---|---|---|---|
motion |
id | the folder’s name | The motion’s id. Lowercase letters, digits and _, starting with a letter. |
title |
string | the id | What the app shows. |
timezone |
IANA zone | the tenant’s | The zone the calendar resolves in, such as America/Sao_Paulo. |
approvers |
handles | required | At least one. They approve changesets, release checkpoints, upgrade batches, accept suggestions, make versions live, and can answer any queue. |
reasons |
ids | none | When given, every hold, drop or done reason a step returns must be one of them, or the step fails. |
input |
{ list } |
none | list: the CRM list a batch opens on unless someone picks another. |
calendar |
map of id → calendar entry | none | Named instants, resolved when a batch opens. |
steps |
list of steps | required | At least one, in order. |
queues |
map of question type → queue | none | Who answers each question type. |
Every step has:
| Key | Type | Default | |
|---|---|---|---|
id |
id | required | Unique in the motion. Facts are stored under it: company.facts.<id>. |
kind |
company, batch, checkpoint, changeset |
company |
See Batches and lanes. |
title |
string | the id | What the batch screen shows. |
after |
step ids | the step before | The steps it runs after. Each must be earlier in the list. |
company and batch steps
Section titled “company and batch steps”| Key | Type | Default | |
|---|---|---|---|
run |
path | required | The step’s file, relative to the motion folder: steps/identity.ts. |
sources |
operation ids | none | The source operations it may call, built-in (rdap.lookup) or custom (brasilapi.cnpj). |
crm.read |
companies, contacts, deals, owners, notes |
none | The CRM objects it may read. |
crm.propose |
companies.update, contacts.create, contacts.update, associate, notes.create, notes.pin |
none | The changes it may propose. Needs a changeset step after it. |
cap |
{ per_company_usd?, per_batch_usd? } |
no cap | The most it may spend on sources, in US dollars, per company and per batch. Positive numbers. |
retries |
0–10 | 2 | How many times a passing failure (timeout, rate limit) is retried before the step fails. |
when |
{ fact, in } |
always runs | Company steps only. Runs only when the value at fact is one of in. fact is a path starting with core, fields, or an upstream step’s id: core.country, fields.segment, fit.tier. |
checkpoint steps
Section titled “checkpoint steps”| Key | Type | Default | |
|---|---|---|---|
until.at |
calendar key or duration | none | Releases once this time has passed, measured from when the batch opened. At this time, blocking questions still open upstream take their defaults. |
until.event |
name | none | Releases once this event has happened in the batch. |
until.manual |
boolean | false |
Releases only when an approver chooses Release. |
With no until, a checkpoint releases when every company still moving has reached it. With at and event, both must hold.
changeset steps
Section titled “changeset steps”| Key | Type | Default | |
|---|---|---|---|
approval |
required, auto |
required |
auto approves the changeset as soon as it seals. |
run, sources, crm, cap and retries aren’t allowed on checkpoints and changesets; when only on company steps; until only on checkpoints; approval only on changesets.
queues
Section titled “queues”Keyed by question type: a question of type identity goes to the identity queue.
| Key | Type | Default | |
|---|---|---|---|
title |
string | the type | What the app shows for the queue. |
owner |
handle | the first approver | Who answers. The approvers can too. |
deadline |
calendar key or duration | none | When an unanswered question takes the default, measured from when it was asked. |
default |
hold, drop, continue, recommended |
hold |
What the question gets at its deadline. recommended picks the question’s recommended option; continue picks it too, or else the first option that continues. |
A question type with no queue goes to the first approver, with no deadline, defaulting to hold.
calendar
Section titled “calendar”Each entry is one of:
| Form | Resolves to |
|---|---|
{ in: 2d } |
that long after the batch opened |
{ weekday: mon, at: "18:00" } |
the next such weekday and time after the batch opened, in the motion’s time zone. Weekdays are sun to sat. |
{ at: "2026-12-01T09:00:00-03:00" } |
that instant |
Durations
Section titled “Durations”A number and a unit: 30s, 15m, 4h, 2d. Decimals work: 1.5h.
Example
Section titled “Example”title: Weekly batchapprovers: [hugo]input: { list: weekly }reasons: [not_icp, duplicate, open_deal]calendar: manager_answers: { weekday: mon, at: "18:00" } distribution: { weekday: wed, at: "13:00" }
steps: - { id: twins, kind: batch, title: Find duplicates, run: steps/twins.ts, crm: { read: [companies] } } - id: identity title: Match the CNPJ run: steps/identity.ts sources: [cnpj.match, rdap.lookup] cap: { per_company_usd: 0.03 } - id: gate title: Check the fit run: steps/gate.ts crm: { read: [deals, owners] } - id: people title: Find people run: steps/people.ts sources: [harvestapi.lead_search, harvestapi.profile] crm: { read: [contacts], propose: [contacts.create, associate] } cap: { per_company_usd: 0.40, per_batch_usd: 80 } - { id: hold_until_wednesday, kind: checkpoint, until: { at: distribution } } - { id: write_contacts, kind: changeset, title: Write contacts }
queues: identity: { owner: hugo, deadline: 4h, default: hold } open_deal: { owner: ari, deadline: manager_answers, default: recommended }Motions is built by Pruma. These docs describe what the platform does today; Limitations lists what it doesn't do yet. Open the app