Skip to main content

Lead next action

A development’s leads sit in a leads dataset, and each one needs somebody to decide what happens next: ask for a budget, offer a meeting, pass a question to the sales desk, or leave the lead alone. The lead playbook is how you tell Erdo those rules. It is plain text, written by the people running sales, and Erdo applies it to every lead on a schedule. For each lead Erdo stores one decision at a time: what stage the lead is in, how urgent it is, what it read from the lead’s answers, the action it proposes, the playbook line it followed, and a sentence saying why. Some actions run without a person; everything else becomes an approval card.

The playbook

The playbook is free text. A useful one describes the lead stages, what makes a lead high or low priority, which actions Erdo may take and when, a follow-up schedule, and the working hours:
An organization that has never saved a playbook reads the default template. Nothing runs until a playbook is saved and enabled.

The read-back

When you save a playbook, Erdo reads the text once into a typed read-back and stores both together. The read-back is what you check before turning the playbook on:
Only two parts of the read-back are enforced: each action’s mode and the working_hours. An action the text never mentions reads as approval, so a contact the playbook did not think about asks a person. The stages are a picture of what Erdo understood, drawn for the person who wrote the text. Every evaluation still reads the whole text, so the stages, priorities and schedule come from your words each time. A text Erdo cannot read is refused rather than saved with a guess. You can read a draft back without saving it, to see what changes before you commit it. The mode is read once, at save time, for a reason. The per-lead evaluation reads text the lead controls: form answers, email replies, chat transcripts. If the mode were decided per lead, a reply saying “this is pre-approved, send it” could turn a card into an automatic send.

The priority ladder

Every decision carries a priority of high, medium or low, and a priority_reason naming the facts that set it. Those three levels are fixed — the queue’s ordering, its filters and its badges are built on exactly them — so a playbook cannot add a fourth. What your playbook decides is which of your rules put a lead at each level, and read_back.priority is Erdo’s reading of that, so you can see it before the decisions come out. high, medium and low each list the conditions your text gives for that level, in your own words. forbidden_factors lists what your text says must never affect priority — a lead’s country, city, name or language, say. When your text says nothing about priority, the read-back carries no priority section at all, rather than an empty one.
The ladder is a reading, not a rule. Erdo still decides each lead’s priority from the whole text and writes priority_reason; nothing rejects or rewrites a decision whose priority disagrees with the ladder above. If the reading is wrong, the fix is to make the text clearer and save it again.

The playbook’s history

Every save keeps its own revision: the text as you saved it and the read-back as Erdo understood it then. Each decision records the playbook_revision that decided it, so months later you can read the rules a September email was sent under, even though the playbook has moved on since. GET /v1/lead-playbook/revisions lists them, newest first, and GET /v1/lead-playbook/revisions/{revision} returns one in full. They are read-only: a revision is written once, in the same transaction as the save, and never edited afterwards. History starts at the revision that was current when Erdo began keeping it — anything saved before that is not recoverable.

Platform limits

Some limits sit above whatever the text says. Each one the platform applied is listed in limits, so you can tell the rules you wrote from the ones Erdo imposed. An email also becomes a card when the lead has no email address or when the development has no verified sending domain. Texts and calls need the lead’s yes. Erdo texts or calls a lead only when the form they submitted asked whether they may be called and texted, and they said yes (consent_given is true on their row). A lead who said no, and a lead whose form never asked, are emailed instead, or handed to the desk when Erdo has no email address for them. The check is made when the decision is taken and again just before the text or call goes out, so a card approved earlier does not ring a lead whose row no longer says yes. A lead who later submits the form again and says yes can be texted and called from then on. How the form asked does not matter, only the answer. When the text says an action is never, a proposal of it is not filed at all, not even as a card. The decision is stored as a wait with the reason, and the lead is looked at again in seven days.

The concierge

A playbook can name one concierge: the voice agent that already answers this development’s website widget, its phone and its texts. Link one and the same person your leads have been talking to is who writes their follow-ups. Three things change when a concierge is linked:
  • Every draft is written as that concierge. Its persona — the same text the widget and the SMS replies speak from — says who is writing and how they sound, and the playbook’s signature_name signs the email. The playbook still decides what may be said; the persona never overrides it.
  • Drafts are grounded in what the development has published. Before each decision Erdo reads the organization’s public knowledge for what this lead has been asking about, so a follow-up can answer a question from last week’s chat instead of repeating the playbook. Facts taken from there are not treated as unsupported figures. A knowledge outage costs the grounding, never the decision.
  • Texts and calls become possible to propose. Without a concierge they read back as never and are not filed at all, because nothing is named to carry them out; the limits say so. They are still approval-gated with one, and approving one records the decision — status approved — which the delivery step then carries out as the concierge.

