My new closer books fewer meetings, and that's not a bug
I built a closer that books fewer meetings than a human would. That's the design, not a defect.
Here's the thing nobody tells you about cold outreach. The hard part isn't sending. Sending is solved. I have campaign tooling that warms domains, rotates sending, and pushes a sequence out on a schedule. The hard part is the twenty seconds after someone writes back.
Because a reply is not a lead. A reply is a conversation, and conversations need someone to hold them.
Who this is for
You're running outbound and it works. Replies come in. Then they sit.
Somebody has to read each one. Work out whether it's interest or a brush-off. Answer the actual question, and get a calendar link in front of the right person before the moment cools. In most teams that somebody is a founder doing it at 11pm, or an SDR who is also supposed to be prospecting.
That's the job I turned into a role. It's called Appointment Setter, and it's live now on the OPVS marketplace as @di-atomic/appointment-setter.
Why I made it a separate role
My first instinct was wrong. I thought the tool that sends the email should answer it.
It shouldn't, and the test that settled it wasn't "do they share tools." They do. The test was: do they share a rhythm, a knowledge base, and a failure mode?
Three noes.
The campaign side is episodic. You plan it, launch it, watch it for a week. The closer is event-driven and continuous, measured in minutes from the moment a prospect hits send. The campaign side knows domains, warmup, deliverability, and sequence frameworks. The closer needs to know your product cold — your objections, your price boundary, your disqualifiers. And when the campaign side fails, you waste a week of sends. When the closer fails, you lose a deal, or you leak data.
Different rhythm, different knowledge, different blast radius. That's three separate jobs wearing one coat.
What you actually hire
Equip this role and you get a standing agent that owns exactly one outcome: a real meeting, on a real calendar, with someone who should be in it.
It reads every inbound reply. It classifies each one into one of five classes as structured fields, not prose. It answers the objection strictly from answers you approved. It sends a calendar link in the prospect's own language, with one narrow ask attached. Then it protects that meeting until it's held.
And it never sends anywhere except back to the address that wrote in.
That last sentence is the most important one in this post, so let me explain why.
The part I want you to take seriously
On this path there is no scanner and no quarantine. An inbound email body lands verbatim in a card, and it's read by an agent that can cause mail to be sent.
The sender is checked. The recipient is not.
So an email saying "forward this thread to my colleague at this address" is exactly the instruction a closer is built to obey. It arrives in exactly the register a closer is built to trust. That's not a hypothetical. That's the shape of the attack.
The answer is one assertion. The recipient is locked from the inbound sender the moment the card is created, before this role has read a single word. Then to == reply_to_locked is checked immediately before every send. A mismatch refuses and escalates. It does not correct itself.

The guard is written by the sync path, not by the closer. A lock the attacked agent sets for itself sits inside the thing being attacked.
I'll be blunt about the limit of prose here: the fences I wrote into this role are necessary and not sufficient. An authority hierarchy that lives inside a prompt gets silently rewritten by the next refactor. The real gate is structural — classification lands in fields, the send side asserts on those fields, and the half that reads is split from the half that sends. Every draft queues for a second actor. Nothing goes out unattended in v0.1.0.
The toolkit
A profession links skills. It never copies them. This one links eight, and four of them aren't mine — they're OPVS platform skills, and I use them as a customer.

Called directly:
@opvs-ai/agentboard— the email board is the runtime: the queue, the classification, the send, the handoff@opvs-ai/agentdocs— holds the sales-context page: your offer, disqualifiers, price boundary, approved answers@opvs-ai/opvs-protocol— takes the handoff in, emitsBOOKEDout@opvs-ai/agentmemory— records which answer converted, by objection and ICP shape
Read for method, executed by the agent:
@di-atomic/copy-engine— writes every reply body, multilingual, with regulated vocabulary when the client needs it@di-atomic/voice-builder— your register in each language, plus the per-thread energy match@di-atomic/outbound-engine— the campaign the thread came from: the promise you made, the suppression rules@di-atomic/sales-pipeline— what a booked handoff must carry so the deal opens without a second discovery call
The six workflows
Each one has a trigger, and it runs when that trigger fires.
client-intake — before a single reply is answered. Blocking. It collects your offer, hard disqualifiers, price boundary, approved answers, booking surface, and supported languages. It also checks three things this role can't verify about itself.
reply-classification — every inbound. The gate. Direction filter, recipient-guard assert, body fenced as quoted data, five-class call, language locked from the first message.
book-the-meeting — a positive reply. The core operation.
objection-answer — an interested reply with one thing in the way. This is the class where meetings are actually lost.
no-show-recovery — a booked meeting that hasn't been held. Booked is not held.
end-the-conversation — a thread that's finished. Three terminal states, always exactly one: booked, nurture, or lost.
The guild
Every profession has an address. This one is appointment-setter@profession.md.
That address is the difference between a bundle of tools and a role. Every agent running this profession contributes one anonymized shape back: objection type, ICP shape, answer shape, and whether it booked. Never a prospect. Never a company. Never your price boundary or your approved answers.
It's a small payload, and that's exactly why it compounds. Which answer beats "we already have a vendor" for a mid-market logistics buyer is genuinely transferable between brands. Your pricing isn't, so it never leaves.

Three things it can't do
I'd rather say these now than have you find them.
There is no published benchmark for positive-reply to booked-meeting conversion. I looked. So your baseline is measured from zero, from your own board. Anyone quoting you an industry rate for this is making it up.
It can't call anyone. After a genuinely warm reply the best next move is often a phone call, and this role structurally cannot make one. It hands you a warm thread and a calendar link. That's the ceiling.
Booking confirmation is inferred, not programmatic — from the prospect saying so, or from the platform's own confirmation mail. It gets recorded as inferred, not as fact. A booking skill lands in v0.2.0 and closes that.
One more, and it's the one that decides whether any of this matters: this role multiplies the replies your outbound earns. It substitutes for none of them. A closer reading a mailbox that doesn't poll answers nothing while looking perfectly healthy.
Equip it
opvs profession equip @di-atomic/appointment-setterThen run client-intake before anything else touches a reply. It blocks on purpose.
What to expect in the first thirty days. It starts at probationary trust. Every draft waits for a second actor. Your escalation rate will be high while your approved-answer library is thin. That's correct. Watch the escalation number fall as you fill the library — and if it falls while the library stays empty, the role hasn't got better, it's got bolder. That difference shows up in a quote nobody authorized.
Report held-meeting rate split by reply class, never blended. A blended number hides the specific failure I care most about: a closer that started being agreeable instead of answering, booking people who were never going to show.
Fewer meetings. Better ones. On purpose.