One sequence, multiple channels: email, LinkedIn steps, and calls together.
Reply.io builds a single sequence that mixes email with LinkedIn steps and call tasks rather than treating each channel as a separate campaign. Your agent resolves or creates the sequence, links a sending mailbox, enrolls the contacts, then stops and waits for your approval before it starts sending.
Reply.io is activation for a multichannel cadence. Sourcing and enrichment fill the contact list before it goes near a sequence.
validate the list before it goes into a live sequence
personalisation across the email and LinkedIn steps
LinkedIn URLs feed the LinkedIn steps in the same sequence
replies land on the record automatically
A skill is a whole pipeline your agent already knows. These ones call Reply.io as part of the run.
use whenyou have the list and now you need a cadence built, loaded and ready, with nothing going out until you say so
use whenone channel is not getting answers and you want a single cadence where a contact who ignores the email meets a LinkedIn touch and then a call
use whena campaign is loaded and ready, and you want to know the mailboxes and the domain behind it are fit to send before you press start
use whencampaigns are running or finished across one or more sequencers and nobody has looked at which ones earn replies and which only use up the list
Every tool ships with a written playbook, and the agent loads it before the first call. Auth, rate limits, what each call costs, which actions need your approval, and the mistakes worth avoiding. It is the difference between an agent that knows the tool and one that guesses at it.
Read the Reply.io docs →HOW in lib/reply_io.py. Docs cached at reference/docs/reply_io/raw/endpoints.md.
https://api.reply.io (every path sits under /v3) · Auth: Authorization: Bearer <key> (env REPLY_IO_API_KEY; never hardcode). Get the key from the Reply dashboard: Settings → API Key.start_sequence(id) begins real outbound sending. add_contacts_to_sequence into a running sequence puts mail in flight. Approval-gate both: build the sequence and enroll into a paused state, pilot, confirm, then start.Contacts: list_contacts, get_contact, create_contact, update_contact, search_contacts. Contact lists: list_contact_lists, add_contacts_to_list. Sequences: list_sequences, get_sequence, create_sequence, start_sequence, pause_sequence, get_sequence_stats, list_sequence_steps. Sequence contacts: list_sequence_contacts, add_contacts_to_sequence, remove_contacts_from_sequence, set_contacts_status_in_sequence, set_contacts_replied. Email accounts: list_email_accounts, list_sequence_email_accounts, link_email_account_to_sequence. Identity: whoami. Else → generic request().
Activation layer: resolve/create a sequence → link mailboxes → create or import validated contacts → add_contacts_to_sequence → review → start_sequence. Replies feed back through get_sequence_stats and set_contacts_replied.
Field-shape note: these are vendor-native operational notes. The client returns the raw vendor JSON and uses the method names in this file — read field shapes accordingly (no normalized-wrapper /
result.data.prefix).
Activation order: resolve/create sequence -> link sending mailboxes -> create or import contacts -> enroll via add_contacts_to_sequence -> start_sequence -> monitor via get_sequence_stats. Always resolve the sequence ID before any write.
Gotchas (vendor-native):
domain:verb (e.g. contacts:read, sequences:operate). A key missing sequences:operate can read sequences but cannot enroll or start anyone — the #1 confusing 403.add_contacts_to_sequence/remove_contacts_from_sequence accept up to 10,000 contact ids; set_contacts_status_in_sequence/set_contacts_replied accept up to 100. Over the cap the adapter raises rather than trimming.top (page size, default 25, max 1000) + skip. top > 1000 is rejected, not clamped — a clamp would make a paging loop silently skip records.update_contact is PATCH: omitted fields keep their current value, unlike a PUT.get_sequence_stats takes either a dateRangePreset (lastWeek/lastMonth/lastYear/allTime) or an explicit from/to, never both.create_sequence requires a name AND at least one step — a name-only create is rejected.set_contacts_replied marks a contact replied and that finishes them in the sequence.problem+json (title, status, detail, code, errors[]); a 401 has an empty body — check WWW-Authenticate instead.Retry-After.