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:Languages and price
The default template has two sections worth filling in before you enable it:- Languages lists the languages your desk can follow up in
(
Supported languages: English, Spanish.). Erdo writes to and calls each lead in their own language when it is on that list, and in English when it is not, or when it cannot tell. Edit the list to match your team. - Starting price sits in About us. It is the only price Erdo ever gives a lead: when they ask about price, or when it helps them decide to meet. Any other price question (a unit, a discount, a payment plan) is handed to your desk. Until you replace the placeholder, Erdo gives no price at all.
A booking link to your follow-up page
Write the booking link in the playbook as the page’s plain address, for exampleBooking link: https://pages.erdo.ai/p/<page id>. When an email, text or
WhatsApp message Erdo sends carries a link to one of your organization’s own
published pages (on the pages host or on one of your custom domains), Erdo
completes that link for the lead it goes to, the same way the
lead auto-reply does:
?lid=carries the lead’s reference, so the visit shows up against the lead in your page analytics;#ld=carries the lead’s name, email and phone in the URL fragment, so the page greets them and its booking form is already filled in. A browser never sends the fragment to a server, and the page removes it before any analytics records the address.
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: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.
Each stage also carries a label, the stage’s name written out for display
(qualified_out reads “Qualified out”), and a tone Erdo judges from how a
lead in that stage is doing: positive, in_progress, negative or
closed. They are for showing a lead’s stage, for example as a coloured
badge, and never change a decision.
The flow
The read-back also carries aflow: the order your playbook works a lead in,
read out of the same text so it can be drawn as a map. It has four parts:
stages: for each stage, its steps in the order they happen. Each step has awhen(“at once”, “+5 min”, “next day”), anaction, a shortlabel, the stage it moves the lead to (exit_to, ordeskfor a handoff), and the conditions it applies under (only_if). Anactionofmessagemeans your text sends something without naming a channel;movemeans the step only changes the lead’s stage.any_time: the rules that win from any stage, such as a complaint going to the desk or “stop” closing the lead, in order of precedence.conditions: the facts that change which steps happen. Four are Erdo’s own and keep Erdo’s names:reachability(whether the lead has ever answered us),has_phone,text_consentandwithin_working_hours. Any other condition comes from your text, such as which country a phone number is from. Options that lead to the same steps are merged into one.conflicts: places where your text asks for two things that cannot both happen, so you can decide rather than leave it to the engine.
source_found says whether Erdo found that passage word for word. Like the
stages, the flow is drawn for you and never enforced: each decision still reads
the whole text. A playbook saved before flows existed has no flow until it is
saved again.
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 apriority 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 theplaybook_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 inlimits, 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.
Erdo never emails an address again once an email to it has bounced or its owner
has reported one as spam. That refusal does not expire as message history gets
older, and it also stops an email waiting beside a call or text and one whose
bounce arrived after the decision was made. Erdo uses another channel it can
reach the lead on, or hands the lead to the desk when there is none. A new
address the lead gives later is emailed as normal.
Texts need the lead’s yes; calls do not. Erdo texts 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 called and emailed but never texted. The check is
made when the decision is taken and again just before the text goes out, so a
card approved earlier does not text a lead whose row no longer says yes. A lead
who later submits the form again and says yes can be texted from then on. How
the form asked does not matter, only the answer. A call needs no yes on the
form; the do-not-call list and opt-outs still stop one. Check with your counsel
that calling without that yes suits the rules where your leads live.
A stop is a stop on both. A lead who replies STOP to a text is not written
to on WhatsApp, and a lead who taps Stop or replies STOP on WhatsApp is not
texted. A number with no WhatsApp account is a different thing: the lead said
nothing. The WhatsApp message is not sent, and the lead is decided again within
the hour, by text.
When the text says an action is never, a proposal of it is not filed at all,
not even as a card, and the lead’s channel list shows that channel as not
possible. The decision is stored as a wait with the reason. For an email, text,
WhatsApp message or call, the lead is looked at again when the next channel
your playbook allows opens, within the hour at the latest; for a handoff, a wait
or a close, 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_namesigns 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
neverand are not filed at all, because nothing is named to carry them out; thelimitssay so. With one, the playbook decides whether they go on their own or wait for a person, and the delivery step carries them out as the concierge.
What the concierge is told to do
A decision about an email, a text or a call carriesagent_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.
agent_instructions.language. English, Spanish, Portuguese, French, Italian,
German and Russian are covered; any other language opens in English. On a US or
Canadian number the recording notice follows in
the same language. The brief takes over from there.
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.
A figure the lead gave us is not unsupported: what they answered on the form
and what they said on a call, a text or a chat all count, including numbers
they said in words — a lead who said “one to one-point-five million” on a call
can be emailed “1.5M” without a card. When a figure is flagged,
downgrade_cause names it as the draft wrote it, such as $1.5M.
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.
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 a person at the desk has to. It is filed straight to the desk as a task: there is no approval card, nothing expires, and Erdo sends that lead nothing while the handoff is open unless they get in touch. A task nobody knows about is how someone who asked a direct question sits in silence.handoff_alert_recipients is what stops that. Every address on the list is
emailed the moment a handoff is filed. The email is a notification: it says
which lead, what Erdo could not answer, why it became a handoff, and how to
reach them, and it carries the buttons you declare in handoff_alert_links (see
below). The handoff itself is
carried out only when somebody at the desk marks it done (see
Handoffs).
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 still
gets its handoffs in the follow-up queue; nobody is emailed about them.
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.
Buttons in the alert
handoff_alert_links declares the buttons the alert carries, so the person
reading it can open the lead in whatever app your team works leads in. Erdo does
not link anywhere on its own: with no links the alert has no button.
Each link is {label, url, requires}, and you can declare up to three. url is
an absolute https URL with placeholders filled in from the lead:
Every value is escaped as a single URL component, and placeholders can only
appear after the host, so a button always goes to the host you declared. New
lead alerts on a dataset expose
lead_ref too, so one template such as
{{lead_ref|email|phone}} works in both emails.
requires lists fields that must be set for the button to show. For example, a
call button that addresses the lead by id but needs a phone number to be useful
has "requires": ["phone"]. If a placeholder or required field is not set for
a lead, that button is left out of that lead’s alert.
Changing only the alert
PUT /v1/lead-playbook saves the whole playbook: it needs the text, reads it
again, and records a new revision. To change only who is told and which buttons
the email carries, use PUT /v1/lead-playbook/handoff-alert instead. It takes
handoff_alert_recipients and handoff_alert_links, with the same rules as
above. A field you leave out keeps its saved value, and an empty list clears it.
It does not read the playbook text again, does not record a revision, and leaves
every other setting alone. It answers with the playbook, like the full save. An
organization that has not saved a playbook yet gets an error, because nothing is
filing handoffs to alert anybody about.
Working hours
No email and no call goes out outside the playbook’s working hours. Anything decided outside them waits and goes out when the next window opens; it is never failed for being out of hours. A text is the exception: it may go at any hour, because it waits on the lead’s phone until they look, the way an email waits in an inbox. So when a call is due and the lead’s hours are shut, Erdo can text them now and call when their hours open. A text still has to pass the organization’s own quiet hours, when those are turned on, and its 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 underlimits.
A call follows 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 call is different: it rings at the moment it is placed. So for a call, Erdo keeps your days and your hours but reads them where the lead is. A lead in Madrid is called 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:- The timezone recorded when the lead was captured, which is the usual case.
- The country on the lead’s record, where that country keeps one clock.
- The country code of the phone number they gave, if they wrote it with a
+.
The daily contact cap
The daily contact cap bounds how many contacts Erdo makes in any 24 hours: emails, texts, WhatsApp messages and calls, whether they go out on their own or are put in front of a person as a card. It defaults to 200 and can be set from 0 to 500. Each message or call takes one place, so an email sent beside a text or call that is waiting for approval takes a second. A place is spent when the contact actually goes out, so one decided on Friday evening takes Monday’s place rather than Friday’s; one over the cap waits where it is and goes out when a place opens. The cap stops a first run over hundreds of older leads from calling and texting all of them in one morning. Handoffs, waits and closes reach nobody and never count. Neither does your concierge answering a lead who wrote in: replies inside a WhatsApp or SMS conversation, a chat on your site or a phone call are not the follow-up engine and are never held by this cap.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 text and a WhatsApp message count as the same message for this: a lead who
was just texted is not then sent a WhatsApp message, or the other way round,
until the gap has passed.
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:
- For a lead who has never answered, the messages your follow-up schedule lays out go on their own, and the first one past the schedule’s last step is always a card, even when the playbook makes email automatic. Erdo counts the attempts your schedule names (for example: a call, a text, an email, a second call, a second email, and one last email a week later is six). It allows at most eight unanswered messages in a row on its own, however long the schedule. When your playbook has no such schedule, or for a lead who answered once and then went quiet, the limit is four.
- 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.
The sweep
Every 15 minutes Erdo goes through the leads datasets of every organization with an enabled playbook. For each lead it:- Skips test rows, leads captured before the playbook was switched on (see Starting follow-up on a lead), 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. A lead who calls your agent’s number back does not wait either: when the caller ID is that one lead’s number, the call is added to their timeline as soon as it ends and the lead is decided again straight away. A caller ID that is no lead’s, or that two leads share, is linked on the usual schedule.
- 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.
- Evaluates the lead against the playbook and stores the decision.
- Sends an automatic email, files a card, or records a wait or close.
facts holds only language, the language Erdo read the lead
writing in; decisions made before this change keep the budget and other facts
they were stored with.
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 for the desk, and a text or a call that cites none stays a text or a call a person must approve; either way the rationale starts withNo 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, the lead’s own row or what the lead told us in their lead details turns the email into an approval card, with the reason recorded asdowngrade_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.
Two things about the lead’s own past are not figures:
- A date or time from their timeline. When they filled in the form, when
you emailed or called them and the slot of a meeting they booked are known,
however the message writes them:
2026-10-04, “Oct 4”, “4 de octubre” or “12:32”. A date that is not on the timeline and not in the playbook is still flagged, and so is a year on its own, such as “delivery in 2028”. - How long ago something happened. “In the past 18 hours”, “4 days ago”, “hace 4 días” and “nas últimas 18 horas” look back and promise nothing. Anything that looks forward, such as “we’ll call you in 20 minutes” or “within 24 hours”, is a promise about timing and is still checked.
Unreadable characters
A message or call brief is checked for characters written as codes, such as\u00e9 where é belongs. Erdo reads a code back into its character before
the decision is stored. When a code names no character, an automatic email,
text or call becomes an approval card whose downgrade_cause reads “The text
contains unreadable characters”, and an email alongside a text or a call is
not sent. The same check runs again just before anything is sent.
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 or call — 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
supersededand nothing is sent. The row says which of those it was, inerror, 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_refnames the message or the call that really happened. If the concierge has been archived or unlinked, the actionfailedand says so — Erdo never sends as nobody. - A handoff is not an approval card. See Handoffs.
- You can take an approval back until the moment it is carried out:
POST /v1/datasets/{slug}/leads/{lead}/next-actions/undoputs 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.
An email alongside a text or a call
When the playbook makes a text or a call wait for a person, a decision to call a lead files a card. A text or a call the playbook lets go on its own needs none of what follows: it reaches the lead by itself. A gated one 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.
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.
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.
Resuming a held or closed lead
A hold or a close can be ended early, so Erdo works the lead again: the desk finished with a snoozed lead before the date it picked, or stopped one by mistake. Resuming works on the lead’s current decision when it is a hold whose time is still running, or a close, whether the desk or Erdo recorded it.decided_by_external_ref is your own name for the
person, as on the hold and close, and is stored on the decision as
resumed_by_external_ref. The response is the hold or close itself, now with
revisit_at and resumed_at set to the moment it was resumed and resumed_by
set to the account the API key belongs to. Resuming records no new decision:
Erdo decides for the lead on its next pass, within about fifteen minutes, and
that decision becomes the lead’s current one. If the lead asked not to be
contacted, that decision will usually be another close.
The call is refused with the error code failed_precondition and the message
This lead is not snoozed or stopped. when the lead has no decision, when its
current decision is anything other than a hold or a close, when a hold’s time
has already run out, or when it was already resumed.
Starting follow-up on a lead
Switching the playbook on does not reach back over every lead you ever captured. Erdo works a lead by itself only when it was captured after the playbook was last switched on (enabled_at on the playbook). Leads from before then, leads
whose arrival time cannot be read, and test traffic are left alone until
somebody starts them.
Start brings one of those leads in. Erdo records the start as a decision,
contacting nobody, and decides the lead’s next step straight away from the
playbook, as it would for a lead that just arrived. A start is refused when the
playbook is switched off, or when Erdo already has the lead (use Resume for a
snoozed or stopped one).
Starting a lead over
"reset": true with kind: "start" starts the lead over, which is useful when
you test a playbook on your own contact details. Anything open for the lead is
withdrawn, its card included, and from that moment Erdo reads the lead afresh:
- its earlier decisions and the desk’s refusals are not read;
- timeline entries from before the reset are not read;
- answers the lead gave in a call, chat or message before the reset are not read, while their form answers are;
- the lead counts as captured at the reset, so the new-lead grace and every step your playbook times from capture start again.
GET /v1/datasets/{slug}/leads/{lead}/next-actions)
carries follow_up: state is off, not_started (Erdo will not reach this
lead by itself; start it), waiting (Erdo will decide it on its own soon),
paused (snoozed or stopped) or active, with enabled_at and, after a
reset, reset_at.
Handoffs
A handoff is accepted the moment Erdo files it. It lands on statusapproved
with no approval request, the desk is emailed (see
Telling the desk a lead needs a person),
and it stays open with the desk until somebody closes it. Nothing automatic
ever carries a handoff out. The desk closes it with one of two answers:
- Done: somebody dealt with the lead. The handoff becomes
executed, withdecided_by,decided_atandexecuted_atset andexecution_refaccepted. Erdo then leaves the lead alone until they get in touch again. - Not needed: the task did not need doing. The handoff becomes
rejected, attributed the same way. Erdo leaves the lead alone for a week, or less if they get in touch first.
decision is done or not_needed. action_id names the exact handoff you
are answering (omit it to answer the lead’s current decision), note is kept
on the decision, and decided_by_external_ref is your own name for the person,
as on the hold and close. The call answers the decision as it now stands. It is
refused with the error code failed_precondition when the lead’s decision is
not an open handoff, and the message says what it is instead: already marked done or not needed, replaced by
a newer decision, or not a handoff at all.
While a handoff is open, Erdo does not decide anything else for that lead
unless the lead gets in touch. If they do, Erdo decides again and the new
decision replaces the open handoff.
A handoff cannot be taken back with the undo call: there is no approval behind
it. Mark it not needed instead. Handoffs filed as approval cards before
September 2026 are still answered on their card, and answering “Mark done”
there marks them done.
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 arecapture, 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 call follows. A text follows no working hours. 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 itscanonical_lead_id UUID or its 22-character lead
reference, as on lead identity. The dataset is addressed by
slug.
Save and enable a playbook:
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:
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, closing or resuming 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
--json for the raw response.