What the concierge is told to do

A decision about an email, a text or a call carries agent_instructions in its action_input: an objective saying what the action is for, and instructions saying what to say, what not to say, and in what register. For a call that block is the call brief. For a text the decision also carries sms.body, the message as the lead would receive it — plain text, at most 320 characters; a longer draft is dropped rather than trimmed and the downgrade_cause says so.
A text or a call carries no handoff block at all: it is not work for the desk, and a card that showed both a desk task and a finished message said two contradictory things about one decision. handoff.summary belongs to a genuine handoff, where a person deals with the lead personally; the instructions are addressed to the concierge that carries a text or a call out. They go through the same figure check as an email body, so an automatic email whose brief states a price the playbook and the published material do not becomes a card, and a text card whose brief does says so in its downgrade_cause. The approval card shows the draft and the brief. Link a concierge by passing its agent_id when you save the playbook. List the organization’s concierges with GET /v1/voice/agents or erdo voice agents. Unlike enabled and daily_contact_cap, agent_id is not kept when you leave it out: a save with no agent_id clears the link.

The name a lead sees

signature_name is the name your leads meet: a follow-up email is signed and sent as it, and a call brief opens with it. It is separate from the concierge’s own name because the two are chosen for different readers. A voice agent’s name is the label you pick to tell one agent from another in a list — “Outbound Re-engagement Agent” is useful there and odd to receive an email from — and the persona written for that agent often introduces it to leads by a different name again. Set signature_name to the name the concierge introduces itself by, and the email signature, the From header and the call brief all agree. Leave it empty and nothing changes from how the engine has always behaved: the concierge’s own name signs the draft, and with no concierge linked the draft is unsigned and the email goes out under the organization’s sending name. Unlike agent_id, signature_name is kept when you leave it out, like enabled and daily_contact_cap. Clearing a concierge link is a deliberate choice a picker offers; a name is free text, and a client that does not know the field must not be able to strip the name a development signs its mail with. Send an empty string to clear it back to the concierge’s name. The name is at most 120 characters and must be a single line — it becomes an email’s From header.
Each saved revision records the signature_name in force when it was written, so a decision that cites a revision can still say which name it went out under. GET /v1/lead-playbook returns both agent_id (what was saved) and agent (what it resolves to now). They are the same thing except when the concierge has been archived, where agent_id is still set and agent is null — that pair is how you can tell an archived concierge from none at all. An archived concierge stops texts and calls immediately, without re-saving the playbook. Everything about a playbook with no concierge works exactly as it always has: email, wait, close and handoff are unchanged.

Telling the desk a lead needs a person

A handoff is Erdo saying it cannot answer this one — so nothing reaches the lead, and the decision waits as an approval card. A card nobody opens expires after three days, and Erdo then leaves that lead alone for a week. Someone who asked a direct question can therefore sit in silence for ten days while nobody at the desk knows the question was asked. handoff_alert_recipients is what stops that. Every address on the list is emailed the moment a handoff is filed — not when it is approved, because approving means somebody has already found the card, and finding it is the problem. The email says which lead, what Erdo could not answer, why it became a handoff, and how to reach them, and it links straight to the follow-up queue. An empty list means nobody is told. That is the default and it is a real setting, not a gap: Erdo has no fallback audience for this and never emails the organization’s members instead. A development that has not filled this in gets the behaviour it has always had, where the card waits in the queue until somebody opens it. Addresses are lowercased, de-duplicated and sorted, and at most ten people can be on the list. An entry that is not an email address is refused and the save does nothing, rather than being dropped quietly — silently discarding a typo is how somebody comes to believe they are on the alert list when they are not. Like signature_name, the list is kept when you leave the field out, so a client that does not know about it cannot take a development’s desk off its own alert list. Send an empty list to stop alerting anybody.
Unlike every other playbook setting, the list is not frozen into each saved revision. Who gets told is a delivery detail rather than something a decision was made under, so it is read when the alert is sent: change the list and the next handoff — including ones already waiting — goes to the new list, with no need to re-save the playbook. The alert is an internal message and is treated as one. It does not count against the daily contact cap, it does not wait for working hours, and it is never signed as the concierge — all three are promises about what reaches a lead, and this reaches your own staff.

