Skip to content

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.

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.
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.
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.

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.

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.

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

A number and a unit: 30s, 15m, 4h, 2d. Decimals work: 1.5h.

title: Weekly batch
approvers: [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