Your audience is already defined. It's a list in Attio that somebody on your team keeps honest: warm inbound, target accounts, signed up and never booked. Finding the people was never the hard part. The round trip is — you pull them out, work them somewhere else, and whatever comes back arrives as a second copy of a person you already had.
Twain closes that loop both ways. It reads an Attio list, researches every person on it, writes the multi-step sequence, and upserts the result back onto the same Attio record. Two decisions make the loop hold, and both are worth stealing whether or not you use Twain: the sync watches list membership instead of update timestamps, and the write-back is an upsert on a unique attribute rather than a create.
Where the import starts
Attio shows up as a lead source in three places. Same picker, same mapping form; what changes is when the import runs and how often.
- Campaign creation. Pick Attio as the source while you set up a new campaign. The list you choose lands in the campaign and research starts on everyone in it.
- Leads import. Import into a campaign you've already built — topping up an audience, or adding a second list to a campaign that's already calibrated.
- Workflow node. Drop an Attio import node into a workflow. It keeps watching the list and hands each new person to the steps after it: add to campaign, generate, export, notify.
Most teams run a one-off import first to judge the output, then move the same list onto a workflow node. That's the version where people arrive already researched, with drafts written, before a rep opens the app. Every person gets a research pass first — signals, a thesis, the reasoning behind the angle — so what your rep reviews is a draft with a stated reason.
Connecting Attio
The first time you pick Attio, Twain sends you through Attio's OAuth screen at app.attio.com. You approve the workspace, and Twain reads back the scopes Attio actually granted.
Twain sends no scope parameter in that request, on purpose. Attio doesn't take scopes per authorization the way most APIs do — an Attio app's scopes are configured on the app itself, in Attio's developer dashboard. Asking at authorization time would be asking the wrong system. And Attio issues no refresh tokens, so there's no expiry to pre-empt and no refresh cycle to fail quietly on a Sunday night. The token works until somebody revokes it in Attio; revoking it costs you one reconnect.
Lists are the selector
The unit of import is one Attio list. Not "all people," not a query you have to write — the list your team already curates, with its own parent object deciding what Twain reads and a fallback to people when the list doesn't name one. You maintain the filter in Attio; Twain reads whatever the list currently holds.
Three practical notes:
- The count in the picker is a best-effort number. Attio has no count endpoint, so Twain scans a bounded slice of the list to show you roughly what you're about to pull. A large list shows as
N+rather than an exact figure. - A one-shot import caps at 25,000 people. Split anything bigger in Attio.
- "No members to import" has two causes. The list is empty, or it's restricted to other people in your Attio workspace. Attio answers both cases identically over its API, so Twain names both instead of guessing at one. If you expected people, share the list with the account you connected.
Map attributes to variables
One rule governs whether a person is importable at all: Twain needs a LinkedIn profile URL or a work email. Either one is enough. A record with neither gets skipped, because there's nothing to research and nowhere to send a message.
The defaults cover a stock Attio workspace — email addresses, name, job title, LinkedIn, company, primary location — and all of them are overridable. Company is a record reference, so Twain resolves it to the company's name and domain instead of handing the writer an id.
Look at the two empty dropdowns in that panel. Auto-mapping leaves First name and Last name alone, and that isn't an oversight: Attio stores a single personal-name value rather than separate first and last fields, so there's no honest default to pick. Map them yourself if your workspace keeps the parts in custom attributes, or leave them and let the name value carry it.
Beyond the defaults, Twain reads text, email, domain, phone, personal name, number, select, status, record reference, and location attributes. Only the first value of a multi-value attribute comes through, and a record reference Twain can't resolve is dropped rather than passed along — a raw UUID in a variable eventually shows up inside a sentence somebody sends.
The Attio-shaped fields are the ones that pay off. A select attribute like Persona or Segment tells the writer which angle to take, so one campaign covers a Head of RevOps and a founder without you building two. A status attribute — lifecycle, pipeline stage, onboarding state — tells the research pass what this person's relationship with you already is. Map those once and they stay attached to the lead, so the day-one email and the day-fourteen follow-up work from the same context. If you want the reason and angle of the campaign settled before any of that runs, Campaign Brief is where you do it.
Why the sync watches membership, not timestamps
Once the list is on a workflow node, Twain re-checks it every two minutes, compares the current membership against the snapshot it stored last time, and works only the difference.
The cheaper implementation is a watermark: ask Attio for records updated since the last poll. We didn't build it that way, because for lists it's wrong.
People leave lists and come back. Somebody drops out of warm inbound in March, and a new signal puts them back in June. That re-entry is exactly the moment you want a rep in their inbox, and a timestamp watermark misses it, because the record itself may not have changed at all. Only its membership did. Diffing membership catches the re-entry. Diffing timestamps catches an edit to a phone number.
If you build these loops yourself, that's the rule worth keeping: when the audience is a list, the list is the event. Watch the set, not the rows.
The controls around it:
- Enroll existing people is a toggle on the node. Leave it off and the first poll only takes a snapshot — nobody currently on the list is imported, and you start receiving people from that moment forward. The node reads Monitoring new people in that state.
- Changing the list resets the snapshot. Twain won't diff one list's membership against a different list's and call the whole new list "new."
- Already-imported people are skipped by their Attio record id, so re-running an import doesn't duplicate anyone.
- Continuous sync tracks up to 20,000 records per list.
Writing the sequences back without duplicates
Here's the second decision. When Twain exports people back to Attio, it upserts them: create-or-update in a single request, matched on a unique Attio attribute, Email addresses by default.
There is no plain create in the Attio export at all, and that's deliberate. Every export is idempotent: run the same one twice, run it after a re-import, run it from a workflow that fires ten times, and one person stays one record. You don't manage the duplicate-contact problem. You don't have one.
The matching attribute gets validated before the first write. If it doesn't exist or isn't unique, the run aborts with the name of the offending attribute and nothing written. A rejection halfway through a 900-lead export would leave you reconciling a half-written workspace by hand.
What lands on the record: the sequence copy one attribute per step with each step's subject line beside it, the research that justified it — signals, anti-signals, thesis, strategy, insights, headline, other roles, location, company info and size, website, and any warnings Twain raised about fit — and the identity fields, always.
Those go into Attio attributes, not notes. A note is where text goes to be forgotten. An attribute is something your team can see on the record, filter on, and build a view around. Where a mapped attribute doesn't exist yet, Twain creates it as a text attribute described "Created by Twain." — text is Attio's only arbitrary-length string type, so a five-step sequence actually fits in it.
Two boundaries. Only generated leads that have messages are exported, and a lead with no value in the matching attribute is skipped and counted for you. And exports land on the record itself: the export form has no option to also drop those people into an Attio list, so if you want a "Twain touched this" list, build it in Attio as a filtered view over one of the attributes Twain writes.
On volume, Attio documents 100 read requests and 25 write requests per second across its API, and returns a Retry-After on a 429. Twain paces reads and writes under that ceiling and honors the header when it appears, so a large export doesn't throttle the workspace your team is trying to work in.
Start with one list — the one you trust most. Connect Attio, drop the import node on a workflow, leave Enroll existing people off so you're only judging fresh arrivals, and read the first five sequences before you turn anything else on.