Working hours

Nothing Erdo sends goes out outside the playbook’s working hours — an email, a text or a call. Anything decided outside them waits and goes out when the next window opens; it is never failed for being out of hours. A text or a call also has to pass the organization’s own quiet hours and consent rules, and a message those hold back waits in the same way. When the text states no working hours Erdo can read, the default is Monday to Saturday, 08:00 to 19:00, New York time, and the read-back lists that under limits.

A text and a call follow the lead’s own clock

Your working hours are your development’s — “Monday to Saturday, 08:00 to 19:00, New York time”. An email is sent in those hours, because an email waits in an inbox until the lead opens it. A phone is different: it rings at the moment the message is sent. So for a text and a call, Erdo keeps your days and your hours but reads them where the lead is. A lead in Madrid is texted between 08:00 and 19:00 Madrid time, not between 08:00 and 19:00 in New York — which would have reached them at two in the morning. You do not configure this and there is nothing to set: it follows from the hours you already wrote. Erdo works out where a lead is from the lead’s own record, and never from their name or the language they wrote in:
  1. The timezone recorded when the lead was captured, which is the usual case.
  2. The country on the lead’s record, where that country keeps one clock.
  3. The country code of the phone number they gave, if they wrote it with a +.
When none of those answers, your own working hours are used unchanged, and the decision says so in as many words — so a card for a call tells you which clock it was timed in, including when that clock is yours because Erdo could not tell where the lead is.

The daily contact cap

The daily contact cap bounds how many emails Erdo sends, or puts in front of a person as email cards, in any 24 hours. It defaults to 40 and can be set from 0 to 500. A slot is spent when the email actually goes out, so an email decided on Friday evening takes Monday’s slot rather than Friday’s; one over the cap waits where it is and goes out when a slot opens. The cap stops a first run over hundreds of older leads from emailing all of them in one morning. Handoff cards do not count toward it.

How often one lead is contacted

The first thing Erdo tries to find out about a new lead is whether they can be reached at all. A lead who has never answered on any channel — no reply, no call, no chat, no text, no booking — is unconfirmed, and is worked harder and faster, close to when they were captured. The first answer of any kind, on any channel, makes them confirmed for good, and the slower, ordinary pace takes over. Erdo keeps a gap per channel, so an email this morning and a text this afternoon are both possible, while two emails inside the email gap are not: A proposal inside a channel’s gap is stored as a wait until that channel reopens. A lead who responded since our last message on a channel can always be answered at once. Your playbook can set any of these. Write them in plain language — “while a new lead has not answered, email at most every two hours and text at most every hour; once they reply, never email twice in the same week; contact a new lead thirty minutes after they come in” — and Erdo reads them back to you before any lead is touched. Erdo will not go below its own minimums (30 minutes between emails, an hour between texts, three hours between calls, five minutes after a lead is captured); where your text asks for less, the read-back says so and the minimum applies. Five minutes after capture is also the default, so a playbook that says nothing about it gets in front of a new lead as soon as their record has finished being written. Two limits hold whatever the playbook says:
  • After four messages in a row with no response, another email is always a card, even when the playbook makes email automatic. This does not change while a lead is unconfirmed: four unanswered messages are an answer.
  • Working hours, consent, quiet hours, opt-outs and do-not-call are untouched by any of this. Contacting sooner never means contacting outside them, and texts and calls are still always checked by a person.
How many follow-ups to send, in what order, and when to give up belong in the playbook’s follow-up schedule.

The sweep

Every 15 minutes Erdo goes through the leads datasets of every organization with an enabled playbook. For each lead it:
  1. Skips test rows, and leads captured in the last 5 minutes, so a capture has finished writing the lead’s record before it is read. Your playbook can set that grace, up to a week; Erdo will not go under five minutes. A new lead does not wait for the next sweep — a capture wakes Erdo directly, and the lead is decided as soon as its grace is up.
  2. Decides whether the lead needs a new decision. A lead is evaluated when it has never been evaluated, when its row or timeline changed since the last decision, or when the last decision’s revisit time has passed. Nothing else triggers a model call.
  3. Evaluates the lead against the playbook and stores the decision.
  4. Sends an automatic email, files a card, or records a wait or close.
