clay (@clay-run/cli), autumn (@autumnai/cli),
jq, Python with requests, and AUTUMN_API_KEY set.
Read from Clay only. Don’t write to the CRM until step 7. Never print an API key.
1. Check tools
clay login or autumn login. Ask which table
to move.
2. Export from Clay
3 (auth_forbidden), the Clay plan may not include table reads.
Don’t work around it. Ask the user for a CSV export (Actions → Export → Download CSV)
and for each enrichment and AI column’s purpose and prompt. Then turn the CSV into the same
files, so the scripts below work unchanged:
csv_to_export.py
rowCount.
What you get:
Bulk enrichment tables return only a 20-row sample (
truncated: true); use the original input
list instead.
3. Write the mapping
Sort each column:
Write
clay-to-autumn.json. Describe what each research value means, not which provider
found it:
keymust uniquely identify a row in the user’s systems. If there is none, ask.- Don’t put the key in
research. It comes back on every row as an input column. - Other input columns can come back corrected or not at all, so research fields must not
reuse input names. Ask for a corrected value as its own field (
resolved_domain). researchcan include fields Clay didn’t have.logic,routingandrulescan be empty ({}). Put a per-row check that matters downstream inrules, for example{"b2b": "Sells mainly to businesses."}. Name rules in snake_case: Autumn returns each one asrule_<name>and step 5 looks for that exact field.- A run condition on a research column (
conditionalRunFormulaText) goes in that field’s description, for example “only when domain is set”. toleranceis how far apart two numbers can be and still agree in step 5.
4. Run a sample
build_task.py
autumn wait returns after about 100 seconds with exit code 3 while the task is still
working, so the loop waits again until the task finishes.
- Include a few messy rows (empty domain, name that doesn’t match its domain).
autumn wait --jsonreportscredits_used. Scale it byrowCountintable.jsonand tell the user before the full run.- Rules come back as
rule_<name>fields (matchorunclear), and Autumn can add rule fields of its own. Hold any row where a rule you asked for is missing or anyrule_field isn’tmatch. - Check the output field names against the mapping (
autumn rows "$TASK_ID" --format json). Autumn can normalize a field name (in one testfull_namecame back asname). In step 5 that shows as “Autumn filled 0/N”. Map the name back in code; don’t ask the task to rename it.
5. Compare with Clay
compare.py
results/<task_id>/, so batches don’t overwrite each other.
Rows that were sent but not returned go into the next batch again. held_rows.json lists
each held row with its problems: a rule that isn’t match or is missing, a key that wasn’t
sent, or a key that came back twice. Only autumn_rows.json goes on to the CRM.
The one disagreement was a row whose input domain belonged to a different company: Clay had
enriched the wrong one, and resolved_domain caught it. For each disagreement, ask which
value is current. Every Autumn value has a source: open app_url from step 4 to see the page
behind each one.
Show the user the summary and disagreements.csv, and wait for a yes.
Read rows as JSON. The CSV export prefixes values starting with +, -, = or @
with an apostrophe, which changes phone numbers. See
Outputs and sources.
6. Full run
Run the rest in batches with the same mapping, for example 100 rows at a time:compare.py
reads task.json to know which rows were sent. Keep each batch on input_rows.
Attach a CSV starts from a draft task, and output and rules only
apply when a task is created.
When every batch is done, combine the approved rows:
logic columns in code and rename fields back to their Clay column names.
7. Cut over
- Run Clay and Autumn side by side for one cycle. Only Clay writes to production.
- Point the user’s routing code at the Autumn rows, same CRM fields, same names.
- When the user says so, pause the table’s schedule and signals in Clay. Keep the table.
Filter searches
When the table’s rows come from Find Companies or Find People.
Signals
Move signals onto your own schedule.