One sweep makes at most 200 evaluations across all organizations. Leads never evaluated go first, then the ones looked at longest ago, and the rest wait for the next sweep. Revisit times keep a quiet lead moving without re-reading it every 15 minutes:

Rule citation

An automatic email must quote the playbook line it follows, and Erdo checks that the quote really occurs in the text. Case, line wrapping and list markers do not matter; a paraphrase or an invented rule counts as no rule. The check exists because every evaluation has to propose something. Where the playbook is silent, a model would otherwise fill the gap from general sales sense, and an automatic email that follows no rule you wrote is exactly what the playbook is meant to prevent. So an email that cites no real line becomes a handoff card, and a text or a call that cites none stays a text or a call a person must approve; either way the rationale starts with No playbook rule was cited:. Gaps in the text therefore reach a person as cards, and the desk adds a line to the playbook when the situation will come up again. A wait or a close needs no citation, because neither contacts anyone.

The figure check

An automatic email is checked for figures: prices, dates, times, unit numbers, any number. A figure that does not appear in the playbook, the development’s name or the lead’s own row turns the email into an approval card, with the reason recorded as downgrade_cause. Links are ignored. The playbook is the only source of facts an automatic email may state, so a delivery date or a price the model supplied is checked by a person before it reaches a lead.

Approval cards

An action that needs a person is filed as an ordinary approval request, with the lead as its subject. It appears in the approvals queue with the message, the brief or the desk task in full and the rationale as its context.
  • Approving records the decision; it does not send. Every approved card — email, text, call or handoff — lands on status approved, and a delivery step running every two minutes carries it out. It sends exactly what the card showed: nothing is rewritten between the card and the send.
  • Before it goes out, the decision is checked against the lead as it is now. If the lead answered you, was closed or held by the desk, or a newer decision was filed, the action is superseded and nothing is sent. The row says which of those it was, in error, and a decision somebody had approved says so — an approval that does not go out is never dropped silently. A column changing on the lead’s record is not one of these reasons: it makes Erdo look at the lead again, and it does not cancel a step you already approved.
  • A text or a call is carried out by the concierge, from its own number, subject to the organization’s consent, opt-out, do-not-call and quiet-hours rules. execution_ref names the message or the call that really happened. If the concierge has been archived or unlinked, the action failed and says so — Erdo never sends as nobody.
  • Approving a handoff card records that the desk has taken it. Nothing is sent.
  • You can take an approval back until the moment it is carried out: POST /v1/datasets/{slug}/leads/{lead}/next-actions/undo puts the decision back in front of a person and records who took it back. If the action has already gone out the call is refused rather than pretending to recall it.
  • Rejecting a text, a call or an email shuts that one channel for this lead for 7 days. Erdo decides again on the next sweep and goes on with the playbook’s other channels, so turning down a text does not also stop the email the playbook sends next. A reply from the lead lifts it early.
  • Rejecting a desk task, or letting any card expire after 72 hours, stops Erdo proposing that lead again for 7 days, unless something about the lead changes first: a reply, a call, a new capture, or an edit to its row.
  • Editing the playbook withdraws cards nobody has answered yet and decides those leads again. An approved card stays approved: it goes out under the playbook’s current hours and gaps, unless the edit now forbids that kind of contact altogether.
  • A newer decision withdraws the older card, so an email that a later evaluation replaced can no longer be approved.
Standing approval policies never approve these cards. The saved playbook already decided they need a person.

An email alongside a text or a call

A text and a call always wait for a person. An email does not. So a decision to call a lead used to file a card and leave that lead with nothing at all until somebody at the desk acted on it — which may be three days, since a card expires after 72 hours, and then another week of quiet. A decision that needs a person can now carry an email that goes out at once beside it. Erdo writes it in the same evaluation that chose the call, sends it immediately, and the card still waits for you. The lead hears from us within minutes of arriving; the phone call still has a person in front of it. It is one decision, not two. There is still exactly one open suggestion per lead, one card, and one row in the lead’s history — the email rides on it.

Whether your playbook sends one

Write it in your playbook text and Erdo reads it back:
  • “When you decide to call a lead, email them the booking link as well” turns it on.
  • “Do not email a lead you are also calling” turns it off.
  • Say nothing, and Erdo sends one when your playbook already lets it email a lead without approval, and never otherwise. An unanswered call leaves the lead nothing; an email leaves something they can read and a link they can use. But if you have not given Erdo permission to email a lead unattended, it does not get that permission by attaching the email to something else.
The read-back shows the answer, and says so in limits when your text asked for one your playbook does not allow:

What it obeys

Exactly what an automatic email obeys, and in the same words: your daily contact cap, the gap Erdo keeps between two emails to one lead, the ceiling on unanswered messages, your working hours, your verified sending domain, the lead’s consent and opt-out, and the check that stops Erdo stating a price or a date your playbook does not. If any of those says no, the card is still filed — it just says on it that the lead has not heard from us.

On the card

The card names the call you are approving and says, above the brief, whether the lead has already been emailed — with the subject and the words that went. You are approving the call, not the email; the email has gone and cannot be recalled. A card that says the email has not gone yet is telling you the lead is still waiting in silence.

What it will not do

  • It never goes twice. Approving the call carries out the call; the email that already went does not go again, and one that had not gone is dropped — the call is reaching them instead.
  • Undo does not unsend it. Taking an approval back puts the call in front of a person again; the email the lead already read stays on the record, and the new card still shows it.
  • A replaced decision does not pretend it did nothing. If a reply arrives and a newer decision supersedes this one, an email that already went stays on the record and the concierge is told about it before it calls. One that had not gone is dropped.
Read it back on any decision as accompanying_email:
status is pending (drafted, not sent yet, with error saying what it is waiting for), sending, sent, failed (a rule said no permanently) or skipped (the decision moved on first). It is absent on every decision that carries none.

Hold and close

The sales desk works leads outside Erdo too: calls from its own phones, emails from a colleague’s inbox. Two manual decisions tell Erdo so:
  • Hold means the desk is handling this lead. It lasts seven days by default, at most 180, and ends early when the lead gets in touch again.
  • Close means stop working this lead. Erdo suggests nothing more until the lead gets in touch again.
Both replace the lead’s open suggestion and withdraw any card it filed, so Erdo does not email somebody the desk is already talking to. Both are stored as decisions, so the lead’s history shows who held or closed it and why.

Statuses

The timeline and the dry run

The timeline is everything the evaluation reads about one lead: the dataset row, the lead’s email addresses and phone numbers, and every entry in time order. Entry kinds are capture, email, email_reply, sms, call, chat, booking and suggestion. Every entry is dated when the thing happened, so a booking carries the moment the lead picked a time and names the meeting itself in its summary — the meeting is also given on its own as the next or last meeting in the timing facts. It also carries the timing facts a schedule rule is matched on, computed by the platform rather than by the model: days since capture, days since our last message and since the lead’s last reply, how many of our messages in a row went unanswered, the next or last meeting, and whether it is now inside working hours. Two readings of the hours are given: the development’s, which an email follows, and phone_hours, the same hours read where the lead is, which a text and a call follow. lead_zone beside them says which timezone that is and how Erdo worked it out — or that it could not, and your own hours are being used. A source that could not be read is listed under unavailable, and the evaluation is told that source is unknown. The dry run evaluates one lead now and returns the decision with the read-back and timeline it used. Nothing is stored and nothing is sent. Pass a draft playbook to see what a change would do on a real lead before you save it; without one, the dry run uses the saved playbook and refuses when none is saved.

Permissions

Reading the playbook, the suggestions, a timeline and the dry run take organization membership. Saving the playbook takes an organization admin. Scoped API keys, the per-end-user credentials, cannot save the playbook or hold and close leads.

REST API

A lead is addressed by its canonical_lead_id UUID or its 22-character lead reference, as on lead identity. The dataset is addressed by slug. Save and enable a playbook:
An agent_id that is not a live concierge of your organization is refused with 400 and a message saying which of the three things is wrong: the id is malformed, the concierge belongs to another organization, or it has been archived. List the cards waiting for a person:
Hold a lead the desk is calling:
The response is the stored decision, with action_kind hold, status recorded and revisit_at set to the end of the hold. Try a draft playbook on one lead:

MCP tools

MCP clients can read and try the playbook, but cannot change what Erdo does to leads: Saving or enabling the playbook, and holding or closing a lead, deliberately have no MCP tool. Enabling a playbook that marks email automatic lets Erdo email real people without anyone looking, and a hold or close is the desk’s judgement about somebody it is talking to. A person makes those decisions over REST or the CLI.

CLI

Every command takes --json for the raw response.